Compare commits

...

68 commits

Author SHA1 Message Date
Friendika fbd2b29089 pointer to new project 2010-11-07 02:44:10 -08:00
Mike Macgirvin 26f97b8284 like,dislike for photos (still needs a bit of tweaking) 2010-11-02 16:24:23 -07:00
Mike Macgirvin d8630dbdd8 infrastructure for swat0 (#fsw) 2010-11-01 23:42:26 -07:00
Mike Macgirvin 36a77c6db2 build feeds rather than template them 2010-11-01 17:56:36 -07:00
Mike Macgirvin 4f4d6bace6 add rel=mentioned links for tagged persons 2010-10-31 21:57:30 -07:00
Mike Macgirvin b376f21533 notify folks who have been tagged in a post 2010-10-31 20:36:59 -07:00
Mike Macgirvin b919a1e35a more lint 2010-10-31 16:40:09 -07:00
Mike Macgirvin f0b6400584 more lint 2010-10-31 16:38:22 -07:00
Mike Macgirvin ceabd7629b no longer required 2010-10-30 18:20:22 -07:00
Mike Macgirvin fab63ca751 -Wall cleanup 2010-10-30 13:25:37 -07:00
Mike Macgirvin 768acb0a3f -Wall cleanup 2010-10-30 04:59:10 -07:00
Mike Macgirvin cbaf0f2dc9 another typo 2010-10-30 01:16:51 -07:00
Mike Macgirvin 2fc4677173 messages need subjects to link to 2010-10-29 23:00:10 -07:00
Mike Macgirvin 30fe8e39d6 security issue 2010-10-29 22:18:05 -07:00
Mike Macgirvin 7ae75101f1 upd readme 2010-10-29 00:26:08 -07:00
Mike Macgirvin f34c1ce66a provide the means to tag link a person by full_name 2010-10-29 00:02:26 -07:00
Mike Macgirvin 6301de1032 catch a couple of edge cases with the tag linkifier 2010-10-28 20:11:50 -07:00
Mike Macgirvin 051fb7107e linkify @person and @person@domain.com tags 2010-10-28 18:18:20 -07:00
Mike Macgirvin f7e1e907bc typo 2010-10-28 16:06:34 -07:00
Mike Macgirvin a0f6f8ad53 preserve utf-8 on notification emails 2010-10-28 16:05:09 -07:00
Mike Macgirvin 42e6b6cfe4 accepted but ignored - should probably be a 202 http code 2010-10-27 17:29:30 -07:00
Mike Macgirvin f01e8743fc match schemeless activities per the latest activity spec 2010-10-27 15:50:44 -07:00
Mike Macgirvin 78351df785 we need this file 2010-10-26 22:09:51 -07:00
Mike Macgirvin 2028e1695c rework the logging interface 2010-10-26 22:09:13 -07:00
Mike Macgirvin eb5e6aae72 a few more fsw tweaks 2010-10-26 19:01:16 -07:00
Mike Macgirvin d453560be9 more robust (though wasteful) salmon, try both encodings 2010-10-26 15:56:19 -07:00
Mike Macgirvin d2e20d029a de-duplicate photo importation logic 2010-10-26 14:50:38 -07:00
Mike Macgirvin c16f314ec3 two-way subscriptions working with federated social accounts 2010-10-25 21:52:30 -07:00
Mike Macgirvin 1335ef7595 no sparkle on federated network 2010-10-24 21:10:52 -07:00
Mike Macgirvin b41218ca30 workflow for federated/non-dfrn followers 2010-10-24 20:39:24 -07:00
Mike Macgirvin b8b227b328 add nicknames to contact records (going forward and retroactive) 2010-10-23 01:20:26 -07:00
Mike Macgirvin d850badf2b pull out follow, unfollow and as:actor for handling 2010-10-21 21:48:22 -07:00
Mike Macgirvin 16b9c58412 rely on feed item (e.g. salmon) to declare namespaces. This way we
don't cause conflict with any chosen NS prefix in the feed
2010-10-21 20:51:21 -07:00
Mike Macgirvin 8d59ff3c06 aid salmon discovery for feed scrapers that look for the old-style rel type. 2010-10-21 18:07:22 -07:00
Mike Macgirvin d193763aa8 fixed it. Twas the infernal 100 continue headers 2010-10-21 16:45:26 -07:00
Mike Macgirvin a266217a6d temporary fix until I figure out why the header is leaking 2010-10-21 16:26:25 -07:00
Mike Macgirvin a8a88d2532 clean up the salmon consumer bits 2010-10-21 15:32:09 -07:00
Mike Macgirvin 81be82ddab put lrdd link into html headers for completeness 2010-10-21 14:32:29 -07:00
Mike Macgirvin 5edee3c4d1 magic-envelope verification, status.net appears to do it wrong.
Ultimately we need to do it right (or why bother having a spec?),
and fallback to doing it wrong if we're talking to a broken system - which
ironically seems to include most of the federated social web projects.
2010-10-21 04:53:43 -07:00
Mike Macgirvin 39b19cd089 fakelink was being inherited incorrectly by the ACL selector 2010-10-20 03:44:18 -07:00
Mike Macgirvin 68464b5d93 ability to clear browser location on individual posts 2010-10-20 00:33:17 -07:00
Mike Macgirvin b91e9545f7 we'll need this for browser geotagging of course 2010-10-19 20:58:01 -07:00
Mike Macgirvin a8e4ec7801 use browser geolocation when desired 2010-10-19 20:52:05 -07:00
Mike Macgirvin 81835acc36 default the geotag privacy preference 2010-10-19 17:33:22 -07:00
Mike Macgirvin 7c9b323e25 provide choice of using browser geotag 2010-10-19 17:30:15 -07:00
Mike Macgirvin bf727dc3e8 db support for relationship->with in profiles 2010-10-19 17:15:00 -07:00
Mike Macgirvin d58ff1a8df duplex wasn't getting set correctly on group pages 2010-10-19 16:23:05 -07:00
Mike Macgirvin 9d807ba66f oops 2010-10-19 16:10:16 -07:00
Mike Macgirvin d715c062c0 clean up the html layout on profile page 2010-10-19 16:09:10 -07:00
Mike Macgirvin 0b2d85891e lrdd link on profile page (for salmon m/e), remove dfrn-template, qualify some contact lookups, some cleanup of app/boot 2010-10-19 15:51:56 -07:00
Mike Macgirvin 3876cab8ea sorting out the last(?) quirks in group pages. 2010-10-18 16:38:48 -07:00
Mike Macgirvin ac824fe83e eradicate redundant get_uid function 2010-10-18 14:34:59 -07:00
Mike Macgirvin 103814ab8e hordes sounds better 2010-10-18 03:38:12 -07:00
Mike Macgirvin 44853c6453 readme update 2010-10-18 03:32:53 -07:00
Mike Macgirvin 664cf8ac8e pass community page permissions through notification feeds 2010-10-18 03:02:51 -07:00
Mike Macgirvin fbc64baf31 we probably need the page template for the last checkin 2010-10-18 00:47:43 -07:00
Mike Macgirvin 511c761fec group/community/celebrity pages 2010-10-18 00:43:49 -07:00
Mike Macgirvin be981a4f8a wrong type comparison (string, int) which was the cause of the last problem. 2010-10-17 20:27:27 -07:00
Mike Macgirvin 1d2fdb259e funny behaviour with post permissions after recent changes 2010-10-17 20:24:58 -07:00
Mike Macgirvin 3789c288a7 dash, not underscore 2010-10-17 20:13:45 -07:00
Mike Macgirvin 0f47ac282c celebrity/group/community pages about 75% implemented 2010-10-17 20:04:17 -07:00
Mike Macgirvin f5a8a92df1 infrastructure for supporting pages/groups 2010-10-16 22:11:21 -07:00
Mike Macgirvin 36e1afa6ae allow login by username and multiple unique email addresses on system - this will provide support for group/celebrity pages (coming soon). 2010-10-16 20:38:27 -07:00
Mike Macgirvin 6d646e9df5 don't allow ignored contacts to post through the hub, change default poll
for hub subscribers to once a day now that we can utilise multiple hubs.
2010-10-15 04:58:13 -07:00
Mike Macgirvin a1d37b6cc4 add recipient url to pubsub instrumentation 2010-10-15 04:36:39 -07:00
Mike Macgirvin 35a9b49ed0 allow for multiple pubsub hubs so everything can still work when/if one goes flaky
(Google's hub has been particularly unreliable recently and the symptoms are that
you just stop receiving updates, and/or updates you send are silently dropped and
never delivered). Also add more instrumentation to help debug pubsub issues.
2010-10-15 04:20:42 -07:00
Mike Macgirvin e9aa6eb0c7 readme 2010-10-14 05:26:20 -07:00
Mike Macgirvin ba957e9fe9 readme update 2010-10-14 04:20:39 -07:00
84 changed files with 2813 additions and 1163 deletions

57
README
View file

@ -1,58 +1,15 @@
Mistpark Server
Distributed Social Network
Mistpark
Distributed Social Network
IMPORTANT: Please see the file INSTALL for system requirements.
Mistpark has been discontinued - but don't be alarmed. We've merely changed
the name. The project is alive and well at
Mistpark is a social network without boundaries. Mistpark installations can
all link together into a global social network which is free from central
control. We are also developing connectors to seamlessly communicate with many
other open social networks and providers - GNU-social, Diaspora, Status.net,
and even the larger closed services such as Facebook and Twitter.
http://github.com/friendika/friendika
Over the coming months, the boundaries between these networks will start to
become indistinguishable as they all become part of your social circle.
Find us on the web at http://friendika.com
Your personal thoughts and conversations belong to you - and are shared with
those you wish to share them with.
Period.
Mistpark is secure, and as private as you wish it to be. Our privacy settings
are straight-forward and simple, because we know that relationships rarely are
(straight-forward and simple). Whether you're communicating with drinking
buddies or potential employers, you can rest assured that each is only able to
see the side of you that you wish to present.
A single instance of Mistpark Server supports up to several hundred people
using commodity hosting hardware. Each of these people can connect with any
other supported network anywhere in the world and share photos, links,
status updates, whatever.
But maybe you don't want to be connected to the world. That's OK too. Mistpark
may also be closed off from the global community and used to support
social networking amongst corporate, educational, religious, and other private
communities. This makes it an excellent choice for the social networking needs
of young teenagers. Their network can grow to global scope as their maturity
increases - and can be made available only to their known friends until then.
Every person on Mistpark has unlimited profiles available to them. There is a
"public profile" which can be seen by anybody. Additional profiles may be
tailored to specific groups or individuals.
Groups may be created and used for closed conversations. In this way your
conversations with one group of friends is completely isolated from other
friends or groups of friends.
Please see http://mistpark.com for more information.
At the present time, you may contact the author and raise issues via
the source code repository on github.com.
http://github.com/macgirvin/mistpark
It's your network now. If social networking isn't what you thought it would
be, help us to make it better.
Please support mistpark with a donation.

333
boot.php
View file

@ -2,12 +2,20 @@
set_time_limit(0);
define ( 'BUILD_ID', 1007 );
define ( 'BUILD_ID', 1013 );
define ( 'DFRN_PROTOCOL_VERSION', '2.0' );
define ( 'EOL', "<br />\r\n" );
define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
// log levels
define ( 'LOGGER_NORMAL', 0 );
define ( 'LOGGER_TRACE', 1 );
define ( 'LOGGER_DEBUG', 2 );
define ( 'LOGGER_DATA', 3 );
define ( 'LOGGER_ALL', 4 );
// registration policy
define ( 'REGISTER_CLOSED', 0 );
@ -20,6 +28,19 @@ define ( 'REL_VIP', 1);
define ( 'REL_FAN', 2);
define ( 'REL_BUD', 3);
// page/profile types
// PAGE_NORMAL is a typical personal profile account
// PAGE_SOAPBOX automatically approves all friend requests as REL_FAN, (readonly)
// PAGE_COMMUNITY automatically approves all friend requests as REL_FAN, but with
// write access to wall and comments (no email and not included in page owner's ACL lists)
// PAGE_FREELOVE automatically approves all friend requests as full friends (REL_BUD).
define ( 'PAGE_NORMAL', 0 );
define ( 'PAGE_SOAPBOX', 1 );
define ( 'PAGE_COMMUNITY', 2 );
define ( 'PAGE_FREELOVE', 3 );
// Maximum number of "people who like (or don't like) this"
// that we will list by name
@ -39,9 +60,12 @@ define ( 'NAMESPACE_DFRN' , 'http://purl.org/macgirvin/dfrn/1.0' );
define ( 'NAMESPACE_THREAD' , 'http://purl.org/syndication/thread/1.0' );
define ( 'NAMESPACE_TOMB' , 'http://purl.org/atompub/tombstones/1.0' );
define ( 'NAMESPACE_ACTIVITY', 'http://activitystrea.ms/spec/1.0/' );
define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/');
define ( 'NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env');
define ( 'NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe');
define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/' );
define ( 'NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env' );
define ( 'NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe' );
define ( 'NAMESPACE_GEORSS', 'http://www.georss.org/georss' );
define ( 'NAMESPACE_POCO', 'http://portablecontacts.net/spec/1.0' );
define ( 'NAMESPACE_FEED', 'http://schemas.google.com/g/2010#updates-from' );
// activity stream defines
@ -50,6 +74,8 @@ define ( 'ACTIVITY_DISLIKE', NAMESPACE_DFRN . '/dislike' );
define ( 'ACTIVITY_OBJ_HEART', NAMESPACE_DFRN . '/heart' );
define ( 'ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend' );
define ( 'ACTIVITY_FOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'follow' );
define ( 'ACTIVITY_UNFOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'unfollow' );
define ( 'ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post' );
define ( 'ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update' );
@ -94,6 +120,7 @@ class App {
public $pager;
public $strings;
public $path;
public $interactive = true;
private $scheme;
private $hostname;
@ -101,6 +128,7 @@ class App {
private $db;
private $curl_code;
private $curl_headers;
function __construct() {
@ -108,17 +136,17 @@ class App {
$this->page = array();
$this->pager= array();
$this->scheme = ((isset($_SERVER['HTTPS'])
&& ($_SERVER['HTTPS'])) ? 'https' : 'http' );
$this->hostname = str_replace('www.','',
$_SERVER['SERVER_NAME']);
set_include_path("include/$this->hostname"
. PATH_SEPARATOR . 'include'
. PATH_SEPARATOR . '.' );
$this->scheme = ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'])) ? 'https' : 'http' );
if(substr($_SERVER['QUERY_STRING'],0,2) == "q=")
if(x($_SERVER,'SERVER_NAME'))
$this->hostname = $_SERVER['SERVER_NAME'];
set_include_path("include/$this->hostname" . PATH_SEPARATOR . 'include' . PATH_SEPARATOR . '.' );
if((x($_SERVER,'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'],0,2) == "q=")
$_SERVER['QUERY_STRING'] = substr($_SERVER['QUERY_STRING'],2);
$this->cmd = trim($_GET['q'],'/');
if(x($_GET,'q'))
$this->cmd = trim($_GET['q'],'/');
$this->argv = explode('/',$this->cmd);
@ -143,9 +171,7 @@ class App {
if(strlen($this->baseurl))
return $this->baseurl;
$this->baseurl = (($ssl) ? 'https' : $this->scheme) . "://" . $this->hostname
. ((isset($this->path) && strlen($this->path))
? '/' . $this->path : '' );
$this->baseurl = (($ssl) ? 'https' : $this->scheme) . "://" . $this->hostname . ((isset($this->path) && strlen($this->path)) ? '/' . $this->path : '' );
return $this->baseurl;
}
@ -163,7 +189,7 @@ class App {
}
function set_path($p) {
$this->path = ltrim(trim($p),'/');
$this->path = trim(trim($p),'/');
}
function get_path() {
@ -195,6 +221,15 @@ class App {
return $this->curl_code;
}
function set_curl_headers($headers) {
$this->curl_headers = $headers;
}
function get_curl_headers() {
return $this->curl_headers;
}
}}
// retrieve the App structure
@ -330,13 +365,12 @@ function t($s) {
// results.
if(! function_exists('fetch_url')) {
function fetch_url($url,$binary = false) {
function fetch_url($url,$binary = false, &$redirects = 0) {
$ch = curl_init($url);
if(! $ch) return false;
if(($redirects > 8) || (! $ch))
return false;
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);
curl_setopt($ch, CURLOPT_MAXREDIRS,8);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
// by default we will allow self-signed certs
@ -357,26 +391,49 @@ function fetch_url($url,$binary = false) {
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
$s = curl_exec($ch);
$info = curl_getinfo($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$header = substr($s,0,strpos($s,"\r\n\r\n"));
if(stristr($header,'100') && (strlen($header) < 30)) {
// 100 Continue has two headers, get the real one
$s = substr($s,strlen($header)+4);
$header = substr($s,0,strpos($s,"\r\n\r\n"));
}
if($http_code == 301 || $http_code == 302 || $http_code == 303) {
$matches = array();
preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
$url = trim(array_pop($matches));
$url_parsed = parse_url($url);
if (isset($url_parsed)) {
$redirects++;
return fetch_url($url,$binary,$redirects);
}
}
$a = get_app();
$a->set_curl_code($info['http_code']);
$a->set_curl_code($http_code);
$body = substr($s,strlen($header)+4);
$a->set_curl_headers($header);
curl_close($ch);
return($s);
return($body);
}}
// post request to $url. $params is an array of post variables.
if(! function_exists('post_url')) {
function post_url($url,$params) {
function post_url($url,$params, $headers = null, &$redirects = 0) {
$ch = curl_init($url);
if(! $ch) return false;
if(($redirects > 8) || (! $ch))
return false;
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);
curl_setopt($ch, CURLOPT_MAXREDIRS,8);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
if(is_array($headers))
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$check_cert = get_config('system','verifyssl');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
$prx = get_config('system','proxy');
@ -389,11 +446,31 @@ function post_url($url,$params) {
}
$s = curl_exec($ch);
$info = curl_getinfo($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$header = substr($s,0,strpos($s,"\r\n\r\n"));
if(stristr($header,'100') && (strlen($header) < 30)) {
// 100 Continue has two headers, get the real one
$s = substr($s,strlen($header)+4);
$header = substr($s,0,strpos($s,"\r\n\r\n"));
}
if($http_code == 301 || $http_code == 302 || $http_code == 303) {
$matches = array();
preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
$url = trim(array_pop($matches));
$url_parsed = parse_url($url);
if (isset($url_parsed)) {
$redirects++;
return post_url($url,$binary,$headers,$redirects);
}
}
$a = get_app();
$a->set_curl_code($info['http_code']);
$a->set_curl_code($http_code);
$body = substr($s,strlen($header)+4);
$a->set_curl_headers($header);
curl_close($ch);
return($s);
return($body);
}}
// random hash, 64 chars
@ -539,8 +616,7 @@ function goaway($s) {
if(! function_exists('xml_status')) {
function xml_status($st, $message = '') {
if(strlen($message))
$xml_message = "\t<message>" . xmlify($message) . "</message>\r\n";
$xml_message = ((strlen($message)) ? "\t<message>" . xmlify($message) . "</message>\r\n" : '');
header( "Content-type: text/xml" );
echo '<?xml version="1.0" encoding="UTF-8"?>'."\r\n";
@ -553,7 +629,7 @@ function xml_status($st, $message = '') {
if(! function_exists('local_user')) {
function local_user() {
if((x($_SESSION,'authenticated')) && (x($_SESSION,'uid')))
return $_SESSION['uid'];
return intval($_SESSION['uid']);
return false;
}}
@ -562,7 +638,7 @@ function local_user() {
if(! function_exists('remote_user')) {
function remote_user() {
if((x($_SESSION,'authenticated')) && (x($_SESSION,'visitor_id')))
return $_SESSION['visitor_id'];
return intval($_SESSION['visitor_id']);
return false;
}}
@ -571,9 +647,9 @@ function remote_user() {
if(! function_exists('notice')) {
function notice($s) {
$_SESSION['sysmsg'] .= $s;
$a = get_app();
if($a->interactive)
$_SESSION['sysmsg'] .= $s;
}}
// wrapper around config to limit the text length of an incoming message
@ -901,11 +977,11 @@ function webfinger($s) {
if(strlen($host)) {
$tpl = fetch_lrdd_template($host);
if(strlen($tpl)) {
$pxrd = str_replace('{uri}', urlencode('acct://'.$s), $tpl);
$pxrd = str_replace('{uri}', urlencode('acct:'.$s), $tpl);
$links = fetch_xrd_links($pxrd);
if(! count($links)) {
// try without the double slashes
$pxrd = str_replace('{uri}', urlencode('acct:'.$s), $tpl);
// try with double slashes
$pxrd = str_replace('{uri}', urlencode('acct://'.$s), $tpl);
$links = fetch_xrd_links($pxrd);
}
return $links;
@ -914,6 +990,54 @@ function webfinger($s) {
return array();
}}
if(! function_exists('lrdd')) {
function lrdd($uri) {
$a = get_app();
if(strstr($uri,'@')) {
return(webfinger($uri));
}
else {
$html = fetch_url($uri);
$headers = $a->get_curl_headers();
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
// TODO alter the following regex to support multiple relations (space separated)
if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) {
$link = $matches[1];
break;
}
}
}
if(! isset($link)) {
// parse the page of the supplied URL looking for rel links
require_once('library/HTML5/Parser.php');
$dom = HTML5_Parser::parse($html);
if($dom) {
$items = $dom->getElementsByTagName('link');
foreach($items as $item) {
$x = $item->getAttribute('rel');
if($x == "lrdd") {
$link = $item->getAttribute('href');
break;
}
}
}
}
if(isset($link))
return(fetch_xrd_links($link));
}
return array();
}}
// Given a host name, locate the LRDD template from that
// host. Returns the LRDD template or an empty string on
// error/failure.
@ -1009,13 +1133,6 @@ function photo_new_resource() {
}}
// Returns logged in user ID
if(! function_exists('get_uid')) {
function get_uid() {
return ((x($_SESSION,'uid')) ? intval($_SESSION['uid']) : 0) ;
}}
// Take a URL from the wild, prepend http:// if necessary
// and check DNS to see if it's real
// return true if it's OK, false if something is wrong with it
@ -1120,6 +1237,7 @@ function allowed_email($email) {
if(! function_exists('format_like')) {
function format_like($cnt,$arr,$type,$id) {
$o = '';
if($cnt == 1)
$o .= $arr[0] . (($type === 'like') ? t(' likes this.') : t(' doesn\'t like this.')) . EOL ;
else {
@ -1134,7 +1252,7 @@ function format_like($cnt,$arr,$type,$id) {
if($total >= MAX_LIKERS)
$str .= t(', and ') . $total - MAX_LIKERS . t(' other people');
$str .= (($type === 'like') ? t(' like this.') : t(' don\'t like this.'));
$o .= '<div id="' . $type . 'list-' . $id . '" style="display: none;" >' . $str . '</div>';
$o .= "\t" . '<div id="' . $type . 'list-' . $id . '" style="display: none;" >' . $str . '</div>';
}
return $o;
}}
@ -1151,4 +1269,115 @@ function load_view_file($s) {
if($lang && file_exists("$d/$lang/$b"))
return file_get_contents("$d/$lang/$b");
return file_get_contents($s);
}}
}}
// for html,xml parsing - let's say you've got
// an attribute foobar="class1 class2 class3"
// and you want to find out if it contains 'class3'.
// you can't use a normal sub string search because you
// might match 'notclass3' and a regex to do the job is
// possible but a bit complicated.
// pass the attribute string as $attr and the attribute you
// are looking for as $s - returns true if found, otherwise false
if(! function_exists('attribute_contains')) {
function attribute_contains($attr,$s) {
$a = explode(' ', $attr);
if(count($a) && in_array($s,$a))
return true;
return false;
}}
if(! function_exists('logger')) {
function logger($msg,$level = 0) {
$debugging = get_config('system','debugging');
$loglevel = intval(get_config('system','loglevel'));
$logfile = get_config('system','logfile');
if((! $debugging) || (! $logfile) || ($level > $loglevel))
return;
@file_put_contents($logfile, datetime_convert() . ':' . session_id() . ' ' . $msg . "\n", FILE_APPEND);
return;
}}
if(! function_exists('activity_match')) {
function activity_match($haystack,$needle) {
if(($haystack === $needle) || ((basename($needle) === $haystack) && strstr($needle,NAMESPACE_ACTIVITY_SCHEMA)))
return true;
return false;
}}
// Pull out all #hashtags and @person tags from $s;
// We also get @person@domain.com - which would make
// the regex quite complicated as tags can also
// end a sentence. So we'll run through our results
// and strip the period from any tags which end with one.
// Returns array of tags found, or empty array.
if(! function_exists('get_tags')) {
function get_tags($s) {
$ret = array();
if(preg_match_all('/([@#][^ ,:?]*)([ ,:?]|$)/',$s,$match)) {
foreach($match[1] as $match) {
if(substr($match,-1,1) === '.')
$ret[] = substr($match,0,-1);
else
$ret[] = $match;
}
}
return $ret;
}}
// quick and dirty quoted_printable encoding
if(! function_exists('qp')) {
function qp($s) {
return str_replace ("%","=",rawurlencode($s));
}}
if(! function_exists('like_puller')) {
function like_puller($a,$item,&$arr,$mode) {
$url = '';
$sparkle = '';
$verb = (($mode === 'like') ? ACTIVITY_LIKE : ACTIVITY_DISLIKE);
if((activity_match($item['verb'],$verb)) && ($item['id'] != $item['parent'])) {
$url = $item['url'];
if(($item['network'] === 'dfrn') && (! $item['self'])) {
$url = $a->get_baseurl() . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle" ';
}
if(! ((isset($arr[$item['parent'] . '-l'])) && (is_array($arr[$item['parent'] . '-l']))))
$arr[$item['parent'] . '-l'] = array();
if(! isset($arr[$item['parent']]))
$arr[$item['parent']] = 1;
else
$arr[$item['parent']] ++;
$arr[$item['parent'] . '-l'][] = '<a href="'. $url . '"'. $sparkle .'>' . $item['name'] . '</a>';
}
return;
}}
function get_mentions($item) {
$o = '';
if(! strlen($item['tag']))
return $o;
$arr = explode(',',$item['tag']);
foreach($arr as $x) {
$matches = null;
if(preg_match('/@\[url=([^\]]*)\]/',$x,$matches))
$o .= "\t\t" . '<link rel="mentioned" href="' . $matches[1] . '" />' . "\r\n";
}
return $o;
}

View file

@ -56,12 +56,14 @@ CREATE TABLE IF NOT EXISTS `contact` (
`duplex` tinyint(1) NOT NULL DEFAULT '0',
`network` char(255) NOT NULL,
`name` char(255) NOT NULL,
`nick` char(255) NOT NULL,
`photo` text NOT NULL,
`thumb` text NOT NULL,
`site-pubkey` text NOT NULL,
`issued-id` char(255) NOT NULL,
`dfrn-id` char(255) NOT NULL,
`url` char(255) NOT NULL,
`lrdd` char(255) NOT NULL,
`pubkey` text NOT NULL,
`prvkey` text NOT NULL,
`request` text NOT NULL,
@ -174,6 +176,7 @@ CREATE TABLE IF NOT EXISTS `item` (
`object` text NOT NULL,
`resource-id` char(255) NOT NULL,
`tag` mediumtext NOT NULL,
`inform` mediumtext NOT NULL,
`location` char(255) NOT NULL,
`coord` char(255) NOT NULL,
`allow_cid` mediumtext NOT NULL,
@ -280,6 +283,7 @@ CREATE TABLE IF NOT EXISTS `profile` (
`country-name` char(255) NOT NULL,
`gender` char(32) NOT NULL,
`marital` char(255) NOT NULL,
`with` text NOT NULL,
`sexual` char(255) NOT NULL,
`politic` char(255) NOT NULL,
`religion` char(255) NOT NULL,
@ -346,17 +350,24 @@ CREATE TABLE IF NOT EXISTS `user` (
`email` char(255) NOT NULL,
`timezone` char(128) NOT NULL,
`default-location` char(255) NOT NULL,
`allow_location` tinyint(1) NOT NULL DEFAULT '0',
`theme` char(255) NOT NULL,
`pubkey` text NOT NULL,
`prvkey` text NOT NULL,
`spubkey` text NOT NULL,
`sprvkey` text NOT NULL,
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0', `blocked`
tinyint(1) unsigned NOT NULL DEFAULT '0', `notify-flags` int(11)
unsigned NOT NULL DEFAULT '65535', `pwdreset` char(255) NOT NULL,
`allow_cid` mediumtext NOT NULL, `allow_gid` mediumtext NOT NULL,
`deny_cid` mediumtext NOT NULL, `deny_gid` mediumtext NOT NULL,
PRIMARY KEY (`uid`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
`blocked` tinyint(1) unsigned NOT NULL DEFAULT '0',
`notify-flags` int(11) unsigned NOT NULL DEFAULT '65535',
`page-flags` int(11) unsigned NOT NULL DEFAULT '0',
`pwdreset` char(255) NOT NULL,
`allow_cid` mediumtext NOT NULL,
`allow_gid` mediumtext NOT NULL,
`deny_cid` mediumtext NOT NULL,
`deny_gid` mediumtext NOT NULL,
PRIMARY KEY (`uid`),
KEY `nickname` (`nickname`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `register` (

BIN
images/noglobe.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

View file

@ -16,7 +16,7 @@ function user_remove($uid) {
q("DELETE FROM `profile` WHERE `uid` = %d", intval($uid));
q("DELETE FROM `profile_check` WHERE `uid` = %d", intval($uid));
q("DELETE FROM `user` WHERE `uid` = %d", intval($uid));
if($uid == get_uid()) {
if($uid == local_user()) {
unset($_SESSION['authenticated']);
unset($_SESSION['uid']);
killme();

View file

@ -208,3 +208,44 @@ class Photo {
}}
function import_profile_photo($photo,$uid,$cid) {
$a = get_app();
$photo_failure = false;
$filename = basename($photo);
$img_str = fetch_url($photo,true);
$img = new Photo($img_str);
if($img->is_valid()) {
$img->scaleImageSquare(175);
$hash = photo_new_resource();
$r = $img->store($uid, $cid, $hash, $filename, t('Contact Photos'), 4 );
if($r === false)
$photo_failure = true;
$img->scaleImage(80);
$r = $img->store($uid, $cid, $hash, $filename, t('Contact Photos'), 5 );
if($r === false)
$photo_failure = true;
$photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
$thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';
}
else
$photo_failure = true;
if($photo_failure) {
$photo = $a->get_baseurl() . '/images/default-profile.jpg';
$thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg';
}
return(array($photo,$thumb));
}

View file

@ -2,15 +2,6 @@
require_once('library/HTML5/Parser.php');
if(! function_exists('attribute_contains')) {
function attribute_contains($attr,$s) {
$a = explode(' ', $attr);
if(count($a) && in_array($s,$a))
return true;
return false;
}}
if(! function_exists('scrape_dfrn')) {
function scrape_dfrn($url) {
@ -33,6 +24,11 @@ function scrape_dfrn($url) {
$x = $item->getAttribute('rel');
if(substr($x,0,5) == "dfrn-")
$ret[$x] = $item->getAttribute('href');
if($x === 'lrdd') {
$decoded = urldecode($item->getAttribute('href'));
if(preg_match('/acct:([^@]*)@/',$decoded,$matches))
$ret['nick'] = $matches[1];
}
}
// Pull out hCard profile elements
@ -48,7 +44,7 @@ function scrape_dfrn($url) {
$ret['photo'] = $x->getAttribute('src');
if(attribute_contains($x->getAttribute('class'),'key'))
$ret['key'] = $x->textContent;
}
}
}
}
@ -102,3 +98,40 @@ function scrape_meta($url) {
return $ret;
}}
if(! function_exists('scrape_vcard')) {
function scrape_vcard($url) {
$ret = array();
$s = fetch_url($url);
if(! $s)
return $ret;
$dom = HTML5_Parser::parse($s);
if(! $dom)
return $ret;
// Pull out hCard profile elements
$items = $dom->getElementsByTagName('*');
foreach($items as $item) {
if(attribute_contains($item->getAttribute('class'), 'vcard')) {
$level2 = $item->getElementsByTagName('*');
foreach($level2 as $x) {
if(attribute_contains($x->getAttribute('class'),'fn'))
$ret['fn'] = $x->textContent;
if((attribute_contains($x->getAttribute('class'),'photo'))
|| (attribute_contains($x->getAttribute('class'),'avatar')))
$ret['photo'] = $x->getAttribute('src');
if((attribute_contains($x->getAttribute('class'),'nickname'))
|| (attribute_contains($x->getAttribute('class'),'uid')))
$ret['nick'] = $x->textContent;
}
}
}
return $ret;
}}

View file

@ -2,9 +2,9 @@
// login/logout
if((x($_SESSION,'authenticated')) && (! ($_POST['auth-params'] === 'login'))) {
if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-params'))) || ($_POST['auth-params'] !== 'login'))) {
if($_POST['auth-params'] === 'logout' || $a->module === 'logout') {
if(((x($_POST,'auth-params')) && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) {
// process logout request
@ -14,6 +14,7 @@ if((x($_SESSION,'authenticated')) && (! ($_POST['auth-params'] === 'login'))) {
unset($_SESSION['administrator']);
unset($_SESSION['cid']);
unset($_SESSION['theme']);
unset($_SESSION['page_flags']);
notice( t('Logged out.') . EOL);
goaway($a->get_baseurl());
}
@ -34,12 +35,13 @@ if((x($_SESSION,'authenticated')) && (! ($_POST['auth-params'] === 'login'))) {
$a->user = $r[0];
$_SESSION['theme'] = $a->user['theme'];
$_SESSION['page_flags'] = $a->user['page-flags'];
if(strlen($a->user['timezone']))
date_default_timezone_set($a->user['timezone']);
$_SESSION['my_url'] = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
$r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1",
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
intval($_SESSION['uid']));
if(count($r)) {
$a->contact = $r[0];
@ -51,22 +53,27 @@ if((x($_SESSION,'authenticated')) && (! ($_POST['auth-params'] === 'login'))) {
}
else {
unset($_SESSION['authenticated']);
unset($_SESSION['uid']);
unset($_SESSION['visitor_id']);
unset($_SESSION['administrator']);
unset($_SESSION['cid']);
unset($_SESSION['theme']);
unset($_SESSION['my_url']);
if(isset($_SESSION)) {
unset($_SESSION['authenticated']);
unset($_SESSION['uid']);
unset($_SESSION['visitor_id']);
unset($_SESSION['administrator']);
unset($_SESSION['cid']);
unset($_SESSION['theme']);
unset($_SESSION['my_url']);
unset($_SESSION['page_flags']);
}
$encrypted = hash('whirlpool',trim($_POST['password']));
if(x($_POST,'password'))
$encrypted = hash('whirlpool',trim($_POST['password']));
if((x($_POST,'auth-params')) && $_POST['auth-params'] === 'login') {
// process login request
$r = q("SELECT * FROM `user`
WHERE `email` = '%s' AND `password` = '%s' AND `blocked` = 0 AND `verified` = 1 LIMIT 1",
WHERE ( `email` = '%s' OR `nickname` = '%s' ) AND `password` = '%s' AND `blocked` = 0 AND `verified` = 1 LIMIT 1",
dbesc(trim($_POST['login-name'])),
dbesc(trim($_POST['login-name'])),
dbesc($encrypted));
if(($r === false) || (! count($r))) {
@ -76,6 +83,7 @@ else {
$_SESSION['uid'] = $r[0]['uid'];
$_SESSION['theme'] = $r[0]['theme'];
$_SESSION['authenticated'] = 1;
$_SESSION['page_flags'] = $r[0]['page-flags'];
$_SESSION['my_url'] = $a->get_baseurl() . '/profile/' . $r[0]['nickname'];
notice( t("Welcome back ") . $r[0]['username'] . EOL);
@ -86,6 +94,7 @@ else {
$r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1",
intval($_SESSION['uid']));
if(count($r)) {
$a->contact = $r[0];
$a->cid = $r[0]['id'];
$_SESSION['cid'] = $a->cid;
}

View file

@ -36,8 +36,8 @@ class dba {
$mesg = '';
if($this->db->mysqli->errno)
$debug_text .= $this->db->mysqli->error . EOL;
if($this->db->errno)
$debug_text .= $this->db->error . EOL;
if($result === false)
$mesg = 'false';
@ -58,8 +58,11 @@ class dba {
}
}
else {
if(($result === false) && (file_exists('dbfail.out')))
file_put_contents('dbfail.out', printable($sql) . ' returned false' . "\n", FILE_APPEND);
if($result === false) {
logger('dba: ' . printable($sql) . ' returned false.');
if(file_exists('dbfail.out'))
file_put_contents('dbfail.out', printable($sql) . ' returned false' . "\n", FILE_APPEND);
}
}
if(($result === true) || ($result === false))

View file

@ -122,11 +122,13 @@ function group_get_members($gid) {
function group_side($every="contacts",$each="group") {
if(! local_user())
return;
$o = '';
$createtext = t('Create a new group');
$linktext= t('Everybody');
if(! local_user())
return '';
$createtext = t('Create a new group');
$linktext= t('Everybody');
$o .= <<< EOT

View file

@ -27,8 +27,10 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) {
$r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
intval($owner_id)
);
if(count($r))
if(count($r)) {
$owner = $r[0];
$owner['nickname'] = $owner_nick;
}
else
killme();
@ -90,7 +92,7 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) {
$sort = 'ASC';
if(! strlen($last_update))
$last_update = 'now - 30 days';
$last_update = 'now -30 days';
$check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s');
@ -117,23 +119,33 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) {
$items = $r;
$feed_template = load_view_file('view/atom_feed.tpl');
$tomb_template = load_view_file('view/atom_tomb.tpl');
$item_template = load_view_file('view/atom_item.tpl');
$cmnt_template = load_view_file('view/atom_cmnt.tpl');
$atom = '';
$hub = get_config('system','huburl');
$hubxml = ((strlen($hub)) ? '<link rel="hub" href="' . xmlify($hub) . '" />' . "\n" : '');
$hubxml = '';
if(strlen($hub)) {
$hubs = explode(',', $hub);
if(count($hubs)) {
foreach($hubs as $h) {
$h = trim($h);
if(! strlen($h))
continue;
$hubxml .= '<link rel="hub" href="' . xmlify($h) . '" />' . "\n" ;
}
}
}
$salmon = '<link rel="salmon" href="' . xmlify($a->get_baseurl() . '/salmon/' . $owner_nick) . '" />' . "\n" ;
$salmon = ''; // remove this line when salmon handler is finished
$salmon .= '<link rel="http://salmon-protocol.org/ns/salmon-replies" href="' . xmlify($a->get_baseurl() . '/salmon/' . $owner_nick) . '" />' . "\n" ;
$salmon .= '<link rel="http://salmon-protocol.org/ns/salmon-mention" href="' . xmlify($a->get_baseurl() . '/salmon/' . $owner_nick) . '" />' . "\n" ;
$atom .= replace_macros($feed_template, array(
'$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner_nick),
'$feed_title' => xmlify($owner['name']),
'$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', $updated . '+00:00' , ATOM_TIME)) ,
'$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now' , ATOM_TIME)) ,
'$hub' => $hubxml,
'$salmon' => $salmon,
'$name' => xmlify($owner['name']),
@ -156,65 +168,13 @@ function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) {
// public feeds get html, our own nodes use bbcode
if($dfrn_id === '*') {
$allow = (($item['last-child']) ? 1 : 0);
$item['body'] = bbcode($item['body']);
$type = 'html';
}
else {
$allow = ((($item['last-child']) && ($contact['rel']) && ($contact['rel'] != REL_FAN)) ? 1 : 0);
$type = 'text';
}
if($item['deleted']) {
$atom .= replace_macros($tomb_template, array(
'$id' => xmlify($item['uri']),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME))
));
}
else {
$verb = construct_verb($item);
$actobj = construct_activity($item);
if($item['parent'] == $item['id']) {
$atom .= replace_macros($item_template, array(
'$name' => xmlify($item['name']),
'$profile_page' => xmlify($item['url']),
'$thumb' => xmlify($item['thumb']),
'$owner_name' => xmlify($item['owner-name']),
'$owner_profile_page' => xmlify($item['owner-link']),
'$owner_thumb' => xmlify($item['owner-avatar']),
'$item_id' => xmlify($item['uri']),
'$title' => xmlify($item['title']),
'$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME)),
'$location' => xmlify($item['location']),
'$type' => $type,
'$alt' => xmlify($a->get_baseurl() . '/display/' . $owner_nick . '/' . $item['id']),
'$content' => xmlify($item['body']),
'$verb' => xmlify($verb),
'$actobj' => $actobj, // do not xmlify
'$comment_allow' => $allow
));
}
else {
$atom .= replace_macros($cmnt_template, array(
'$name' => xmlify($item['name']),
'$profile_page' => xmlify($item['url']),
'$thumb' => xmlify($item['thumb']),
'$item_id' => xmlify($item['uri']),
'$title' => xmlify($item['title']),
'$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME)),
'$type' => $type,
'$content' => xmlify($item['body']),
'$alt' => xmlify($a->get_baseurl() . '/display/' . $owner_nick . '/' . $item['id']),
'$verb' => xmlify($verb),
'$actobj' => $actobj, // do not xmlify
'$parent_id' => xmlify($item['parent-uri']),
'$comment_allow' => $allow
));
}
}
$atom .= atom_entry($item,$type,null,$owner,true);
}
$atom .= '</feed>' . "\r\n";
@ -253,28 +213,89 @@ function construct_activity($item) {
function get_atom_elements($item) {
function get_atom_elements($feed,$item) {
require_once('library/HTMLPurifier.auto.php');
require_once('include/html2bbcode.php');
$res = array();
$best_photo = array();
$raw_author = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
if($raw_author) {
if($raw_author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] === 'photo')
$res['author-avatar'] = unxmlify($raw_author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href']);
}
$res = array();
$author = $item->get_author();
$res['author-name'] = unxmlify($author->get_name());
$res['author-link'] = unxmlify($author->get_link());
if(! $res['author-avatar'])
$res['author-avatar'] = unxmlify($author->get_avatar());
$res['uri'] = unxmlify($item->get_id());
$res['title'] = unxmlify($item->get_title());
$res['body'] = unxmlify($item->get_content());
// look for a photo. We should check media size and find the best one,
// but for now let's just find any author photo
$rawauthor = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
$base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
foreach($base as $link) {
if(! $res['author-avatar']) {
if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
$res['author-avatar'] = unxmlify($link['attribs']['']['href']);
}
}
}
$rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor');
if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
$base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
if($base && count($base)) {
foreach($base as $link) {
if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
$res['author-link'] = unxmlify($link['attribs']['']['href']);
if(! $res['author-avatar']) {
if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
$res['author-avatar'] = unxmlify($link['attribs']['']['href']);
}
}
}
}
// No photo/profile-link on the item - look at the feed level
if((! $res['author-link']) || (! $res['author-avatar'])) {
$rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
$base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
foreach($base as $link) {
if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
$res['author-link'] = unxmlify($link['attribs']['']['href']);
if(! $res['author-avatar']) {
if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
$res['author-avatar'] = unxmlify($link['attribs']['']['href']);
}
}
}
$rawactor = $feed->get_feed_tags(NAMESPACE_ACTIVITY, 'subject');
if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
$base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
if($base && count($base)) {
foreach($base as $link) {
if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
$res['author-link'] = unxmlify($link['attribs']['']['href']);
if(! $res['author-avatar']) {
if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
$res['author-avatar'] = unxmlify($link['attribs']['']['href']);
}
}
}
}
}
$maxlen = get_max_import_size();
if($maxlen && (strlen($res['body']) > $maxlen))
$res['body'] = substr($res['body'],0, $maxlen);
@ -296,7 +317,7 @@ function get_atom_elements($item) {
'[youtube]$1[/youtube]', $res['body']);
$config = HTMLPurifier_Config::createDefault();
$config->set('Core.DefinitionCache', null);
$config->set('Cache.DefinitionImpl', null);
// we shouldn't need a whitelist, because the bbcode converter
// will strip out any unsupported tags.
@ -339,10 +360,21 @@ function get_atom_elements($item) {
elseif($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])
$res['owner-link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] === 'photo')
$res['owner-avatar'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href']);
elseif($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data'])
$res['owner-avatar'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data']);
if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
$base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
foreach($base as $link) {
if(! $res['owner-avatar']) {
if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
$res['owner-avatar'] = unxmlify($link['attribs']['']['href']);
}
}
}
$rawgeo = $item->get_item_tags(NAMESPACE_GEORSS,'point');
if($rawgeo)
$res['coord'] = unxmlify($rawgeo[0]['data']);
$rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
// select between supported verbs
@ -351,7 +383,6 @@ function get_atom_elements($item) {
$rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
if($rawobj) {
$res['object'] = '<object>' . "\n";
if($rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
@ -375,7 +406,7 @@ function get_atom_elements($item) {
'[youtube]$1[/youtube]', $body);
$config = HTMLPurifier_Config::createDefault();
$config->set('Core.DefinitionCache', null);
$config->set('Cache.DefinitionImpl', null);
$purifier = new HTMLPurifier($config);
$body = $purifier->purify($body);
@ -393,14 +424,11 @@ function get_atom_elements($item) {
function item_store($arr) {
//print_r($arr);
if($arr['gravity'])
$arr['gravity'] = intval($arr['gravity']);
elseif($arr['parent-uri'] == $arr['uri'])
$arr['gravity'] = 0;
elseif($arr['verb'] == ACTIVITY_POST)
elseif(activity_match($arr['verb'],ACTIVITY_POST))
$arr['gravity'] = 6;
if(! x($arr,'type'))
@ -418,6 +446,7 @@ function item_store($arr) {
$arr['changed'] = datetime_convert();
$arr['title'] = notags(trim($arr['title']));
$arr['location'] = notags(trim($arr['location']));
$arr['coord'] = notags(trim($arr['coord']));
$arr['body'] = escape_tags(trim($arr['body']));
$arr['last-child'] = intval($arr['last-child']);
$arr['visible'] = ((x($arr,'visible') !== false) ? intval($arr['visible']) : 1);
@ -504,10 +533,10 @@ function get_item_contact($item,$contacts) {
}
function dfrn_deliver($contact,$atom,$debugging = false) {
function dfrn_deliver($owner,$contact,$atom) {
if((! strlen($contact['dfrn-id'])) && (! $contact['duplex']))
if((! strlen($contact['dfrn-id'])) && (! $contact['duplex']) && (! ($owner['page-flags'] == PAGE_COMMUNITY)))
return 3;
$idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
@ -519,13 +548,11 @@ function dfrn_deliver($contact,$atom,$debugging = false) {
$url = $contact['notify'] . '?dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION ;
if($debugging)
echo "URL: $url\n";
logger('dfrn_deliver: ' . $url);
$xml = fetch_url($url);
if($debugging)
echo $xml;
logger('dfrn_deliver: ' . $xml);
if(! $xml)
return 3;
@ -541,7 +568,9 @@ function dfrn_deliver($contact,$atom,$debugging = false) {
$final_dfrn_id = '';
if($contact['duplex'] && strlen($contact['prvkey'])) {
if(($contact['duplex'] && strlen($contact['prvkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) {
openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']);
openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']);
}
@ -556,6 +585,7 @@ function dfrn_deliver($contact,$atom,$debugging = false) {
$final_dfrn_id = substr($final_dfrn_id,2);
if($final_dfrn_id != $orig_id) {
logger('dfrn_deliver: wrong dfrn_id.');
// did not decode properly - cannot trust this site
return 3;
}
@ -566,14 +596,16 @@ function dfrn_deliver($contact,$atom,$debugging = false) {
if(($contact['rel']) && ($contact['rel'] != REL_FAN) && (! $contact['blocked']) && (! $contact['readonly'])) {
$postvars['data'] = $atom;
}
elseif($owner['page-flags'] == PAGE_COMMUNITY) {
$postvars['data'] = $atom;
}
else {
$postvars['data'] = str_replace('<dfrn:comment-allow>1','<dfrn:comment-allow>0',$atom);
}
$xml = post_url($contact['notify'],$postvars);
if($debugging)
echo $xml;
logger('dfrn_deliver: ' . "SENDING: " . print_r($postvars,true) . "\n" . "RECEIVING: " . $xml);
$res = simplexml_load_string($xml);
@ -582,6 +614,22 @@ function dfrn_deliver($contact,$atom,$debugging = false) {
}
/*
*
* consume_feed - process atom feed and update anything/everything we might need to update
*
* $xml = the (atom) feed to consume - no RSS spoken here, it might partially work since simplepie
* handles both, but we don't claim it will work well, and are reasonably certain it won't.
* $importer = the contact_record (joined to user_record) of the local user who owns this relationship.
* It is this person's stuff that is going to be updated.
* $contact = the person who is sending us stuff. If not set, we MAY be processing a "follow" activity
* from an external network and MAY create an appropriate contact record. Otherwise, we MUST
* have a contact record.
* $hub = should wefind ahub declation in the feed, pass it back to our calling process, who might (or
* might not) try and subscribe to it.
*
*/
function consume_feed($xml,$importer,$contact, &$hub) {
require_once('simplepie/simplepie.inc');
@ -592,6 +640,7 @@ function consume_feed($xml,$importer,$contact, &$hub) {
$feed->init();
// Check at the feed level for updated contact name and/or photo
$debugging = get_config('system','debugging');
$name_updated = '';
$new_name = '';
@ -599,10 +648,10 @@ function consume_feed($xml,$importer,$contact, &$hub) {
$photo_url = '';
$foundhub = $feed->get_link(0,'hub');
$hubs = $feed->get_links('hub');
if(strlen($foundhub))
$hub = $foundhub;
if(count($hubs))
$hub = implode(',', $hubs);
$rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
if($rawtags) {
@ -623,7 +672,7 @@ function consume_feed($xml,$importer,$contact, &$hub) {
$photo_url = $feed->get_image_url();
}
}
if(($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $contact['avatar-date'])) {
if((is_array($contact)) && ($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $contact['avatar-date'])) {
require_once("Photo.php");
$photo_failure = false;
@ -660,7 +709,7 @@ function consume_feed($xml,$importer,$contact, &$hub) {
}
}
if(($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) {
if((is_array($contact)) && ($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) {
q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1",
dbesc(notags(trim($new_name))),
dbesc(datetime_convert()),
@ -686,10 +735,11 @@ function consume_feed($xml,$importer,$contact, &$hub) {
else
$when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
}
if($deleted) {
$r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
if($deleted && is_array($contact)) {
$r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `contact-id` = %d LIMIT 1",
dbesc($uri),
intval($importer['uid'])
intval($importer['uid']),
intval($contact['id'])
);
if(count($r)) {
$item = $r[0];
@ -746,7 +796,7 @@ function consume_feed($xml,$importer,$contact, &$hub) {
}
if($is_reply) {
if(($is_reply) && is_array($contact)) {
// Have we seen it? If not, import it.
@ -775,11 +825,13 @@ function consume_feed($xml,$importer,$contact, &$hub) {
}
continue;
}
$datarray = get_atom_elements($item);
$datarray = get_atom_elements($feed,$item);
if($contact['network'] === 'stat' && strlen($datarray['title']))
unset($datarray['title']);
$datarray['parent-uri'] = $parent_uri;
$datarray['uid'] = $importer['uid'];
$datarray['contact-id'] = $contact['id'];
if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) {
if((activity_match($datarray['verb'],ACTIVITY_LIKE)) || (activity_match($datarray['verb'],ACTIVITY_DISLIKE))) {
$datarray['type'] = 'activity';
$datarray['gravity'] = GRAVITY_LIKE;
}
@ -808,7 +860,26 @@ function consume_feed($xml,$importer,$contact, &$hub) {
}
continue;
}
$datarray = get_atom_elements($item);
$datarray = get_atom_elements($feed,$item);
if(activity_match($datarray['verb'],ACTIVITY_FOLLOW)) {
logger('consume-feed: New follower');
new_follower($importer,$contact,$datarray,$item);
return;
}
if(activity_match($datarray['verb'],ACTIVITY_UNFOLLOW)) {
lose_follower($importer,$contact,$datarray,$item);
return;
}
if(! is_array($contact))
return;
if($contact['network'] === 'stat') {
if(strlen($datarray['title']))
unset($datarray['title']);
if(($contact['rel'] == REL_VIP) || ($contact['rel'] == REL_BUD))
$datarray['last-child'] = 1;
}
$datarray['parent-uri'] = $item_id;
$datarray['uid'] = $importer['uid'];
$datarray['contact-id'] = $contact['id'];
@ -821,6 +892,78 @@ function consume_feed($xml,$importer,$contact, &$hub) {
}
function new_follower($importer,$contact,$datarray,$item) {
$url = notags(trim($datarray['author-link']));
$name = notags(trim($datarray['author-name']));
$photo = notags(trim($datarray['author-avatar']));
$rawtag = $item->get_item_tags(NAMESPACE_ACTIVITY,'actor');
if($rawtag && $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data'])
$nick = $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data'];
if(is_array($contact)) {
if($contact['network'] == 'stat' && $contact['rel'] == REL_FAN) {
$r = q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(REL_BUD),
intval($contact['id']),
intval($importer['uid'])
);
}
// send email notification to owner?
}
else {
// create contact record - set to readonly
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `name`, `nick`, `photo`, `network`, `rel`,
`blocked`, `readonly`, `pending` )
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, 0, 1, 1 ) ",
intval($importer['uid']),
dbesc(datetime_convert()),
dbesc($url),
dbesc($name),
dbesc($nick),
dbesc($photo),
dbesc('stat'),
intval(REL_VIP)
);
$r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `pending` = 1 AND `rel` = %d LIMIT 1",
intval($importer['uid']),
dbesc($url),
intval(REL_VIP)
);
if(count($r))
$contact_record = $r[0];
// create notification
$hash = random_string();
if(is_array($contact_record)) {
$ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `hash`, `datetime`)
VALUES ( %d, %d, 0, 0, '%s', '%s' )",
intval($importer['uid']),
intval($contact_record['id']),
dbesc($hash),
dbesc(datetime_convert())
);
}
}
}
function lose_follower($importer,$contact,$datarray,$item) {
if(($contact['rel'] == REL_BUD) || ($contact['rel'] == REL_FAN)) {
q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d LIMIT 1",
intval(REL_FAN),
intval($contact['id'])
);
}
else {
contact_remove($contact['id']);
}
}
function subscribe_to_hub($url,$importer,$contact) {
@ -834,16 +977,89 @@ function subscribe_to_hub($url,$importer,$contact) {
$push_url = get_config('system','url') . '/pubsub/' . $r[0]['nickname'] . '/' . $contact['id'];
$verify_token = random_string();
// Use a single verify token, even if multiple hubs
$verify_token = ((strlen($contact['hub-verify'])) ? $contact['hub-verify'] : random_string());
$params= 'hub.mode=subscribe&hub.callback=' . urlencode($push_url) . '&hub.topic=' . urlencode($contact['poll']) . '&hub.verify=async&hub.verify_token=' . $verify_token;
$r = q("UPDATE `contact` SET `hub-verify` = '%s' WHERE `id` = %d LIMIT 1",
dbesc($verify_token),
intval($contact['id'])
);
if(! strlen($contact['hub-verify'])) {
$r = q("UPDATE `contact` SET `hub-verify` = '%s' WHERE `id` = %d LIMIT 1",
dbesc($verify_token),
intval($contact['id'])
);
}
post_url($url,$params);
return;
}
}
function atom_author($tag,$name,$uri,$h,$w,$photo) {
$o = '';
if(! $tag)
return $o;
$name = xmlify($name);
$uri = xmlify($uri);
$h = intval($h);
$w = intval($w);
$photo = xmlify($photo);
$o .= "<$tag>\r\n";
$o .= "<name>$name</name>\r\n";
$o .= "<uri>$uri</uri>\r\n";
$o .= '<link rel="photo" type="image/jpeg" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n";
$o .= '<link rel="avatar" type="image/jpeg" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n";
$o .= "</$tag>\r\n";
return $o;
}
function atom_entry($item,$type,$author,$owner,$comment = false) {
if($item['deleted'])
return '<at:deleted-entry ref="' . xmlify($item['uri']) . '" when="' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '" />' . "\r\n";
$a = get_app();
$o = "\r\n\r\n<entry>\r\n";
if(is_array($author))
$o .= atom_author('author',$author['name'],$author['url'],80,80,$author['thumb']);
else
$o .= atom_author('author',$item['name'],$item['url'],80,80,$item['thumb']);
if(strlen($item['owner-name']))
$o .= atom_author('dfrn:owner',$item['owner-name'],$item['owner-link'],80,80,$item['owner-avatar']);
if($item['parent'] != $item['id'])
$o .= '<thr:in-reply-to ref="' . xmlify($item['parent-uri']) . '" type="text/html" href="' . xmlify($a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id']) . '" />' . "\r\n";
$o .= '<id>' . xmlify($item['uri']) . '</id>' . "\r\n";
$o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
$o .= '<published>' . xmlify(datetime_convert('UTC','UTC',$item['created'] . '+00:00',ATOM_TIME)) . '</published>' . "\r\n";
$o .= '<updated>' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '</updated>' . "\r\n";
$o .= '<content type="' . $type . '" >' . xmlify(($type === 'html') ? bbcode($item['body']) : $item['body']) . '</content>' . "\r\n";
$o .= '<link rel="alternate" href="' . xmlify($a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id']) . '" />' . "\r\n";
if($comment)
$o .= '<dfrn:comment-allow>' . intval($item['last-child']) . '</dfrn:comment-allow>' . "\r\n";
if($item['location'])
$o .= '<dfrn:location>' . xmlify($item['location']) . '</dfrn:location>' . "\r\n";
if($item['coord'])
$o .= '<georss:point>' . xmlify($item['coord']) . '</georss:point>' . "\r\n";
$verb = construct_verb($item);
$o .= '<as:verb>' . xmlify($verb) . '</as:verb>' . "\r\n";
$actobj = construct_activity($item);
if(strlen($actobj))
$o .= $actobj;
$mentioned = get_mentions($item);
if($mentioned)
$o .= $mentioned;
$o .= '</entry>' . "\r\n";
return $o;
}

View file

@ -1,5 +1,8 @@
<?php
if(! x($a->page,'nav'))
$a->page['nav'] = '';
$a->page['nav'] .= '<div id="panel" style="display: none;"></div>' ;
if(local_user()) {
@ -27,8 +30,12 @@ else {
$a->page['nav'] .= '<a id="nav-home-link" class="nav-commlink" href="profile/' . $a->user['nickname'] . '">'
. t('Home') . '</a><span id="home-update" class="nav-ajax-left"></span>' . "\r\n";
$a->page['nav'] .= '<a id="nav-notify-link" class="nav-commlink" href="notifications">' . t('Notifications')
. '</a><span id="notify-update" class="nav-ajax-left"></span>' . "\r\n";
// only show friend requests for normal pages. Other page types have automatic friendship.
if($_SESSION['page_flags'] == PAGE_NORMAL) {
$a->page['nav'] .= '<a id="nav-notify-link" class="nav-commlink" href="notifications">' . t('Notifications')
. '</a><span id="notify-update" class="nav-ajax-left"></span>' . "\r\n";
}
$a->page['nav'] .= '<a id="nav-messages-link" class="nav-commlink" href="message">' . t('Messages')
. '</a><span id="mail-update" class="nav-ajax-left"></span>' . "\r\n";

View file

@ -10,12 +10,10 @@
unset($db_host, $db_user, $db_pass, $db_data);
$debugging = get_config('system','debugging');
require_once("session.php");
require_once("datetime.php");
require_once('include/items.php');
require_once('include/bbcode.php');
if($argc < 3)
exit;
@ -34,10 +32,8 @@
break;
}
if($debugging)
dbg(3);
$recipients = array();
$url_recipients = array();
if($cmd === 'mail') {
@ -72,7 +68,7 @@
killme();
}
$r = q("SELECT `contact`.*, `user`.`nickname`
$r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, `user`.`page-flags`
FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
intval($uid)
@ -84,9 +80,13 @@
killme();
$hub = get_config('system','huburl');
// If this is a public conversation, notify the feed hub
$notify_hub = true;
// fill this in with a single salmon slap if applicable
$slap = '';
if($cmd != 'mail') {
require_once('include/group.php');
@ -105,8 +105,9 @@
if((strlen($parent['allow_cid']))
|| (strlen($parent['allow_gid']))
|| (strlen($parent['deny_cid']))
|| (strlen($parent['deny_gid'])))
|| (strlen($parent['deny_gid']))) {
$notify_hub = false; // private recipients, not public
}
$allow_people = expand_acl($parent['allow_cid']);
$allow_groups = expand_groups(expand_acl($parent['allow_gid']));
@ -118,8 +119,23 @@
foreach($items as $item) {
$recipients[] = $item['contact-id'];
$conversants[] = $item['contact-id'];
// pull out additional tagged people to notify (if public message)
if($notify_hub && strlen($item['inform'])) {
$people = explode(',',$item['inform']);
foreach($people as $person) {
if(substr($person,0,4) === 'cid:') {
$recipients[] = intval(substr($person,4));
$conversants[] = intval(substr($person,4));
}
else {
$url_recipients[] = substr($person,4);
}
}
}
}
logger('notifier: url_recipients' . print_r($url_recipients,true));
$conversants = array_unique($conversants,SORT_NUMERIC);
@ -128,8 +144,6 @@
$recipients = array_diff($recipients,$deny);
$conversant_str = dbesc(implode(', ',$conversants));
}
$r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0");
@ -138,19 +152,26 @@
killme();
$contacts = $r;
$tomb_template = load_view_file('view/atom_tomb.tpl');
$item_template = load_view_file('view/atom_item.tpl');
$cmnt_template = load_view_file('view/atom_cmnt.tpl');
}
$feed_template = load_view_file('view/atom_feed.tpl');
$mail_template = load_view_file('view/atom_mail.tpl');
$atom = '';
$hubxml = '';
$slaps = array();
$hubxml = ((strlen($hub)) ? '<link rel="hub" href="' . xmlify($hub) . '" />' . "\n" : '');
if(strlen($hub)) {
$hubs = explode(',', $hub);
if(count($hubs)) {
foreach($hubs as $h) {
$h = trim($h);
if(! strlen($h))
continue;
$hubxml .= '<link rel="hub" href="' . xmlify($h) . '" />' . "\n" ;
}
}
}
$atom .= replace_macros($feed_template, array(
'$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner['nickname'] ),
@ -169,6 +190,7 @@
if($cmd === 'mail') {
$notify_hub = false; // mail is not public
$atom .= replace_macros($mail_template, array(
'$name' => xmlify($owner['name']),
'$profile_page' => xmlify($owner['url']),
@ -184,99 +206,28 @@
if($followup) {
foreach($items as $item) { // there is only one item
$verb = construct_verb($item);
$actobj = construct_activity($item);
if($item['id'] == $item_id) {
$atom .= replace_macros($cmnt_template, array(
'$name' => xmlify($owner['name']),
'$profile_page' => xmlify($owner['url']),
'$thumb' => xmlify($owner['thumb']),
'$owner_name' => xmlify($item['owner-name']),
'$owner_profile_page' => xmlify($item['owner-link']),
'$owner_thumb' => xmlify($item['owner-avatar']),
'$item_id' => xmlify($item['uri']),
'$title' => xmlify($item['title']),
'$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME)),
'$location' => xmlify($item['location']),
'$type' => 'text',
'$verb' => xmlify($verb),
'$actobj' => $actobj,
'$alt' => xmlify($a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id']),
'$content' => xmlify($item['body']),
'$parent_id' => xmlify($item['parent-uri']),
'$comment_allow' => 0
));
$slap = atom_entry($item,'html',$owner,$owner,false);
$atom .= atom_entry($item,'text',$owner,$owner,false);
}
}
}
else {
foreach($items as $item) {
if($item['deleted']) {
$atom .= replace_macros($tomb_template, array(
'$id' => xmlify($item['uri']),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME))
));
}
else {
$contact = get_item_contact($item,$contacts);
if(! $contact)
continue;
$contact = get_item_contact($item,$contacts);
if(! $contact)
continue;
$verb = construct_verb($item);
$actobj = construct_activity($item);
if($item['parent'] == $item['id']) {
$atom .= replace_macros($item_template, array(
'$name' => xmlify($contact['name']),
'$profile_page' => xmlify($contact['url']),
'$thumb' => xmlify($contact['thumb']),
'$owner_name' => xmlify($item['owner-name']),
'$owner_profile_page' => xmlify($item['owner-link']),
'$owner_thumb' => xmlify($item['owner-avatar']),
'$item_id' => xmlify($item['uri']),
'$title' => xmlify($item['title']),
'$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME)),
'$location' => xmlify($item['location']),
'$type' => 'text',
'$verb' => xmlify($verb),
'$actobj' => $actobj,
'$content' => xmlify($item['body']),
'$alt' => xmlify($a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id']),
'$comment_allow' => (($item['last-child']) ? 1 : 0)
));
}
else {
$atom .= replace_macros($cmnt_template, array(
'$name' => xmlify($contact['name']),
'$profile_page' => xmlify($contact['url']),
'$thumb' => xmlify($contact['thumb']),
'$item_id' => xmlify($item['uri']),
'$title' => xmlify($item['title']),
'$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
'$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME)),
'$content' => xmlify($item['body']),
'$alt' => xmlify($a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id']),
'$location' => xmlify($item['location']),
'$type' => 'text',
'$verb' => xmlify($verb),
'$actobj' => $actobj,
'$parent_id' => xmlify($item['parent-uri']),
'$comment_allow' => (($item['last-child']) ? 1 : 0)
));
}
}
$atom .= atom_entry($item,'text',$contact,$owner,true);
$slaps[] = atom_entry($item,'html',$contact,$owner,true);
}
}
}
$atom .= '</feed>' . "\r\n";
if($debugging)
echo $atom;
logger('notifier: ' . $atom, LOGGER_DATA);
logger('notifier: slaps: ' . print_r($slaps,true), LOGGER_DATA);
if($followup)
$recip_str = $parent['contact-id'];
@ -284,7 +235,7 @@
$recip_str = implode(', ', $recipients);
$r = q("SELECT * FROM `contact` WHERE `id` IN ( %s ) ",
$r = q("SELECT * FROM `contact` WHERE `id` IN ( %s ) AND `blocked` = 0 ",
dbesc($recip_str)
);
if(! count($r))
@ -292,6 +243,8 @@
// delivery loop
require_once('include/salmon.php');
foreach($r as $contact) {
if($contact['self'])
continue;
@ -300,9 +253,25 @@
switch($contact['network']) {
case 'dfrn':
$deliver_status = dfrn_deliver($contact,$atom,$debugging);
logger('notifier: dfrndelivery: ' . $contact['name']);
$deliver_status = dfrn_deliver($owner,$contact,$atom);
break;
default:
if($followup) {
slapper($owner,$contact['notify'],$slap);
}
else {
// only send salmon if public - e.g. if it's ok to notify
// a public hub, it's ok to send a salmon
if(count($slaps) && $notify_hub) {
logger('notifier: slapdelivery: ' . $contact['name']);
foreach($slaps as $slappy) {
slapper($owner,$contact['notify'],$slappy);
}
}
}
break;
}
@ -311,13 +280,33 @@
intval($item_id)
);
}
}
// send additional slaps to mentioned remote tags (@foo@example.com)
if(count($slaps) && count($url_recipients) && $notify_hub) {
foreach($url_recipients as $url) {
logger('notifier: urldelivery: ' . $url);
foreach($slaps as $slappy) {
slapper($owner,$url,$slappy);
}
}
}
if((strlen($hub)) && ($notify_hub)) {
$params = 'hub.mode=publish&hub.url=' . urlencode($a->get_baseurl() . '/dfrn_poll/' . $owner['nickname'] );
post_url($hub,$params);
if($debugging) {
file_put_contents('pubsub.out', "\n\n" . "Pinged hub at " . datetime_convert() . "\n" . "Hub returned " . $a->get_curl_code() . "\n\n" , FILE_APPEND);
$hubs = explode(',', $hub);
if(count($hubs)) {
foreach($hubs as $h) {
$h = trim($h);
if(! strlen($h))
continue;
$params = 'hub.mode=publish&hub.url=' . urlencode($a->get_baseurl() . '/dfrn_poll/' . $owner['nickname'] );
post_url($h,$params);
logger('pubsub: publish: ' . $h . ' returned ' . $a->get_curl_code());
if(count($hubs) > 1)
sleep(7); // try and avoid multiple hubs responding at precisely the same time
}
}
}

View file

@ -14,15 +14,16 @@
require_once('datetime.php');
require_once('simplepie/simplepie.inc');
require_once('include/items.php');
require_once('include/Contact.php');
$debugging = get_config('system','debugging');
$a->set_baseurl(get_config('system','url'));
// 'stat' clause is a temporary measure until we have federation subscriptions working both directions
$contacts = q("SELECT * FROM `contact`
WHERE ( `dfrn-id` != '' OR (`issued-id` != '' AND `duplex` = 1))
WHERE ( ( `network` = 'dfrn' AND ( `dfrn-id` != '' OR (`issued-id` != '' AND `duplex` = 1)))
OR ( `network` = 'stat' AND `poll` != '' ) )
AND `self` = 0 AND `blocked` = 0 AND `readonly` = 0 ORDER BY RAND()");
if(! count($contacts))
@ -33,6 +34,14 @@
if($contact['priority'] || $contact['subhub']) {
$update = false;
// We should be getting everything via a hub. But just to be sure, let's check once a day.
// This also lets us update our subscription to the hub, and add or replace hubs in case it
// changed.
if($contact['subhub'])
$contact['priority'] = 3;
$t = $contact['last-update'];
switch ($contact['priority']) {
@ -54,13 +63,6 @@
break;
case 1:
default:
// if pubsub delivery is in effect, poll no more than once every hour.
// We shouldn't need to poll at all with pubsub, but the hub isn't
// always the most reliable postmaster... This way we still get the
// messages when the hub goes flaky, just perhaps a bit slower.
// At least it doesn't hurt to get them twice.
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 hour"))
$update = true;
break;
@ -87,80 +89,87 @@
: datetime_convert('UTC','UTC',$contact['last-update'], ATOM_TIME)
);
$idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
if($contact['network'] === 'dfrn') {
if(intval($contact['duplex']) && $contact['dfrn-id'])
$idtosend = '0:' . $orig_id;
if(intval($contact['duplex']) && $contact['issued-id'])
$idtosend = '1:' . $orig_id;
$idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
$url = $contact['poll'] . '?dfrn_id=' . $idtosend
. '&dfrn_version=' . DFRN_PROTOCOL_VERSION
. '&type=data&last_update=' . $last_update ;
if(intval($contact['duplex']) && $contact['dfrn-id'])
$idtosend = '0:' . $orig_id;
if(intval($contact['duplex']) && $contact['issued-id'])
$idtosend = '1:' . $orig_id;
$xml = fetch_url($url);
$url = $contact['poll'] . '?dfrn_id=' . $idtosend
. '&dfrn_version=' . DFRN_PROTOCOL_VERSION
. '&type=data&last_update=' . $last_update ;
$xml = fetch_url($url);
if($debugging) {
echo "URL: " . $url . "\n";
echo "XML: " . $xml . "\n";
}
if($debugging) {
echo "URL: " . $url . "\n";
echo "XML: " . $xml . "\n";
}
if(! $xml) {
// dead connection - might be a transient event, or this might
// mean the software was uninstalled or the domain expired.
// Will keep trying for one month.
mark_for_death($contact);
continue;
}
if(! $xml) {
// dead connection - might be a transient event, or this might
// mean the software was uninstalled or the domain expired.
// Will keep trying for one month.
mark_for_death($contact);
continue;
}
$res = simplexml_load_string($xml);
$res = simplexml_load_string($xml);
if(intval($res->status) == 1) {
// we may not be friends anymore. Will keep trying for one month.
mark_for_death($contact);
if(intval($res->status) == 1) {
// we may not be friends anymore. Will keep trying for one month.
mark_for_death($contact);
}
else {
if($contact['term-date'] != '0000-00-00 00:00:00')
unmark_for_death($contact);
}
if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id)))
continue;
$postvars = array();
$sent_dfrn_id = hex2bin($res->dfrn_id);
$challenge = hex2bin($res->challenge);
$final_dfrn_id = '';
if(($contact['duplex']) && strlen($contact['prvkey'])) {
openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']);
openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']);
}
else {
openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']);
openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']);
}
$final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
if(strpos($final_dfrn_id,':') == 1)
$final_dfrn_id = substr($final_dfrn_id,2);
if($final_dfrn_id != $orig_id) {
// did not decode properly - cannot trust this site
continue;
}
$postvars['dfrn_id'] = $idtosend;
$postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION;
$xml = post_url($contact['poll'],$postvars);
}
else {
if($contact['term-date'] != '0000-00-00 00:00:00')
unmark_for_death($contact);
// $contact['network'] !== 'dfrn'
$xml = fetch_url($contact['poll']);
}
if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id)))
continue;
$postvars = array();
$sent_dfrn_id = hex2bin($res->dfrn_id);
$challenge = hex2bin($res->challenge);
$final_dfrn_id = '';
if(($contact['duplex']) && strlen($contact['prvkey'])) {
openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']);
openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']);
}
else {
openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']);
openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']);
}
$final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
if(strpos($final_dfrn_id,':') == 1)
$final_dfrn_id = substr($final_dfrn_id,2);
if($final_dfrn_id != $orig_id) {
// did not decode properly - cannot trust this site
continue;
}
$postvars['dfrn_id'] = $idtosend;
$postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION;
$xml = post_url($contact['poll'],$postvars);
if($debugging) {
echo "XML response:" . $xml . "\n";
echo "Length:" . strlen($xml) . "\n";
@ -169,12 +178,18 @@
if(! strlen($xml))
continue;
consume_feed($xml,$importer,$contact,$hub);
if((strlen($hub)) && ($contact['rel'] == REL_BUD) && ($contact['priority'] == 0)) {
subscribe_to_hub($hub,$importer,$contact);
if((strlen($hub)) && (($contact['rel'] == REL_BUD) || (($contact['network'] === 'stat') && (! $contact['readonly']))) && ($contact['priority'] == 0)) {
$hubs = explode(',', $hub);
if(count($hubs)) {
foreach($hubs as $h) {
$h = trim($h);
if(! strlen($h))
continue;
subscribe_to_hub($h,$importer,$contact);
}
}
}
@ -183,7 +198,8 @@
intval($contact['id'])
);
}
// loop - next contact
}
killme();

View file

@ -16,3 +16,170 @@ function salmon_key($pubkey) {
return 'RSA' . '.' . $m . '.' . $e ;
}
function base64url_encode($s) {
return strtr(base64_encode($s),'+/','-_');
}
function base64url_decode($s) {
return base64_decode(strtr($s,'-_','+/'));
}
function get_salmon_key($uri,$keyhash) {
$ret = array();
logger('Fetching salmon key');
$arr = lrdd($uri);
if(is_array($arr)) {
foreach($arr as $a) {
if($a['@attributes']['rel'] === 'magic-public-key') {
$ret[] = $a['@attributes']['href'];
}
}
}
else {
return '';
}
// We have found at least one key URL
// If it's inline, parse it - otherwise get the key
if(count($ret)) {
for($x = 0; $x < count($ret); $x ++) {
if(substr($ret[$x],0,5) === 'data:') {
if(strstr($ret[$x],','))
$ret[$x] = substr($ret[$x],strpos($ret[$x],',')+1);
else
$ret[$x] = substr($ret[$x],5);
}
else
$ret[$x] = fetch_url($ret[$x]);
}
}
logger('Key located: ' . print_r($ret,true));
if(count($ret) == 1) {
// We only found one one key so we don't care if the hash matches.
// If it's the wrong key we'll find out soon enough because
// message verification will fail. This also covers some older
// software which don't supply a keyhash. As long as they only
// have one key we'll be right.
return $ret[0];
}
else {
foreach($ret as $a) {
$hash = base64url_encode(hash('sha256',$a));
if($hash == $keyhash)
return $a;
}
}
return '';
}
function slapper($owner,$url,$slap) {
logger('slapper called. Data: ' . $slap);
// does contact have a salmon endpoint?
if(! strlen($url))
return;
// add all namespaces to item
$namespaces = <<< EOT
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns:at="http://purl.org/atompub/tombstones/1.0"
xmlns:media="http://purl.org/syndication/atommedia"
xmlns:dfrn="http://purl.org/macgirvin/dfrn/1.0"
xmlns:as="http://activitystrea.ms/spec/1.0/"
xmlns:georss="http://www.georss.org/georss"
xmlns:poco="http://portablecontacts.net/spec/1.0" >
EOT;
$slap = str_replace('<entry>',$namespaces,$slap);
// create a magic envelope
$data = base64url_encode($slap);
$data_type = 'application/atom+xml';
$encoding = 'base64url';
$algorithm = 'RSA-SHA256';
$keyhash = base64url_encode(hash('sha256',salmon_key($owner['spubkey'])));
// Setup RSA stuff to PKCS#1 sign the data
set_include_path(get_include_path() . PATH_SEPARATOR . 'phpsec');
require_once('phpsec/Crypt/RSA.php');
$rsa = new CRYPT_RSA();
$rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
$rsa->setHash('sha256');
$rsa->loadKey($owner['sprvkey']);
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
$precomputed = '.YXBwbGljYXRpb24vYXRvbSt4bWw=.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
$signature = base64url_encode($rsa->sign($data . $precomputed));
$signature2 = base64url_encode($rsa->sign($data));
$salmon_tpl = load_view_file('view/magicsig.tpl');
$salmon = replace_macros($salmon_tpl,array(
'$data' => $data,
'$encoding' => $encoding,
'$algorithm' => $algorithm,
'$keyhash' => $keyhash,
'$signature' => $signature
));
// slap them
post_url($url,$salmon, array(
'Content-type: application/magic-envelope+xml',
'Content-length: ' . strlen($salmon)
));
$a = get_app();
$return_code = trim($a->get_curl_code());
// check for success, e.g. 2xx
if(substr($return_code,0,1) !== '2') {
// Entirely likely that their salmon implementation is
// non-compliant. Let's try once more, this time only signing
// the data, without the precomputed blob
$salmon = replace_macros($salmon_tpl,array(
'$data' => $data,
'$encoding' => $encoding,
'$algorithm' => $algorithm,
'$keyhash' => $keyhash,
'$signature' => $signature2
));
// slap them
post_url($url,$salmon, array(
'Content-type: application/magic-envelope+xml',
'Content-length: ' . strlen($salmon)
));
$return_code = trim($a->get_curl_code());
}
logger('slapper returned ' . $return_code);
return;
}

View file

@ -1,18 +1,25 @@
<?php
function can_write_wall(&$a,$owner) {
if((! (local_user())) && (! (remote_user())))
return false;
if((local_user()) && ($_SESSION['uid'] == $owner))
return true;
$uid = local_user();
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `id` = %d AND `blocked` = 0 AND `pending` = 0
AND `readonly` = 0 AND `rel` IN ( %d , %d ) LIMIT 1",
intval($owner),
intval($_SESSION['visitor_id']),
intval(REL_VIP),
intval(REL_BUD)
if(($uid) && ($uid == $owner)) {
return true;
}
$r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` LEFT JOIN `user` on `user`.`uid` = `contact`.`uid`
WHERE `contact`.`uid` = %d AND `contact`.`id` = %d AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `readonly` = 0 AND ( `contact`.`rel` IN ( %d , %d ) OR `user`.`page-flags` = %d ) LIMIT 1",
intval($owner),
intval($_SESSION['visitor_id']),
intval(REL_VIP),
intval(REL_BUD),
intval(PAGE_COMMUNITY)
);
if(count($r))
return true;
return false;

View file

@ -12,7 +12,7 @@ $install = ((file_exists('.htconfig.php')) ? false : true);
@include(".htconfig.php");
if(x($lang))
if(isset($lang) && strlen($lang))
load_translation_table($lang);
require_once("dba.php");
@ -31,9 +31,12 @@ $a->init_pagehead();
session_start();
if((x($_SESSION,'authenticated')) || (x($_POST['auth-params'])))
if((x($_SESSION,'authenticated')) || (x($_POST,'auth-params')))
require("auth.php");
if(! x($_SESSION,'sysmsg'))
$_SESSION['sysmsg'] = '';
if($install)
$a->module = 'install';
else
@ -71,7 +74,9 @@ if($a->module_loaded) {
if((! $a->error) && (function_exists($a->module . '_content'))) {
$func = $a->module . '_content';
$a->page['content'] .= $func($a);
if(! x($a->page,'content'))
$a->page['content'] = '';
$a->page['content'] .= $func($a);
}
}
@ -88,6 +93,7 @@ if(x($_SESSION,'sysmsg')) {
unset($_SESSION['sysmsg']);
}
// Feel free to comment out this line on production sites.
$a->page['content'] .= $debug_text;

View file

@ -186,7 +186,7 @@ class ASN_BASE {
case ASN_BOOLEAN:
return new ASN_BOOLEAN((bool)$data);
case ASN_INTEGER:
return new ASN_INTEGER(strtr(base64_encode($data),'+/=','-_,'));
return new ASN_INTEGER(strtr(base64_encode($data),'+/','-_'));
// return new ASN_INTEGER(ord($data));
case ASN_BIT_STR:
return new ASN_BIT_STR(self::parseASNString($data, $level+1, $maxLevels));

View file

@ -4,10 +4,20 @@ require_once('include/Contact.php');
function contacts_init(&$a) {
require_once('include/group.php');
if(! x($a->page,'aside'))
$a->page['aside'] = '';
$a->page['aside'] .= group_side();
if($a->config['register_policy'] != REGISTER_CLOSED)
$a->page['aside'] .= '<div class="side-invite-link-wrapper" id="side-invite-link-wrapper" ><a href="invite" class="side-invite-link" id="side-invite-link">' . t("Invite Friends") . '</a></div>';
$tpl = load_view_file('view/follow.tpl');
$a->page['aside'] .= replace_macros($tpl,array(
'$label' => t('Connect/Follow [profile address]'),
'$hint' => t('Example: bob@example.com, http://example.com/barbara'),
'$follow' => t('Follow')
));
}
function contacts_post(&$a) {
@ -21,7 +31,7 @@ function contacts_post(&$a) {
$orig_record = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($contact_id),
intval(get_uid())
intval(local_user())
);
if(! count($orig_record)) {
@ -34,7 +44,7 @@ function contacts_post(&$a) {
if($profile_id) {
$r = q("SELECT `id` FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($profile_id),
intval(get_uid())
intval(local_user())
);
if(! count($r)) {
notice( t('Could not locate selected profile.') . EOL);
@ -62,7 +72,7 @@ function contacts_post(&$a) {
intval($rating),
dbesc($reason),
intval($contact_id),
intval(get_uid())
intval(local_user())
);
if($r)
notice( t('Contact updated.') . EOL);
@ -76,7 +86,11 @@ function contacts_post(&$a) {
function contacts_content(&$a) {
$sort_type = 0;
$o = '';
$o .= '<script> $(document).ready(function() { $(\'#nav-contacts-link\').addClass(\'nav-selected\'); });</script>';
if(! local_user()) {
notice( t('Permission denied.') . EOL);
return;
@ -92,7 +106,7 @@ function contacts_content(&$a) {
$orig_record = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($contact_id),
intval(get_uid())
intval(local_user())
);
if(! count($orig_record)) {
@ -107,7 +121,7 @@ function contacts_content(&$a) {
$r = q("UPDATE `contact` SET `blocked` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($blocked),
intval($contact_id),
intval(get_uid())
intval(local_user())
);
if($r) {
notice( t('Contact has been ') . (($blocked) ? t('blocked') : t('unblocked')) . EOL );
@ -121,7 +135,7 @@ function contacts_content(&$a) {
$r = q("UPDATE `contact` SET `readonly` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($readonly),
intval($contact_id),
intval(get_uid())
intval(local_user())
);
if($r) {
notice( t('Contact has been ') . (($readonly) ? t('ignored') : t('unignored')) . EOL );
@ -142,7 +156,7 @@ function contacts_content(&$a) {
$contact_id = intval($a->argv[1]);
$r = q("SELECT * FROM `contact` WHERE `uid` = %d and `id` = %d LIMIT 1",
intval(get_uid()),
intval(local_user()),
intval($contact_id)
);
if(! count($r)) {
@ -150,6 +164,8 @@ function contacts_content(&$a) {
return;
}
$_SESSION['return_url'] = $a->get_baseurl() . '/' . $a->cmd;
require_once('view/contact_selectors.php');
$tpl = load_view_file("view/contact_edit.tpl");
@ -172,7 +188,7 @@ function contacts_content(&$a) {
break;
}
if($r[0]['rel'] != REL_FAN) {
if(($r[0]['network'] === 'dfrn') && ($r[0]['rel'])) {
$url = "redir/{$r[0]['id']}";
$sparkle = ' class="sparkle" ';
}
@ -186,10 +202,11 @@ function contacts_content(&$a) {
'$last_update' => (($r[0]['last-update'] == '0000-00-00 00:00:00')
? t('Never')
: datetime_convert('UTC',date_default_timezone_get(),$r[0]['last-update'],'D, j M Y, g:i A')),
'$profile_select' => contact_profile_assign($r[0]['profile-id']),
'$profile_select' => contact_profile_assign($r[0]['profile-id'],(($r[0]['network'] !== 'dfrn') ? true : false)),
'$contact_id' => $r[0]['id'],
'$block_text' => (($r[0]['blocked']) ? t('Unblock this contact') : t('Block this contact') ),
'$ignore_text' => (($r[0]['readonly']) ? t('Unignore this contact') : t('Ignore this contact') ),
'$insecure' => (($r[0]['network'] === 'dfrn') ? '' : load_view_file('view/insecure_net.tpl')),
'$blocked' => (($r[0]['blocked']) ? '<div id="block-message">' . t('Currently blocked') . '</div>' : ''),
'$ignored' => (($r[0]['readonly']) ? '<div id="ignore-message">' . t('Currently ignored') . '</div>' : ''),
'$rating' => contact_reputation($r[0]['rating']),
@ -271,8 +288,7 @@ function contacts_content(&$a) {
default:
break;
}
if($rr['rel'] != REL_FAN) {
if(($rr['network'] === 'dfrn') && ($rr['rel'])) {
$url = "redir/{$rr['id']}";
$sparkle = ' class="sparkle" ';
}

View file

@ -1,37 +1,68 @@
<?php
// There are two possible entry points. Both are called via POST.
// There are two possible entry points.
function dfrn_confirm_post(&$a) {
function dfrn_confirm_post(&$a,$handsfree = null) {
if($a->argc > 1)
$node = $a->argv[1];
if(is_array($handsfree)) {
// called directly from dfrn_request due to automatic friend acceptance
// any $_POST parameters we may require are supplied in the $handsfree array
$node = $handsfree['node'];
$a->interactive = false; // notice() becomes a no-op since nobody is there to see it
}
else {
if($a->argc > 1)
$node = $a->argv[1];
}
// Main entry point. Our user received a friend request notification (perhaps
// from another site) and clicked 'Accept'. $POST['source_url'] is not set.
// They will perform the following:
// from another site) and clicked 'Approve'. $POST['source_url'] is not set.
// OR we have been called directly from dfrn_request ($handsfree != null) due to
// this being a page type which supports automatic friend acceptance.
if(! x($_POST,'source_url')) {
$uid = get_uid();
$uid = ((is_array($handsfree)) ? $handsfree['uid'] : local_user());
if(! $uid) {
notice( t('Permission denied.') . EOL );
return;
}
// These come from the friend request notification form.
$dfrn_id = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : "");
$intro_id = intval($_POST['intro_id']);
$duplex = intval($_POST['duplex']);
$user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
intval($uid)
);
if(! $user) {
notice( t('Profile not found.') . EOL );
return;
}
// These come from either the friend request notification form or $handsfree array.
if(is_array($handsfree)) {
$dfrn_id = $handsfree['dfrn_id'];
$intro_id = $handsfree['intro_id'];
$duplex = $handsfree['duplex'];
}
else {
$dfrn_id = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : "");
$intro_id = intval($_POST['intro_id']);
$duplex = intval($_POST['duplex']);
$cid = intval($_POST['contact_id']);
}
// The other person will have been issued an ID when they first requested friendship.
// Locate their record. At this time, their record will have both pending and blocked set to 1.
// There won't be any dfrn_id if this is a network follower, so use the contact_id instead.
$r = q("SELECT * FROM `contact` WHERE `issued-id` = '%s' AND `uid` = %d LIMIT 1",
$r = q("SELECT * FROM `contact` WHERE ( ( `issued-id` != '' AND `issued-id` = '%s' ) OR ( `id` = %d AND `id` != 0 ) ) AND `uid` = %d LIMIT 1",
dbesc($dfrn_id),
intval($cid),
intval($uid)
);
@ -40,234 +71,248 @@ function dfrn_confirm_post(&$a) {
return;
}
$contact_id = $r[0]['id'];
$relation = $r[0]['rel'];
$site_pubkey = $r[0]['site-pubkey'];
$dfrn_confirm = $r[0]['confirm'];
$aes_allow = $r[0]['aes_allow'];
$contact = $r[0];
$contact_id = $contact['id'];
$relation = $contact['rel'];
$site_pubkey = $contact['site-pubkey'];
$dfrn_confirm = $contact['confirm'];
$aes_allow = $contact['aes_allow'];
// Generate a key pair for all further communications with this person.
// We have a keypair for every contact, and a site key for unknown people.
// This provides a means to carry on relationships with other people if
// any single key is compromised. It is a robust key. We're much more
// worried about key leakage than anybody cracking it.
if($contact['network'] === 'dfrn') {
$res = openssl_pkey_new(array(
'digest_alg' => 'whirlpool',
'private_key_bits' => 4096,
'encrypt_key' => false )
);
// Generate a key pair for all further communications with this person.
// We have a keypair for every contact, and a site key for unknown people.
// This provides a means to carry on relationships with other people if
// any single key is compromised. It is a robust key. We're much more
// worried about key leakage than anybody cracking it.
$res = openssl_pkey_new(array(
'digest_alg' => 'whirlpool',
'private_key_bits' => 4096,
'encrypt_key' => false )
);
$private_key = '';
$private_key = '';
openssl_pkey_export($res, $private_key);
openssl_pkey_export($res, $private_key);
$pubkey = openssl_pkey_get_details($res);
$public_key = $pubkey["key"];
$pubkey = openssl_pkey_get_details($res);
$public_key = $pubkey["key"];
// Save the private key. Send them the public key.
// Save the private key. Send them the public key.
$r = q("UPDATE `contact` SET `prvkey` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
dbesc($private_key),
intval($contact_id),
intval($uid)
);
$r = q("UPDATE `contact` SET `prvkey` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
dbesc($private_key),
intval($contact_id),
intval($uid)
);
$params = array();
// Per the protocol document, we will verify both ends by encrypting the dfrn_id with our
// site private key (person on the other end can decrypt it with our site public key).
// Then encrypt our profile URL with the other person's site public key. They can decrypt
// it with their site private key. If the decryption on the other end fails for either
// item, it indicates tampering or key failure on at least one site and we will not be
// able to provide a secure communication pathway.
// If other site is willing to accept full encryption, (aes_allow is 1 AND we have php5.3
// or later) then we encrypt the personal public key we send them using AES-256-CBC and a
// random key which is encrypted with their site public key.
$src_aes_key = random_string();
$result = '';
openssl_private_encrypt($dfrn_id,$result,$user[0]['prvkey']);
$params['dfrn_id'] = bin2hex($result);
$params['public_key'] = $public_key;
$params = array();
$my_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
// Per the protocol document, we will verify both ends by encrypting the dfrn_id with our
// site private key (person on the other end can decrypt it with our site public key).
// Then encrypt our profile URL with the other person's site public key. They can decrypt
// it with their site private key. If the decryption on the other end fails for either
// item, it indicates tampering or key failure on at least one site and we will not be
// able to provide a secure communication pathway.
openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey);
$params['source_url'] = bin2hex($params['source_url']);
// If other site is willing to accept full encryption, (aes_allow is 1 AND we have php5.3
// or later) then we encrypt the personal public key we send them using AES-256-CBC and a
// random key which is encrypted with their site public key.
$src_aes_key = random_string();
$result = '';
openssl_private_encrypt($dfrn_id,$result,$a->user['prvkey']);
$params['dfrn_id'] = bin2hex($result);
$params['public_key'] = $public_key;
$my_url = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey);
$params['source_url'] = bin2hex($params['source_url']);
if($aes_allow && function_exists('openssl_encrypt')) {
openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey);
$params['aes_key'] = bin2hex($params['aes_key']);
$params['public_key'] = bin2hex(openssl_encrypt($public_key,'AES-256-CBC',$src_aes_key));
}
$params['dfrn_version'] = DFRN_PROTOCOL_VERSION ;
if($duplex == 1)
$params['duplex'] = 1;
// POST all this stuff to the other site.
$res = post_url($dfrn_confirm,$params);
// Now figure out what they responded. Try to be robust if the remote site is
// having difficulty and throwing up errors of some kind.
$leading_junk = substr($res,0,strpos($res,'<?xml'));
$res = substr($res,strpos($res,'<?xml'));
if(! strlen($res)) {
// No XML at all, this exchange is messed up really bad.
// We shouldn't proceed, because the xml parser might choke,
// and $status is going to be zero, which indicates success.
// We can hardly call this a success.
notice( t('Response from remote site was not understood.') . EOL);
return;
}
if(strlen($leading_junk) && get_config('system','debugging')) {
// This might be more common. Mixed error text and some XML.
// If we're configured for debugging, show the text. Proceed in either case.
notice( t('Unexpected response from remote site: ') . EOL . $leading_junk . EOL );
}
$xml = simplexml_load_string($res);
$status = (int) $xml->status;
$message = unxmlify($xml->message); // human readable text of what may have gone wrong.
switch($status) {
case 0:
notice( t("Confirmation completed successfully.") . EOL);
if(strlen($message))
notice( t('Remote site reported: ') . $message . EOL);
break;
case 1:
// birthday paradox - generate new dfrn-id and fall through.
$new_dfrn_id = random_string();
$r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
dbesc($new_dfrn_id),
intval($contact_id),
intval($uid)
);
case 2:
notice( t("Temporary failure. Please wait and try again.") . EOL);
if(strlen($message))
notice( t('Remote site reported: ') . $message . EOL);
break;
case 3:
notice( t("Introduction failed or was revoked.") . EOL);
if(strlen($message))
notice( t('Remote site reported: ') . $message . EOL);
break;
if($aes_allow && function_exists('openssl_encrypt')) {
openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey);
$params['aes_key'] = bin2hex($params['aes_key']);
$params['public_key'] = bin2hex(openssl_encrypt($public_key,'AES-256-CBC',$src_aes_key));
}
if(($status == 0) && ($intro_id)) {
$params['dfrn_version'] = DFRN_PROTOCOL_VERSION ;
if($duplex == 1)
$params['duplex'] = 1;
// Success. Delete the notification.
// POST all this stuff to the other site.
$r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($intro_id),
intval($uid)
);
$res = post_url($dfrn_confirm,$params);
// Now figure out what they responded. Try to be robust if the remote site is
// having difficulty and throwing up errors of some kind.
$leading_junk = substr($res,0,strpos($res,'<?xml'));
$res = substr($res,strpos($res,'<?xml'));
if(! strlen($res)) {
// No XML at all, this exchange is messed up really bad.
// We shouldn't proceed, because the xml parser might choke,
// and $status is going to be zero, which indicates success.
// We can hardly call this a success.
notice( t('Response from remote site was not understood.') . EOL);
return;
}
if(strlen($leading_junk) && get_config('system','debugging')) {
// This might be more common. Mixed error text and some XML.
// If we're configured for debugging, show the text. Proceed in either case.
notice( t('Unexpected response from remote site: ') . EOL . $leading_junk . EOL );
}
$xml = simplexml_load_string($res);
$status = (int) $xml->status;
$message = unxmlify($xml->message); // human readable text of what may have gone wrong.
switch($status) {
case 0:
notice( t("Confirmation completed successfully.") . EOL);
if(strlen($message))
notice( t('Remote site reported: ') . $message . EOL);
break;
case 1:
// birthday paradox - generate new dfrn-id and fall through.
$new_dfrn_id = random_string();
$r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
dbesc($new_dfrn_id),
intval($contact_id),
intval($uid)
);
case 2:
notice( t("Temporary failure. Please wait and try again.") . EOL);
if(strlen($message))
notice( t('Remote site reported: ') . $message . EOL);
break;
case 3:
notice( t("Introduction failed or was revoked.") . EOL);
if(strlen($message))
notice( t('Remote site reported: ') . $message . EOL);
break;
}
if(($status == 0) && ($intro_id)) {
// Success. Delete the notification.
$r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($intro_id),
intval($uid)
);
}
if($status != 0)
return;
}
if($status != 0)
return;
// We have now established a relationship with the other site.
// Let's make our own personal copy of their profile photo so we don't have
// to always load it from their site.
require_once("Photo.php");
$photo_failure = false;
$photos = import_profile_photo($contact['photo'],$uid,$contact_id);
$r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1",
intval($contact_id));
if(count($r)) {
if($contact['network'] === 'dfrn') {
$filename = basename($r[0]['photo']);
$img_str = fetch_url($r[0]['photo'],true);
$img = new Photo($img_str);
if($img->is_valid()) {
$new_relation = REL_VIP;
if(($relation == REL_FAN) || ($duplex))
$new_relation = REL_BUD;
$img->scaleImageSquare(175);
$hash = photo_new_resource();
$r = q("UPDATE `contact` SET `photo` = '%s',
`thumb` = '%s',
`rel` = %d,
`name-date` = '%s',
`uri-date` = '%s',
`avatar-date` = '%s',
`blocked` = 0,
`pending` = 0,
`duplex` = %d,
`network` = 'dfrn' WHERE `id` = %d LIMIT 1
",
dbesc($photos[0]),
dbesc($photos[1]),
intval($new_relation),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($duplex),
intval($contact_id)
);
}
else {
$r = $img->store($uid, $contact_id, $hash, $filename, t('Contact Photos'), 4 );
$notify = '';
$poll = '';
if($r === false)
$photo_failure = true;
// $contact['network'] !== 'dfrn'
$img->scaleImage(80);
$r = $img->store($uid, $contact_id, $hash, $filename, t('Contact Photos'), 5 );
if($r === false)
$photo_failure = true;
$photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
$thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';
$arr = lrdd($contact['url']);
if(count($arr)) {
foreach($arr as $link) {
if($link['@attributes']['rel'] === 'salmon')
$notify = $link['@attributes']['href'];
if($link['@attributes']['rel'] === NAMESPACE_FEED)
$poll = $link['@attributes']['href'];
}
}
else
$photo_failure = true;
}
else
$photo_failure = true;
if($photo_failure) {
$photo = $a->get_baseurl() . '/images/default-profile.jpg';
$thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg';
$r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($intro_id),
intval($uid)
);
$r = q("UPDATE `contact` SET `photo` = '%s',
`thumb` = '%s',
`name-date` = '%s',
`uri-date` = '%s',
`avatar-date` = '%s',
`notify` = '%s',
`poll` = '%s',
`blocked` = 0,
`pending` = 0
WHERE `id` = %d LIMIT 1
",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($notify),
dbesc($poll),
intval($contact_id)
);
}
$new_relation = REL_VIP;
if(($relation == REL_FAN) || ($duplex))
$new_relation = REL_BUD;
$r = q("UPDATE `contact` SET `photo` = '%s',
`thumb` = '%s',
`rel` = %d,
`name-date` = '%s',
`uri-date` = '%s',
`avatar-date` = '%s',
`blocked` = 0,
`pending` = 0,
`duplex` = %d,
`network` = 'dfrn' WHERE `id` = %d LIMIT 1
",
dbesc($photo),
dbesc($thumb),
intval($new_relation),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($duplex),
intval($contact_id)
);
if($r === false)
notice( t('Unable to set contact photo.') . EOL);
notice( t('Unable to set contact photo.') . EOL);
// Let's send our user to the contact editor in case they want to
// do anything special with this new friend.
goaway($a->get_baseurl() . '/contacts/' . intval($contact_id));
if($handsfree === null)
goaway($a->get_baseurl() . '/contacts/' . intval($contact_id));
return; //NOTREACHED
}
@ -385,47 +430,19 @@ function dfrn_confirm_post(&$a) {
// We're good but now we have to scrape the profile photo and send notifications.
require_once("Photo.php");
$photo_failure = false;
$r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1",
intval($dfrn_record));
if(count($r)) {
$filename = basename($r[0]['photo']);
$img_str = fetch_url($r[0]['photo'],true);
$img = new Photo($img_str);
if($img->is_valid()) {
$img->scaleImageSquare(175);
$hash = photo_new_resource();
$r = $img->store($local_uid, $dfrn_record, $hash, $filename, t('Contact Photos') , 4);
if($r === false)
$photo_failure = true;
$img->scaleImage(80);
$r = $img->store($local_uid, $dfrn_record, $hash, $filename, t('Contact Photos') , 5);
if($r === false)
$photo_failure = true;
$photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
$thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';
}
else
$photo_failure = true;
}
if(count($r))
$photo = $r[0]['photo'];
else
$photo_failure = true;
if($photo_failure) {
$photo = $a->get_baseurl() . '/images/default-profile.jpg';
$thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg';
}
require_once("Photo.php");
$photos = import_profile_photo($photo,$local_uid,$dfrn_record);
$new_relation = REL_FAN;
if(($relation == REL_VIP) || ($duplex))
@ -443,8 +460,8 @@ function dfrn_confirm_post(&$a) {
`duplex` = %d,
`network` = 'dfrn' WHERE `id` = %d LIMIT 1
",
dbesc($photo),
dbesc($thumb),
dbesc($photos[0]),
dbesc($photos[1]),
intval($new_relation),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
@ -452,7 +469,7 @@ function dfrn_confirm_post(&$a) {
intval($duplex),
intval($dfrn_record)
);
if($r === false) { // indicates schema is messed up or total db failure
if($r === false) { // indicates schema is messed up or total db failure
$message = t('Unable to update your contact profile details on our system');
xml_status(3,$message);
}

View file

@ -34,7 +34,7 @@ function dfrn_notify_post(&$a) {
$sql_extra = '';
switch($direction) {
case (-1):
$sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($dfrn_id));
$sql_extra = sprintf(" AND ( `issued-id` = '%s' OR `dfrn-id` = '%s' ) ", dbesc($dfrn_id), dbesc($dfrn_id));
break;
case 0:
$sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
@ -50,7 +50,9 @@ function dfrn_notify_post(&$a) {
$r = q("SELECT `contact`.*, `contact`.`uid` AS `importer_uid`, `user`.* FROM `contact`
LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0 $sql_extra LIMIT 1"
WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `user`.`nickname` = '%s' $sql_extra LIMIT 1",
dbesc($a->argv[1])
);
if(! count($r)) {
@ -111,6 +113,14 @@ function dfrn_notify_post(&$a) {
require_once('bbcode.php');
if($importer['notify-flags'] & NOTIFY_MAIL) {
$body = html_entity_decode(strip_tags(bbcode(stripslashes($msg['body']))),ENT_QUOTES,'UTF-8');
if(function_exists('quoted_printable_encode'))
$body = quoted_printable_encode($body);
else
$body = qp($body);
$tpl = load_view_file('view/mail_received_eml.tpl');
$email_tpl = replace_macros($tpl, array(
'$sitename' => $a->config['sitename'],
@ -119,11 +129,15 @@ function dfrn_notify_post(&$a) {
'$email' => $importer['email'],
'$from' => $msg['from-name'],
'$title' => stripslashes($msg['title']),
'$body' => strip_tags(bbcode(stripslashes($msg['body'])))
'$body' => $body
));
$res = mail($importer['email'], t('New mail received at ') . $a->config['sitename'],
$email_tpl, 'From: ' . t('Administrator') . '@' . $a->get_hostname() );
$email_tpl, 'From: ' . t('Administrator') . '@' . $a->get_hostname() . "\r\n"
. 'MIME-Version: 1.0' . "\r\n"
. 'Content-type: text/plain; charset=UTF-8' . "\r\n"
. 'Content-transfer-encoding: quoted-printable' . "\r\n"
);
}
xml_status(0);
// NOTREACHED
@ -203,7 +217,7 @@ function dfrn_notify_post(&$a) {
if($is_reply) {
if($feed->get_item_quantity() == 1) {
// remote reply to our post. Import and then notify everybody else.
$datarray = get_atom_elements($item);
$datarray = get_atom_elements($feed,$item);
$datarray['type'] = 'remote-comment';
$datarray['wall'] = 1;
$datarray['parent-uri'] = $parent_uri;
@ -285,7 +299,7 @@ function dfrn_notify_post(&$a) {
}
continue;
}
$datarray = get_atom_elements($item);
$datarray = get_atom_elements($feed,$item);
$datarray['parent-uri'] = $parent_uri;
$datarray['uid'] = $importer['importer_uid'];
$datarray['contact-id'] = $importer['id'];
@ -352,7 +366,7 @@ function dfrn_notify_post(&$a) {
}
$datarray = get_atom_elements($item);
$datarray = get_atom_elements($feed,$item);
$datarray['parent-uri'] = $item_id;
$datarray['uid'] = $importer['importer_uid'];
$datarray['contact-id'] = $importer['id'];
@ -401,7 +415,7 @@ function dfrn_notify_content(&$a) {
$sql_extra = '';
switch($direction) {
case (-1):
$sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($dfrn_id));
$sql_extra = sprintf(" AND ( `issued-id` = '%s' OR `dfrn-id` = '%s' ) ", dbesc($dfrn_id), dbesc($dfrn_id));
$my_id = $dfrn_id;
break;
case 0:
@ -417,7 +431,10 @@ function dfrn_notify_content(&$a) {
break; // NOTREACHED
}
$r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 $sql_extra LIMIT 1");
$r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `user`.`nickname` = '%s' $sql_extra LIMIT 1",
dbesc($a->argv[1])
);
if(! count($r))
$status = 1;
@ -426,7 +443,7 @@ function dfrn_notify_content(&$a) {
$encrypted_id = '';
$id_str = $my_id . '.' . mt_rand(1000,9999);
if(($r[0]['duplex']) && strlen($r[0]['pubkey'])) {
if((($r[0]['duplex']) && strlen($r[0]['pubkey'])) || (! strlen($r[0]['prvkey']))) {
openssl_public_encrypt($hash,$challenge,$r[0]['pubkey']);
openssl_public_encrypt($id_str,$encrypted_id,$r[0]['pubkey']);
}

View file

@ -6,16 +6,11 @@ require_once('include/auth.php');
function dfrn_poll_init(&$a) {
$dfrn_id = '';
if(x($_GET,'dfrn_id'))
$dfrn_id = $_GET['dfrn_id'];
if(x($_GET,'type'))
$type = $_GET['type'];
if(x($_GET,'last_update'))
$last_update = $_GET['last_update'];
$dfrn_version = (float) $_GET['dfrn_version'] ;
$destination_url = ((x($_GET,'destination_url')) ? $_GET['destination_url'] : '');
$dfrn_id = ((x($_GET,'dfrn_id')) ? $_GET['dfrn_id'] : '');
$type = ((x($_GET,'type')) ? $_GET['type'] : '');
$last_update = ((x($_GET,'last_update')) ? $_GET['last_update'] : '');
$destination_url = ((x($_GET,'destination_url')) ? $_GET['destination_url'] : '');
$dfrn_version = ((x($_GET,'dfrn_version')) ? (float) $_GET['dfrn_version'] : 0);
$direction = (-1);
@ -23,7 +18,7 @@ function dfrn_poll_init(&$a) {
if(strpos($dfrn_id,':') == 1) {
$direction = intval(substr($dfrn_id,0,1));
$dfrn_id = substr($dfrn_id,2);
$dfrn_id = substr($dfrn_id,2);
}
if(($dfrn_id === '') && (! x($_POST,'dfrn_id')) && ($a->argc > 1)) {
@ -33,12 +28,12 @@ function dfrn_poll_init(&$a) {
killme();
}
if((x($type)) && ($type === 'profile')) {
if((isset($type)) && ($type === 'profile')) {
$sql_extra = '';
switch($direction) {
case (-1):
$sql_extra = sprintf(" AND `dfrn-id` = '%s' ", dbesc($dfrn_id));
$sql_extra = sprintf(" AND ( `dfrn-id` = '%s' OR `issued-id` = '%s' ) ", dbesc($dfrn_id),dbesc($dfrn_id));
$my_id = $dfrn_id;
break;
case 0:
@ -56,7 +51,10 @@ function dfrn_poll_init(&$a) {
$r = q("SELECT `contact`.*, `user`.`nickname`
FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0 $sql_extra LIMIT 1");
WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `user`.`nickname` = '%s' $sql_extra LIMIT 1",
dbesc($a->argv[1])
);
if(count($r)) {
@ -86,7 +84,7 @@ function dfrn_poll_init(&$a) {
}
if((x($type)) && ($type === 'profile-check')) {
if((isset($type)) && ($type === 'profile-check')) {
switch($direction) {
case 1:
@ -116,15 +114,15 @@ function dfrn_poll_init(&$a) {
function dfrn_poll_post(&$a) {
$dfrn_id = $_POST['dfrn_id'];
$challenge = $_POST['challenge'];
$url = $_POST['url'];
$dfrn_version = (float) $_POST['dfrn_version'];
$dfrn_id = ((x($_POST,'dfrn_id')) ? $_POST['dfrn_id'] : '');
$challenge = ((x($_POST,'challenge')) ? $_POST['challenge'] : '');
$url = ((x($_POST,'url')) ? $_POST['url'] : '');
$dfrn_version = ((x($_POST,'dfrn_version')) ? (float) $_POST['dfrn_version'] : 0);
$direction = (-1);
if(strpos($dfrn_id,':') == 1) {
$direction = intval(substr($dfrn_id,0,1));
$dfrn_id = substr($dfrn_id,2);
$dfrn_id = substr($dfrn_id,2);
}

View file

@ -44,8 +44,8 @@ function dfrn_request_post(&$a) {
if(x($dfrn_url)) {
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
intval(get_uid()),
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `self` = 0 LIMIT 1",
intval(local_user()),
dbesc($dfrn_url)
);
@ -96,13 +96,14 @@ function dfrn_request_post(&$a) {
dbesc_array($parms);
$r = q("INSERT INTO `contact` ( `uid`, `created`,`url`, `name`, `photo`, `site-pubkey`,
$r = q("INSERT INTO `contact` ( `uid`, `created`,`url`, `name`, `nick`, `photo`, `site-pubkey`,
`request`, `confirm`, `notify`, `poll`, `aes_allow`)
VALUES ( %d, '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', %d)",
intval(get_uid()),
VALUES ( %d, '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)",
intval(local_user()),
datetime_convert(),
dbesc($dfrn_url),
$parms['fn'],
$parms['nick'],
$parms['photo'],
$parms['key'],
$parms['dfrn-request'],
@ -198,7 +199,7 @@ function dfrn_request_post(&$a) {
if($network === 'dfrn') {
$ret = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
$ret = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `self` = 0 LIMIT 1",
intval($uid),
dbesc($url)
);
@ -208,11 +209,16 @@ function dfrn_request_post(&$a) {
notice( t('You have already introduced yourself here.') . EOL );
return;
}
elseif($ret[0]['rel'] == REL_BUD) {
notice( t('Apparently you are already friends with .') . $a->profile['name'] . EOL);
return;
}
else {
$contact_record = $ret[0];
$parms = array('dfrn-request' => $ret[0]['request']);
}
}
$issued_id = random_string();
if(is_array($contact_record)) {
@ -266,13 +272,14 @@ function dfrn_request_post(&$a) {
dbesc_array($parms);
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `name`, `issued-id`, `photo`, `site-pubkey`,
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `name`, `nick`, `issued-id`, `photo`, `site-pubkey`,
`request`, `confirm`, `notify`, `poll` )
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
intval($uid),
datetime_convert(),
$parms['url'],
$parms['fn'],
$parms['nick'],
$parms['issued-id'],
$parms['photo'],
$parms['key'],
@ -314,8 +321,7 @@ function dfrn_request_post(&$a) {
);
}
// This notice will only be seen by the requestor if the requestor and requestee are on the same server.
// This notice will only be seen by the requestor if the requestor and requestee are on the same server.
if(! $failed)
notice( t('Your introduction has been sent.') . EOL );
@ -417,9 +423,13 @@ function dfrn_request_content(&$a) {
WHERE `contact`.`id` = %d LIMIT 1",
intval($intro[0]['contact-id'])
);
if(count($r)) {
if($r[0]['notify-flags'] & NOTIFY_INTRO) {
$auto_confirm = false;
if(count($r)) {
if($r[0]['page-flags'] != PAGE_NORMAL)
$auto_confirm = true;
if(($r[0]['notify-flags'] & NOTIFY_INTRO) && (! $auto_confirm)) {
$email_tpl = load_view_file('view/request_notify_eml.tpl');
$email = replace_macros($email_tpl, array(
'$requestor' => ((strlen(stripslashes($r[0]['name']))) ? stripslashes($r[0]['name']) : t('[Name Withheld]')),
@ -434,22 +444,45 @@ function dfrn_request_content(&$a) {
'From: ' . t('Administrator') . '@' . $_SERVER[SERVER_NAME] );
// This is a redundant notification - no point throwing errors if it fails.
}
if($auto_confirm) {
require_once('mod/dfrn_confirm.php');
$handsfree = array(
'uid' => $r[0]['uid'],
'node' => $r[0]['nickname'],
'dfrn_id' => $r[0]['issued-id'],
'intro_id' => $intro[0]['id'],
'duplex' => (($r[0]['page-flags'] == PAGE_FREELOVE) ? 1 : 0)
);
dfrn_confirm_post($a,$handsfree);
}
}
$r = q("UPDATE `intro` SET `blocked` = 0 WHERE `hash` = '%s' LIMIT 1",
dbesc($_GET['confirm_key'])
);
if(! $auto_confirm) {
// If we are auto_confirming, this record will have already been nuked
// in dfrn_confirm_post()
$r = q("UPDATE `intro` SET `blocked` = 0 WHERE `hash` = '%s' LIMIT 1",
dbesc($_GET['confirm_key'])
);
}
}
killme();
return; // NOTREACHED
}
else {
$myaddr = ((x($_GET,'address')) ? urldecode($_GET['address']) : '');
// Normal web request. Display our user's introduction form.
$o = load_view_file("view/dfrn_request.tpl");
$o = replace_macros($o,array('$nickname' => $a->argv[1]));
if($a->profile['page-flags'] == PAGE_NORMAL)
$tpl = load_view_file('view/dfrn_request.tpl');
else
$tpl = load_view_file('view/auto_request.tpl');
$o .= replace_macros($tpl,array(
'$nickname' => $a->argv[1],
'$name' => $a->profile['name'],
'$myaddr' => $myaddr
));
return $o;
}

View file

@ -4,11 +4,12 @@ function directory_init(&$a) {
}
function directory_content(&$a) {
$o = '';
$o .= '<script> $(document).ready(function() { $(\'#nav-directory-link\').addClass(\'nav-selected\'); });</script>';
$search = ((x($_GET,'search')) ? notags(trim($_GET['search'])) : '');
$tpl .= load_view_file('view/directory_header.tpl');
$tpl = load_view_file('view/directory_header.tpl');
$globaldir = '';
$gdirpath = dirname(get_config('system','directory_submit_url'));

View file

@ -57,7 +57,7 @@ function display_content(&$a) {
// Profile owner - everything is visible
if(local_user() && (get_uid() == $a->profile['uid'])) {
if(local_user() && (local_user() == $a->profile['uid'])) {
$sql_extra = '';
}
@ -86,7 +86,7 @@ function display_content(&$a) {
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`network`, `contact`.`thumb`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
@ -113,43 +113,21 @@ function display_content(&$a) {
if(count($r)) {
foreach($r as $item) {
$sparkle = '';
if(($item['verb'] == ACTIVITY_LIKE) && ($item['id'] != $item['parent'])) {
$url = $item['url'];
if(($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'])) {
$url = $a->get_baseurl() . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle"';
}
if(! is_array($alike[$item['parent'] . '-l']))
$alike[$item['parent'] . '-l'] = array();
$alike[$item['parent']] ++;
$alike[$item['parent'] . '-l'][] = '<a href="'. $url . '"' . $sparkle . '>' . $item['name'] . '</a>';
}
if(($item['verb'] == ACTIVITY_DISLIKE) && ($item['id'] != $item['parent'])) {
$url = $item['url'];
if(($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'])) {
$url = $a->get_baseurl() . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle"';
}
if(! is_array($dlike[$item['parent'] . '-l']))
$dlike[$item['parent'] . '-l'] = array();
$dlike[$item['parent']] ++;
$dlike[$item['parent'] . '-l'][] = '<a href="'. $url . '"' . $sparkle . '>' . $item['name'] . '</a>';
}
like_puller($a,$item,$alike,'like');
like_puller($a,$item,$dlike,'dislike');
}
foreach($r as $item) {
$comment = '';
$template = $tpl;
$redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
if((($item['verb'] == ACTIVITY_LIKE) || ($item['verb'] == ACTIVITY_DISLIKE)) && ($item['id'] != $item['parent']))
if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE)))
&& ($item['id'] != $item['parent']))
continue;
$lock = (($item['uid'] == get_uid()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
$lock = (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))
? '<div class="wall-item-lock"><img src="images/lock_icon.gif" class="lockview" alt="' . t('Private Message') . '" onclick="lockview(event,' . $item['id'] . ');" /></div>'
: '<div class="wall-item-lock"></div>');
@ -180,7 +158,7 @@ function display_content(&$a) {
$redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
if(($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'] )) {
if(($item['network'] === 'dfrn') && (! $item['self'] )) {
$profile_url = $redirect_url;
$sparkle = ' sparkle';
}
@ -209,7 +187,7 @@ function display_content(&$a) {
$template = $wallwall;
$commentww = 'ww';
// If it is our contact, use a friendly redirect link
if(($item['owner-link'] == $item['url']) && ($item['rel'] == REL_VIP || $item['rel'] == REL_BUD)) {
if(($item['owner-link'] == $item['url']) && ($item['network'] === 'dfrn')) {
$owner_url = $redirect_url;
$osparkle = ' sparkle';
}
@ -222,14 +200,21 @@ function display_content(&$a) {
$profile_avatar = ((strlen($item['author-avatar'])) ? $item['author-avatar'] : $item['thumb']);
$profile_link = $profile_url;
if(($item['contact-id'] == $_SESSION['visitor_id']) || ($item['uid'] == get_uid()))
if(($item['contact-id'] == $_SESSION['visitor_id']) || ($item['uid'] == local_user()))
$drop = replace_macros(load_view_file('view/wall_item_drop.tpl'), array('$id' => $item['id']));
else
$drop = replace_macros(load_view_file('view/wall_fake_drop.tpl'), array('$id' => $item['id']));
$like = (($alike[$item['id']]) ? format_like($alike[$item['id']],$alike[$item['id'] . '-l'],'like',$item['id']) : '');
$dislike = (($dlike[$item['id']]) ? format_like($dlike[$item['id']],$dlike[$item['id'] . '-l'],'dislike',$item['id']) : '');
$location = (($item['location']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['location']) . '">' . $item['location'] . '</a>' : '');
$coord = (($item['coord']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['coord']) . '">' . $item['coord'] . '</a>' : '');
if($coord) {
if($location)
$location .= '<br /><span class="smalltext">(' . $coord . ')</span>';
else
$location = '<span class="smalltext">' . $coord . '</span>';
}
$o .= replace_macros($template,array(
'$id' => $item['item_id'],
@ -242,7 +227,7 @@ function display_content(&$a) {
'$body' => bbcode($item['body']),
'$ago' => relative_date($item['created']),
'$lock' => $lock,
'$location' => (($item['location']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['location']) . '">' . $item['location'] . '</a>' : ''),
'$location' => $location,
'$indent' => (($item['parent'] != $item['item_id']) ? ' comment' : ''),
'$owner_url' => $owner_url,
'$owner_photo' => $owner_photo,

170
mod/follow.php Normal file
View file

@ -0,0 +1,170 @@
<?php
require_once('Scrape.php');
function follow_post(&$a) {
if(! local_user()) {
notice( t('Permission denied.') . EOL);
goaway($_SESSION['return_url']);
// NOTREACHED
}
$url = notags(trim($_POST['url']));
if($url) {
$links = lrdd($url);
if(count($links)) {
foreach($links as $link) {
if($link['@attributes']['rel'] === NAMESPACE_DFRN)
$dfrn = $link['@attributes']['href'];
if($link['@attributes']['rel'] === 'salmon')
$notify = $link['@attributes']['href'];
if($link['@attributes']['rel'] === NAMESPACE_FEED)
$poll = $link['@attributes']['href'];
if($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard')
$hcard = $link['@attributes']['href'];
if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page')
$profile = $link['@attributes']['href'];
}
}
}
// If we find a DFRN site, send our subscriber to the other person's
// dfrn_request page and all the other details will get sorted.
if(strlen($dfrn)) {
$ret = scrape_dfrn($dfrn);
if(is_array($ret) && x($ret,'dfrn-request')) {
if(strlen($a->path))
$myaddr = urlencode($a->get_baseurl() . '/profile/' . $a->user['nickname']);
else
$myaddr = urlencode($a->user['nickname'] . '@' . $a->get_hostname());
goaway($ret['dfrn-request'] . "&address=$myaddr");
// NOTREACHED
}
}
if($hcard) {
$vcard = scrape_vcard($hcard);
}
if(! $profile)
$profile = $url;
// do we have enough information?
if(! x($vcard,'fn'))
if(x($vcard,'nick'))
$vcard['fn'] = $vcard['nick'];
if(! ((x($vcard['fn'])) && ($poll) && ($notify) && ($profile))) {
notice( t('The profile address specified does not provide adequate information.') . EOL);
goaway($_SESSION['return_url']);
}
if(! x($vcard,'photo'))
$vcard['photo'] = $a->get_baseurl() . '/images/default-profile.jpg' ;
// check if we already have a contact
// the poll url is more reliable than the profile url, as we may have
// indirect links or webfinger links
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `poll` = '%s' LIMIT 1",
intval(local_user()),
dbesc($poll)
);
if(count($r)) {
// update contact
if($r[0]['rel'] == REL_VIP) {
q("UPDATE `contact` SET `rel` = %d , `readonly` = 0 WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(REL_BUD),
intval($r[0]['id']),
intval(local_user())
);
}
}
else {
// create contact record
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `notify`, `poll`, `name`, `nick`, `photo`, `network`, `rel`,
`blocked`, `readonly`, `pending` )
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 0 ) ",
intval(local_user()),
dbesc(datetime_convert()),
dbesc($profile),
dbesc($notify),
dbesc($poll),
dbesc($vcard['fn']),
dbesc($vcard['nick']),
dbesc($vcard['photo']),
dbesc('stat'),
intval(REL_FAN)
);
}
$r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
dbesc($profile),
intval(local_user())
);
if(! count($r)) {
notice( t('Unable to retrieve contact information.') . EOL);
goaway($_SESSION['return_url']);
// NOTREACHED
}
$contact = $r[0];
$contact_id = $r[0]['id'];
require_once("Photo.php");
$photos = import_profile_photo($vcard['photo'],local_user(),$contact_id);
$r = q("UPDATE `contact` SET `photo` = '%s',
`thumb` = '%s',
`name-date` = '%s',
`uri-date` = '%s',
`avatar-date` = '%s'
WHERE `id` = %d LIMIT 1
",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($contact_id)
);
// pull feed and consume it, which should subscribe to the hub.
// create a follow slap
$tpl = load_view_file('view/follow_slap.tpl');
$slap = replace_macros($tpl, array(
'$name' => $a->user['username'],
'$profile_page' => $a->get_baseurl() . '/profile/' . $a->user['nickname'],
'$photo' => $a->contact['photo'],
'$thumb' => $a->contact['thumb'],
'$published' => datetime_convert('UTC','UTC', 'now', ATOM_TIME),
'$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':follow:' . random_string(),
'$title' => '',
'$type' => 'text',
'$content' => t('following'),
'$nick' => $a->user['nickname'],
'$verb' => ACTIVITY_FOLLOW
));
$r = q("SELECT `contact`.*, `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
WHERE `user`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
intval(local_user())
);
require_once('include/salmon.php');
slapper($r[0],$contact['notify'],$slap);
goaway($_SESSION['return_url']);
// NOTREACHED
}

View file

@ -22,10 +22,10 @@ function group_post(&$a) {
if(($a->argc == 2) && ($a->argv[1] === 'new')) {
$name = notags(trim($_POST['groupname']));
$r = group_add(get_uid(),$name);
$r = group_add(local_user(),$name);
if($r) {
notice( t('Group created.') . EOL );
$r = group_byname(get_uid(),$name);
$r = group_byname(local_user(),$name);
if($r)
goaway($a->get_baseurl() . '/group/' . $r);
}
@ -37,7 +37,7 @@ function group_post(&$a) {
if(($a->argc == 2) && (intval($a->argv[1]))) {
$r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($a->argv[1]),
intval(get_uid())
intval(local_user())
);
if(! count($r)) {
notice( t('Group not found.') . EOL );
@ -49,7 +49,7 @@ function group_post(&$a) {
if((strlen($groupname)) && ($groupname != $group['name'])) {
$r = q("UPDATE `group` SET `name` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1",
dbesc($groupname),
intval(get_uid()),
intval(local_user()),
intval($group['id'])
);
if($r)
@ -59,14 +59,14 @@ function group_post(&$a) {
array_walk($members,'validate_members');
$r = q("DELETE FROM `group_member` WHERE `gid` = %d AND `uid` = %d",
intval($a->argv[1]),
intval(get_uid())
intval(local_user())
);
$result = true;
if(count($members)) {
foreach($members as $member) {
$r = q("INSERT INTO `group_member` ( `uid`, `gid`, `contact-id`)
VALUES ( %d, %d, %d )",
intval(get_uid()),
intval(local_user()),
intval($group['id']),
intval($member)
);
@ -98,10 +98,10 @@ function group_content(&$a) {
if(intval($a->argv[2])) {
$r = q("SELECT `name` FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($a->argv[2]),
intval(get_uid())
intval(local_user())
);
if(count($r))
$result = group_rmv(get_uid(),$r[0]['name']);
$result = group_rmv(local_user(),$r[0]['name']);
if($result)
notice( t('Group removed.') . EOL);
else
@ -116,7 +116,7 @@ function group_content(&$a) {
require_once('view/acl_selectors.php');
$r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($a->argv[1]),
intval(get_uid())
intval(local_user())
);
if(! count($r)) {
notice( t('Group not found.') . EOL );
@ -136,12 +136,14 @@ function group_content(&$a) {
'$delete' => t('Delete')
));
$celeb = ((($a->user['page-flags'] == PAGE_SOAPBOX) || ($a->user['page-flags'] == PAGE_COMMUNITY)) ? true : false);
$tpl = load_view_file('view/group_edit.tpl');
$o .= replace_macros($tpl, array(
'$gid' => $group['id'],
'$name' => $group['name'],
'$drop' => $drop_txt,
'$selector' => contact_select('group_members_select','group_members_select',$preselected,25)
'$selector' => contact_select('group_members_select','group_members_select',$preselected,25,false,$celeb)
));
}

View file

@ -13,6 +13,9 @@ function home_init(&$a) {
if(! function_exists('home_content')) {
function home_content(&$a) {
$o = '';
if(! (x($a->page,'footer')))
$a->page['footer'] = '';
$a->page['footer'] .= "<div class=\"powered\" >Powered by <a href=\"http://mistpark.com\" name=\"mistpark\" >mistpark</a></div>";
$o .= '<h1>Welcome' . ((x($a->config,'sitename')) ? " to {$a->config['sitename']}" : "" ) . '</h1>';
if(file_exists('home.html'))

View file

@ -14,8 +14,7 @@ function item_post(&$a) {
require_once('include/security.php');
$uid = $_SESSION['uid'];
$uid = local_user();
$parent = ((x($_POST,'parent')) ? intval($_POST['parent']) : 0);
@ -57,6 +56,7 @@ function item_post(&$a) {
$title = notags(trim($_POST['title']));
$body = escape_tags(trim($_POST['body']));
$location = notags(trim($_POST['location']));
$coord = notags(trim($_POST['coord']));
$verb = notags(trim($_POST['verb']));
if(! strlen($body)) {
@ -113,6 +113,64 @@ function item_post(&$a) {
}
}
$str_tags = '';
$inform = '';
$tags = get_tags($body);
if(count($tags)) {
foreach($tags as $tag) {
if(strpos($tag,'@') === 0) {
$name = substr($tag,1);
if((strpos($name,'@')) || (strpos($name,'http://'))) {
$newname = $name;
$links = @lrdd($name);
if(count($links)) {
foreach($links as $link) {
if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page')
$profile = $link['@attributes']['href'];
if($link['@attributes']['rel'] === 'salmon') {
if(strlen($inform))
$inform .= ',';
$inform .= 'url:' . str_replace(',','%2c',$link['@attributes']['href']);
}
}
}
}
else {
$newname = $name;
if(strstr($name,'_')) {
$newname = str_replace('_',' ',$name);
$r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
dbesc($newname),
intval($profile_uid)
);
}
else {
$r = q("SELECT * FROM `contact` WHERE `nick` = '%s' AND `uid` = %d LIMIT 1",
dbesc($name),
intval($profile_uid)
);
}
if(count($r)) {
$profile = $r[0]['url'];
if(strlen($inform))
$inform .= ',';
$inform .= 'cid:' . $r[0]['id'];
}
}
if($profile) {
$body = str_replace($name,'[url=' . $profile . ']' . $newname . '[/url]', $body);
if(strlen($str_tags))
$str_tags .= ',';
$profile = str_replace(',','%2c',$profile);
$str_tags .= '@[url=' . $profile . ']' . $newname . '[/url]';
}
}
}
}
$wall = 0;
if($post_type === 'wall' || $post_type === 'wall-comment')
$wall = 1;
@ -127,9 +185,9 @@ function item_post(&$a) {
$uri = item_new_uri($a->get_hostname(),$profile_uid);
$r = q("INSERT INTO `item` (`uid`,`type`,`wall`,`gravity`,`contact-id`,`owner-name`,`owner-link`,`owner-avatar`,
`author-name`, `author-link`, `author-avatar`, `created`,
`edited`, `changed`, `uri`, `title`, `body`, `location`, `verb`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`)
VALUES( %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
`author-name`, `author-link`, `author-avatar`, `created`, `edited`, `changed`, `uri`, `title`, `body`, `location`, `coord`,
`tag`, `inform`, `verb`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`)
VALUES( %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
intval($profile_uid),
dbesc($post_type),
intval($wall),
@ -148,6 +206,9 @@ function item_post(&$a) {
dbesc($title),
dbesc($body),
dbesc($location),
dbesc($coord),
dbesc($str_tags),
dbesc($inform),
dbesc($verb),
dbesc($str_contact_allow),
dbesc($str_group_allow),
@ -343,7 +404,7 @@ function item_content(&$a) {
else {
notice( t('Permission denied.') . EOL);
goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
return; //NOTREACHED
//NOTREACHED
}
}
}

View file

@ -66,7 +66,7 @@ function like_content(&$a) {
}
if((local_user()) && (get_uid() == $owner_uid)) {
if((local_user()) && (local_user() == $owner_uid)) {
$contact = $owner;
}
else {

View file

@ -7,7 +7,8 @@ function lostpass_post(&$a) {
if(! $email)
goaway($a->get_baseurl());
$r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1",
$r = q("SELECT * FROM `user` WHERE ( `email` = '%s' OR `nickname` = '%s' ) LIMIT 1",
dbesc($email),
dbesc($email)
);
if(! count($r))

View file

@ -24,6 +24,9 @@ function message_post(&$a) {
return;
}
if(! strlen($subject))
$subject = t('[no subject]');
$me = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
intval($_SESSION['uid'])
);
@ -83,6 +86,8 @@ function message_post(&$a) {
}
function message_content(&$a) {
$o = '';
$o .= '<script> $(document).ready(function() { $(\'#nav-messages-link\').addClass(\'nav-selected\'); });</script>';
if(! local_user()) {
@ -153,7 +158,7 @@ function message_content(&$a) {
$a->page['htmlhead'] .= replace_macros($tpl, array('$baseurl' => $a->get_baseurl()));
$select .= contact_select('messageto','message-to-select', false, 4, true);
$select = contact_select('messageto','message-to-select', false, 4, true);
$tpl = load_view_file('view/prv_message.tpl');
$o .= replace_macros($tpl,array(
'$header' => t('Send Private Message'),

View file

@ -3,6 +3,8 @@
function network_init(&$a) {
require_once('include/group.php');
if(! x($a->page,'aside'))
$a->page['aside'] = '';
$a->page['aside'] .= group_side('network','network');
}
@ -10,7 +12,9 @@ function network_init(&$a) {
function network_content(&$a, $update = 0) {
if(! local_user())
return;
return '';
$o = '';
require_once("include/bbcode.php");
@ -28,9 +32,14 @@ function network_content(&$a, $update = 0) {
}
$_SESSION['return_url'] = $a->cmd;
$geotag = (($a->user['allow_location']) ? load_view_file('view/jot_geotag.tpl') : '');
$tpl = load_view_file('view/jot-header.tpl');
$a->page['htmlhead'] .= replace_macros($tpl, array('$baseurl' => $a->get_baseurl()));
$a->page['htmlhead'] .= replace_macros($tpl, array(
'$baseurl' => $a->get_baseurl(),
'$geotag' => $geotag
));
require_once('view/acl_selectors.php');
@ -41,13 +50,15 @@ function network_content(&$a, $update = 0) {
else
$lockstate = 'unlock';
$celeb = ((($a->user['page-flags'] == PAGE_SOAPBOX) || ($a->user['page-flags'] == PAGE_COMMUNITY)) ? true : false);
$o .= replace_macros($tpl,array(
'$return_path' => $a->cmd,
'$baseurl' => $a->get_baseurl(),
'$defloc' => $a->user['default-location'],
'$visitor' => 'block',
'$lockstate' => $lockstate,
'$acl' => populate_acl(($group) ? $group_acl : $a->user),
'$acl' => populate_acl((($group) ? $group_acl : $a->user), $celeb),
'$bang' => (($group) ? '!' : ''),
'$profile_uid' => $_SESSION['uid']
));
@ -111,7 +122,7 @@ function network_content(&$a, $update = 0) {
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
@ -133,32 +144,10 @@ function network_content(&$a, $update = 0) {
$dlike = array();
if(count($r)) {
foreach($r as $item) {
$sparkle = '';
if(($item['verb'] == ACTIVITY_LIKE) && ($item['id'] != $item['parent'])) {
$url = $item['url'];
if(($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'])) {
$url = $a->get_baseurl() . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle"';
}
if(! is_array($alike[$item['parent'] . '-l']))
$alike[$item['parent'] . '-l'] = array();
$alike[$item['parent']] ++;
$alike[$item['parent'] . '-l'][] = '<a href="'. $url . '"' . $sparkle . '>' . $item['name'] . '</a>';
}
if(($item['verb'] == ACTIVITY_DISLIKE) && ($item['id'] != $item['parent'])) {
$url = $item['url'];
if(($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'])) {
$url = $a->get_baseurl() . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle"';
}
if(! is_array($dlike[$item['parent'] . '-l']))
$dlike[$item['parent'] . '-l'] = array();
$dlike[$item['parent']] ++;
$dlike[$item['parent'] . '-l'][] = '<a href="'. $url . '"' . $sparkle . '>' . $item['name'] . '</a>';
}
like_puller($a,$item,$alike,'like');
like_puller($a,$item,$dlike,'dislike');
}
foreach($r as $item) {
@ -166,14 +155,14 @@ function network_content(&$a, $update = 0) {
$comment = '';
$template = $tpl;
$commentww = '';
$owner_url = $owner_photo = $owner_name = '';
$profile_url = $item['url'];
$redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
if((($item['verb'] == ACTIVITY_LIKE) || ($item['verb'] == ACTIVITY_DISLIKE)) && ($item['id'] != $item['parent']))
if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
continue;
$lock = (($item['uid'] == get_uid()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
$lock = (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))
? '<div class="wall-item-lock"><img src="images/lock_icon.gif" class="lockview" alt="' . t('Private Message') . '" onclick="lockview(event,' . $item['id'] . ');" /></div>'
: '<div class="wall-item-lock"></div>');
@ -193,7 +182,7 @@ function network_content(&$a, $update = 0) {
$template = $wallwall;
$commentww = 'ww';
}
if($item['type'] === 'remote' && ($item['owner-link'] != $item['author-link'])) {
if(($item['type'] === 'remote') && (strlen($item['owner-link'])) && ($item['owner-link'] != $item['author-link'])) {
// Could be anybody.
$owner_url = $item['owner-link'];
$owner_photo = $item['owner-avatar'];
@ -202,7 +191,7 @@ function network_content(&$a, $update = 0) {
$commentww = 'ww';
// If it is our contact, use a friendly redirect link
if(($item['owner-link'] == $item['url'])
&& ($item['rel'] == REL_VIP || $item['rel'] == REL_BUD)) {
&& ($item['network'] === 'dfrn')) {
$owner_url = $redirect_url;
$osparkle = ' sparkle';
}
@ -238,7 +227,7 @@ function network_content(&$a, $update = 0) {
if(($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'] )) {
if(($item['network'] === 'dfrn') && (! $item['self'] )) {
$profile_url = $redirect_url;
$sparkle = ' sparkle';
}
@ -256,7 +245,7 @@ function network_content(&$a, $update = 0) {
// Can we use our special contact URL for this author?
if(strlen($item['author-link'])) {
if($item['author-link'] == $item['url'] && (! $item['self'])) {
if($item['author-link'] == $item['url'] && ($item['network'] === 'dfrn') && (! $item['self'])) {
$profile_link = $redirect_url;
$sparkle = ' sparkle';
}
@ -267,9 +256,17 @@ function network_content(&$a, $update = 0) {
}
$like = (($alike[$item['id']]) ? format_like($alike[$item['id']],$alike[$item['id'] . '-l'],'like',$item['id']) : '');
$dislike = (($dlike[$item['id']]) ? format_like($dlike[$item['id']],$dlike[$item['id'] . '-l'],'dislike',$item['id']) : '');
$like = ((x($alike,$item['id'])) ? format_like($alike[$item['id']],$alike[$item['id'] . '-l'],'like',$item['id']) : '');
$dislike = ((x($dlike,$item['id'])) ? format_like($dlike[$item['id']],$dlike[$item['id'] . '-l'],'dislike',$item['id']) : '');
$location = (($item['location']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['location']) . '">' . $item['location'] . '</a>' : '');
$coord = (($item['coord']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['coord']) . '">' . $item['coord'] . '</a>' : '');
if($coord) {
if($location)
$location .= '<br /><span class="smalltext">(' . $coord . ')</span>';
else
$location = '<span class="smalltext">' . $coord . '</span>';
}
// Build the HTML
@ -284,7 +281,7 @@ function network_content(&$a, $update = 0) {
'$body' => bbcode($item['body']),
'$ago' => relative_date($item['created']),
'$lock' => $lock,
'$location' => (($item['location']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['location']) . '">' . $item['location'] . '</a>' : ''),
'$location' => $location,
'$indent' => (($item['parent'] != $item['item_id']) ? ' comment' : ''),
'$owner_url' => $owner_url,
'$owner_photo' => $owner_photo,

View file

@ -17,7 +17,7 @@ function notifications_post(&$a) {
WHERE `request-id` = %d
AND `uid` = %d LIMIT 1",
intval($request_id),
intval(get_uid())
intval(local_user())
);
if(count($r)) {
@ -33,7 +33,7 @@ function notifications_post(&$a) {
);
$r = q("DELETE FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($request_id),
intval(get_uid())
intval(local_user())
);
return;
}
@ -71,7 +71,7 @@ function notifications_content(&$a) {
'$hide_text' => ((strlen($sql_extra)) ? t('Show Ignored Requests') : t('Hide Ignored Requests'))
));
$r = q("SELECT `intro`.`id` AS `intro-id`, `intro`.*, `contact`.*
$r = q("SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*
FROM `intro` LEFT JOIN `contact` ON `intro`.`contact-id` = `contact`.`id`
WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0 ",
intval($_SESSION['uid']));
@ -83,15 +83,36 @@ function notifications_content(&$a) {
foreach($r as $rr) {
$friend_selected = (($rr['network'] === 'dfrn') ? ' checked="checked" ' : ' disabled ');
$fan_selected = (($rr['network'] === 'stat') ? ' checked="checked" disabled ' : '');
$dfrn_tpl = load_view_file('view/netfriend.tpl');
$knowyou = '';
$dfrn_text = '';
if($rr['network'] === 'dfrn') {
$knowyou = t('Claims to be known to you: ') . (($rr['knowyou']) ? t('yes') : t('no'));
$dfrn_text = replace_macros($dfrn_tpl,array(
'$intro_id' => $rr['intro_id'],
'$friend_selected' => $friend_selected,
'$fan_selected' => $fan_selected,
));
}
$o .= replace_macros($tpl,array(
'$intro_id' => $rr['intro-id'],
'$dfrn-id' => $rr['issued-id'],
'$notify_type' => (($rr['network'] === 'dfrn') ? t('Friend/Connect Request') : t('New Follower')),
'$dfrn_text' => $dfrn_text,
'$dfrn_id' => $rr['issued-id'],
'$uid' => $_SESSION['uid'],
'$contact-id' => $rr['contact-id'],
'$intro_id' => $rr['intro_id'],
'$contact_id' => $rr['contact-id'],
'$photo' => ((x($rr,'photo')) ? $rr['photo'] : "images/default-profile.jpg"),
'$fullname' => $rr['name'],
'$knowyou' => (($rr['knowyou']) ? t('yes') : t('no')),
'$url' => $rr['url'],
'$knowyou' => $knowyou,
'$note' => $rr['note']
));
}

View file

@ -16,7 +16,7 @@ function photo_init(&$a) {
return; // NOTREACHED
}
if(x($type)) {
if(isset($type)) {
switch($type) {
case 'profile':
@ -37,7 +37,7 @@ function photo_init(&$a) {
if(count($r)) {
$data = $r[0]['data'];
}
if(x($data) === false) {
if(! isset($data)) {
$data = file_get_contents(($resolution == 5)
? 'images/default-profile-sm.jpg'
: 'images/default-profile.jpg');

View file

@ -3,6 +3,7 @@
require_once('Photo.php');
require_once('include/items.php');
require_once('view/acl_selectors.php');
require_once('include/bbcode.php');
function photos_init(&$a) {
@ -51,12 +52,17 @@ function photos_post(&$a) {
killme();
}
$r = q("SELECT `contact`.* `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
$r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `user`.`uid` = %d AND `self` = 1 LIMIT 1",
intval(get_uid())
intval(local_user())
);
if(! count($r)) {
notice( t('Contact information unavailable') . EOL);
logger('photos_post: unable to locate contact record for logged in user. uid=' . local_user());
killme();
}
$contact_record = $r[0];
@ -70,7 +76,7 @@ function photos_post(&$a) {
$r = q("SELECT count(*) FROM `photo` WHERE `album` = '%s' AND `uid` = %d",
dbesc($album),
intval(get_uid())
intval(local_user())
);
if(! count($r)) {
notice( t('Album not found.') . EOL);
@ -83,7 +89,7 @@ function photos_post(&$a) {
q("UPDATE `photo` SET `album` = '%s' WHERE `album` = '%s' AND `uid` = %d",
dbesc($newalbum),
dbesc($album),
intval(get_uid())
intval(local_user())
);
$newurl = str_replace(bin2hex($album),bin2hex($newalbum),$_SESSION['photo_return']);
goaway($a->get_baseurl() . '/' . $newurl);
@ -94,7 +100,7 @@ function photos_post(&$a) {
$res = array();
$r = q("SELECT distinct(`resource-id`) as `rid` FROM `photo` WHERE `uid` = %d AND `album` = '%s'",
intval(get_uid()),
intval(local_user()),
dbesc($album)
);
if(count($r)) {
@ -109,17 +115,17 @@ function photos_post(&$a) {
$str_res = implode(',', $res);
q("DELETE FROM `photo` WHERE `resource-id` IN ( $str_res ) AND `uid` = %d",
intval(get_uid())
intval(local_user())
);
$r = q("SELECT `parent-uri` FROM `item` WHERE `resource-id` IN ( $str_res ) AND `uid` = %d",
intval(get_uid())
intval(local_user())
);
if(count($r)) {
foreach($r as $rr) {
q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
dbesc(datetime_convert()),
dbesc($rr['parent-uri']),
intval(get_uid())
intval(local_user())
);
$drop_id = intval($rr['id']);
@ -141,24 +147,24 @@ function photos_post(&$a) {
if(($a->argc > 1) && (x($_POST,'delete')) && ($_POST['delete'] == t('Delete Photo'))) {
$r = q("SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' LIMIT 1",
intval(get_uid()),
intval(local_user()),
dbesc($a->argv[1])
);
if(count($r)) {
q("DELETE FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'",
intval(get_uid()),
intval(local_user()),
dbesc($r[0]['resource-id'])
);
$i = q("SELECT * FROM `item` WHERE `resource-id` = '%s' AND `uid` = %d LIMIT 1",
dbesc($r[0]['resource-id']),
intval(get_uid())
intval(local_user())
);
if(count($i)) {
q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($i[0]['uri']),
intval(get_uid())
intval(local_user())
);
$url = $a->get_baseurl();
@ -179,35 +185,35 @@ function photos_post(&$a) {
return; // NOTREACHED
}
if(($a->argc > 1) && ((x($_POST,'desc') !== false) || (x($_POST,'newtag') !== false))) {
if(($a->argc > 1) && (x($_POST,'desc') !== false)) {
$desc = notags(trim($_POST['desc']));
$tags = notags(trim($_POST['tags']));
$item_id = intval($_POST['item_id']);
$desc = ((x($_POST,'desc')) ? notags(trim($_POST['desc'])) : '');
$rawtags = ((x($_POST,'newtag')) ? notags(trim($_POST['newtag'])) : '');
$item_id = ((x($_POST,'item_id')) ? intval($_POST['item_id']) : 0);
$resource_id = $a->argv[1];
$p = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d ORDER BY `scale` DESC",
dbesc($resource_id),
intval(get_uid())
intval(local_user())
);
if(count($r)) {
if((count($p)) && ($p[0]['desc'] !== $desc)) {
$r = q("UPDATE `photo` SET `desc` = '%s' WHERE `resource-id` = '%s' AND `uid` = %d",
dbesc($desc),
dbesc($resource_id),
intval(get_uid())
intval(local_user())
);
}
if(! $item_id) {
// Create item container
$title = '';
$basename = basename($filename);
$uri = item_new_uri($a->get_hostname(),get_uid());
// Create item container
$uri = item_new_uri($a->get_hostname(),local_user());
$arr = array();
$arr['uid'] = get_uid();
$arr['uid'] = local_user();
$arr['uri'] = $uri;
$arr['parent-uri'] = $uri;
$arr['type'] = 'photo';
@ -231,14 +237,100 @@ function photos_post(&$a) {
}
$r = q("UPDATE `item` SET `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
dbesc($tags),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($item_id),
intval(get_uid())
);
if($item_id) {
$r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($item_id),
intval(local_user())
);
}
if(count($r)) {
$old_tag = $r[0]['tag'];
$old_inform = $r[0]['inform'];
}
if(strlen($rawtags)) {
$str_tags = '';
$inform = '';
// if the new tag doesn't have a namespace specifier (@foo or #foo) give it a hashtag
$x = substr($rawtags,0,1);
if($x !== '@' && $x !== '#')
$rawtags = '#' . $rawtags;
$tags = get_tags($rawtags);
if(count($tags)) {
foreach($tags as $tag) {
if(strpos($tag,'@') === 0) {
$name = substr($tag,1);
if((strpos($name,'@')) || (strpos($name,'http://'))) {
$newname = $name;
$links = @lrdd($name);
if(count($links)) {
foreach($links as $link) {
if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page')
$profile = $link['@attributes']['href'];
if($link['@attributes']['rel'] === 'salmon') {
if(strlen($inform))
$inform .= ',';
$inform .= 'url:' . str_replace(',','%2c',$link['@attributes']['href']);
}
}
}
}
else {
$newname = $name;
if(strstr($name,'_')) {
$newname = str_replace('_',' ',$name);
$r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
dbesc($newname),
intval(local_user())
);
}
else {
$r = q("SELECT * FROM `contact` WHERE `nick` = '%s' AND `uid` = %d LIMIT 1",
dbesc($name),
intval(local_user())
);
}
if(count($r)) {
$profile = $r[0]['url'];
if(strlen($inform))
$inform .= ',';
$inform .= 'cid:' . $r[0]['id'];
}
}
if($profile) {
if(strlen($str_tags))
$str_tags .= ',';
$profile = str_replace(',','%2c',$profile);
$str_tags .= '@[url=' . $profile . ']' . $newname . '[/url]';
}
}
}
}
$newtag = $old_tag;
if(strlen($newtag) && strlen($str_tags))
$newtag .= ',';
$newtag .= $str_tags;
$newinform = $old_inform;
if(strlen($newinform) && strlen($inform))
$newinform .= ',';
$newinform .= $inform;
$r = q("UPDATE `item` SET `tag` = '%s', `inform` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
dbesc($newtag),
dbesc($newinform),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($item_id),
intval(local_user())
);
}
goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
return; // NOTREACHED
}
@ -266,7 +358,7 @@ function photos_post(&$a) {
$r = q("SELECT * FROM `photo` WHERE `album` = '%s' AND `uid` = %d",
dbesc($album),
intval(get_uid())
intval(local_user())
);
if((! count($r)) || ($album == t('Profile Photos')))
$visible = 1;
@ -301,7 +393,7 @@ function photos_post(&$a) {
$photo_hash = photo_new_resource();
$r = $ph->store(get_uid(), 0, $photo_hash, $filename, $album, 0 , 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
$r = $ph->store(local_user(), 0, $photo_hash, $filename, $album, 0 , 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
if(! $r) {
notice( t('Image upload failed.') . EOL );
@ -310,25 +402,25 @@ function photos_post(&$a) {
if($width > 640 || $height > 640) {
$ph->scaleImage(640);
$ph->store(get_uid(), 0, $photo_hash, $filename, $album, 1, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
$ph->store(local_user(), 0, $photo_hash, $filename, $album, 1, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
$smallest = 1;
}
if($width > 320 || $height > 320) {
$ph->scaleImage(320);
$ph->store(get_uid(), 0, $photo_hash, $filename, $album, 2, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
$ph->store(local_user(), 0, $photo_hash, $filename, $album, 2, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
$smallest = 2;
}
$basename = basename($filename);
$uri = item_new_uri($a->get_hostname(), get_uid());
$uri = item_new_uri($a->get_hostname(), local_user());
// Create item container
$arr = array();
$arr['uid'] = get_uid();
$arr['uid'] = local_user();
$arr['uri'] = $uri;
$arr['parent-uri'] = $uri;
$arr['type'] = 'photo';
@ -437,7 +529,7 @@ function photos_content(&$a) {
// Profile owner - everything is visible
if(local_user() && (get_uid() == $owner_uid)) {
if(local_user() && (local_user() == $owner_uid)) {
$sql_extra = '';
}
elseif(remote_user()) {
@ -466,7 +558,7 @@ function photos_content(&$a) {
if($datatype === 'upload') {
if( ! (local_user() && (get_uid() == $a->data['user']['uid']))) {
if( ! (local_user() && (local_user() == $a->data['user']['uid']))) {
notice( t('Permission denied.'));
return;
}
@ -480,6 +572,9 @@ function photos_content(&$a) {
$albumselect .= '<option value="' . $album['album'] . '">' . $album['album'] . '</option>';
}
}
$celeb = ((($a->user['page-flags'] == PAGE_SOAPBOX) || ($a->user['page-flags'] == PAGE_COMMUNITY)) ? true : false);
$albumselect .= '</select>';
$tpl = load_view_file('view/photos_upload.tpl');
$o .= replace_macros($tpl,array(
@ -490,7 +585,7 @@ function photos_content(&$a) {
'$filestext' => t('Select files to upload: '),
'$albumselect' => $albumselect,
'$permissions' => t('Permissions'),
'$aclselect' => populate_acl($a->user),
'$aclselect' => populate_acl($a->user, $celeb),
'$archive' => $a->get_baseurl() . '/jumploader_z.jar',
'$nojava' => t('Use the following controls only if the Java uploader [above] fails to launch.'),
'$uploadurl' => $a->get_baseurl() . '/photos',
@ -526,7 +621,7 @@ function photos_content(&$a) {
if($cmd === 'edit') {
if(($album != t('Profile Photos')) && ($album != t('Contact Photos'))) {
if(local_user() && (get_uid() == $a->data['user']['uid'])) {
if(local_user() && (local_user() == $a->data['user']['uid'])) {
$edit_tpl = load_view_file('view/album_edit.tpl');
$o .= replace_macros($edit_tpl,array(
'$nametext' => t('New album name: '),
@ -540,7 +635,7 @@ function photos_content(&$a) {
}
else {
if(($album != t('Profile Photos')) && ($album != t('Contact Photos'))) {
if(local_user() && (get_uid() == $a->data['user']['uid'])) {
if(local_user() && (local_user() == $a->data['user']['uid'])) {
$o .= '<div id="album-edit-link"><a href="'. $a->get_baseurl() . '/photos/'
. $a->data['user']['nickname'] . '/album/' . bin2hex($album) . '/edit' . '">'
. t('Edit Album') . '</a></div>';
@ -599,7 +694,7 @@ function photos_content(&$a) {
$o .= '<h3>' . '<a href="' . $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($ph[0]['album']) . '">' . $ph[0]['album'] . '</a></h3>';
if(local_user() && ($ph[0]['uid'] == get_uid())) {
if(local_user() && ($ph[0]['uid'] == local_user())) {
$o .= '<div id="photo-edit-link-wrap" ><a id="photo-edit-link" href="' . $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $datum . '/edit' . '">' . t('Edit photo') . '</a></div>';
}
@ -620,11 +715,12 @@ function photos_content(&$a) {
$r = q("SELECT COUNT(*) AS `total`
FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `parent-uri` = '%s' AND `uri` != '%s' AND `item`.`deleted` = 0
AND NOT `item`.`type` IN ( 'remote', 'net-comment')
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `item`.`uid` = %d
$sql_extra ",
dbesc($i1[0]['uri']),
dbesc($i1[0]['uri'])
dbesc($i1[0]['uri']),
intval($i1[0]['uid'])
);
@ -633,17 +729,18 @@ function photos_content(&$a) {
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`,
`contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`network`,
`contact`.`rel`, `contact`.`thumb`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `parent-uri` = '%s' AND `uri` != '%s' AND `item`.`deleted` = 0
AND NOT `item`.`type` IN ( 'remote', 'net-comment')
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `item`.`uid` = %d
$sql_extra
ORDER BY `parent` DESC, `id` ASC LIMIT %d ,%d ",
dbesc($i1[0]['uri']),
dbesc($i1[0]['uri']),
intval($i1[0]['uid']),
intval($a->pager['start']),
intval($a->pager['itemspage'])
@ -653,9 +750,17 @@ function photos_content(&$a) {
$o .= '<div id="photo-caption" >' . $ph[0]['desc'] . '</div>';
if(count($i1) && strlen($i1[0]['tag'])) {
$arr = explode(',',$i1[0]['tag']);
// parse tags and add links
$o .= '<div id="in-this-photo-text">' . t('In this photo: ') . '</div>';
$o .= '<div id="in-this-photo">' . $i1[0]['tag'] . '</div>';
$o .= '<div id="in-this-photo-text">' . t('Tags: ') . '</div>';
$o .= '<div id="in-this-photo">';
$tag_str = '';
foreach($arr as $t) {
if(strlen($tag_str))
$tag_str .= ', ';
$tag_str .= bbcode($t);
}
$o .= $tag_str . '</div>';
}
if($cmd === 'edit') {
@ -665,8 +770,9 @@ function photos_content(&$a) {
'$resource_id' => $ph[0]['resource-id'],
'$capt_label' => t('Caption'),
'$caption' => $ph[0]['desc'],
'$tag_label' => t('Tags'),
'$tag_label' => t('Add a Tag'),
'$tags' => $i1[0]['tag'],
'$help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping'),
'$item_id' => ((count($i1)) ? $i1[0]['id'] : 0),
'$submit' => t('Submit'),
'$delete' => t('Delete Photo')
@ -675,12 +781,13 @@ function photos_content(&$a) {
}
if(count($i1)) {
// pull out how many people like the photo
$cmnt_tpl = load_view_file('view/comment_item.tpl');
$tpl = load_view_file('view/photo_item.tpl');
$return_url = $a->cmd;
$like_tpl = load_view_file('view/like.tpl');
if(can_write_wall($a,$a->data['user']['uid'])) {
if($i1[0]['last-child']) {
$o .= replace_macros($cmnt_tpl,array(
@ -697,16 +804,41 @@ function photos_content(&$a) {
}
}
$alike = array();
$dlike = array();
// display comments
if(count($r)) {
foreach($r as $item) {
like_puller($a,$item,$alike,'like');
like_puller($a,$item,$dlike,'dislike');
}
$likebuttons = '';
if(can_write_wall($a,$a->data['user']['uid']))
$likebuttons = replace_macros($like_tpl,array('$id' => $i1[0]['id']));
$like = ((isset($alike[$i1[0]['id']])) ? format_like($alike[$i1[0]['id']],$alike[$i1[0]['id'] . '-l'],'like',$i1[0]['id']) : '');
$dislike = ((isset($dlike[$i1[0]['id']])) ? format_like($dlike[$i1[0]['id']],$dlike[$i1[0]['id'] . '-l'],'dislike',$i1[0]['id']) : '');
$o .= $likebuttons;
$o .= $like;
$o .= $dislike;
foreach($r as $item) {
$comment = '';
$template = $tpl;
$sparkle = '';
if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
continue;
$redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
if(can_write_wall($a,$a->data['user']['uid'])) {
if($item['last-child']) {
$comment = replace_macros($cmnt_tpl,array(
'$return_path' => $return_url,
@ -723,8 +855,8 @@ function photos_content(&$a) {
}
if(local_user() && ($item['contact-uid'] == get_uid())
&& ($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'] )) {
if(local_user() && ($item['contact-uid'] == local_user())
&& ($item['network'] == 'dfrn') && (! $item['self'] )) {
$profile_url = $redirect_url;
$sparkle = ' sparkle';
}
@ -739,7 +871,7 @@ function photos_content(&$a) {
$drop = '';
if(($item['contact-id'] == $_SESSION['visitor_id']) || ($item['uid'] == get_uid()))
if(($item['contact-id'] == $_SESSION['visitor_id']) || ($item['uid'] == local_user()))
$drop = replace_macros(load_view_file('view/wall_item_drop.tpl'), array('$id' => $item['id']));
@ -785,7 +917,7 @@ function photos_content(&$a) {
$o .= '<h3>' . t('Recent Photos') . '</h3>';
if( local_user() && (get_uid() == $a->data['user']['uid'])) {
if( local_user() && (local_user() == $a->data['user']['uid'])) {
$o .= '<div id="photo-top-links"><a id="photo-top-upload-link" href="'. $a->get_baseurl() . '/photos/'
. $a->data['user']['nickname'] . '/upload' . '">' . t('Upload New Photos') . '</a></div>';
}

View file

@ -9,26 +9,26 @@ function ping_init(&$a) {
$r = q("SELECT COUNT(*) AS `total` FROM `item`
WHERE `unseen` = 1 AND `visible` = 1 AND `deleted` = 0 AND `uid` = %d",
intval(get_uid())
intval(local_user())
);
$network = $r[0]['total'];
$r = q("SELECT COUNT(*) AS `total` FROM `item`
WHERE `unseen` = 1 AND `visible` = 1 AND `deleted` = 0 AND `uid` = %d AND `type` != 'remote' ",
intval(get_uid())
intval(local_user())
);
$home = $r[0]['total'];
$r = q("SELECT COUNT(*) AS `total` FROM `intro`
WHERE `uid` = %d AND `blocked` = 0 AND `ignore` = 0 ",
intval(get_uid())
intval(local_user())
);
$intro = $r[0]['total'];
$myurl = $a->get_baseurl() . '/profile/' . $user['nickname'] ;
$myurl = $a->get_baseurl() . '/profile/' . $a->user['nickname'] ;
$r = q("SELECT COUNT(*) AS `total` FROM `mail`
WHERE `uid` = %d AND `seen` = 0 AND `from-url` != '%s' ",
intval(get_uid()),
intval(local_user()),
dbesc($myurl)
);

View file

@ -2,7 +2,6 @@
if(! function_exists('profile_load')) {
function profile_load(&$a, $username, $profile = 0) {
if(remote_user()) {
$r = q("SELECT `profile-id` FROM `contact` WHERE `id` = %d LIMIT 1",
intval($_SESSION['visitor_id']));
@ -60,11 +59,14 @@ function profile_init(&$a) {
$which = $a->user['nickname'];
$profile = $a->argv[1];
}
profile_load($a,$which,$profile);
$a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/dfrn_poll/' . $which .'" />' . "\r\n" ;
$a->page['htmlhead'] .= '<meta name="dfrn-template" content="' . $a->get_baseurl() . "/profile/%s" . '" />' . "\r\n" ;
$a->page['htmlhead'] .= '<meta name="dfrn-global-visibility" content="' . (($a->profile['net-publish']) ? 'true' : 'false') . '" />' . "\r\n" ;
profile_load($a,$which,$profile);
$a->page['htmlhead'] .= '<meta name="dfrn-global-visibility" content="' . (($a->profile['net-publish']) ? 'true' : 'false') . '" />' . "\r\n" ;
$a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/dfrn_poll/' . $which .'" />' . "\r\n" ;
$uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->get_hostname() . (($a->path) ? '/' . $a->path : ''));
$a->page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . $a->get_baseurl() . '/xrd/?uri=' . $uri . '" />' . "\r\n";
header('Link: <' . $a->get_baseurl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"');
$dfrn_pages = array('request', 'confirm', 'notify', 'poll');
@ -83,14 +85,14 @@ function profile_content(&$a, $update = 0) {
$groups = array();
$tab = 'posts';
$o = '';
if($update) {
// Ensure we've got a profile owner if updating.
$a->profile['profile_uid'] = $update;
}
else {
if($a->profile['profile_uid'] == get_uid())
if($a->profile['profile_uid'] == local_user())
$o .= '<script> $(document).ready(function() { $(\'#nav-home-link\').addClass(\'nav-selected\'); });</script>';
}
@ -117,6 +119,8 @@ function profile_content(&$a, $update = 0) {
}
}
$is_owner = ((local_user()) && (local_user() == $a->profile['profile_uid']) ? true : false);
if(! $update) {
if(x($_GET,'tab'))
$tab = notags(trim($_GET['tab']));
@ -138,10 +142,19 @@ function profile_content(&$a, $update = 0) {
return $o;
}
$celeb = ((($a->profile['page-flags'] == PAGE_SOAPBOX) || ($a->profile['page-flags'] == PAGE_COMMUNITY)) ? true : false);
if(can_write_wall($a,$a->profile['profile_uid'])) {
$geotag = (($is_owner && $a->profile['allow_location']) ? load_view_file('view/jot_geotag.tpl') : '');
$tpl = load_view_file('view/jot-header.tpl');
$a->page['htmlhead'] .= replace_macros($tpl, array('$baseurl' => $a->get_baseurl()));
$a->page['htmlhead'] .= replace_macros($tpl, array(
'$baseurl' => $a->get_baseurl(),
'$geotag' => $geotag
));
require_once('view/acl_selectors.php');
$tpl = load_view_file("view/jot.tpl");
@ -151,12 +164,12 @@ function profile_content(&$a, $update = 0) {
$lockstate = 'unlock';
$o .= replace_macros($tpl,array(
'$baseurl' => $a->get_baseurl(),
'$defloc' => (($_SESSION['uid'] == $a->profile['profile_uid']) ? $a->user['default-location'] : ''),
'$defloc' => (($is_owner) ? $a->user['default-location'] : ''),
'$return_path' => $a->cmd,
'$visitor' => (($_SESSION['uid'] == $a->profile['profile_uid']) ? 'block' : 'none'),
'$visitor' => (($is_owner) ? 'block' : 'none'),
'$lockstate' => $lockstate,
'$bang' => '',
'$acl' => (($_SESSION['uid'] == $a->profile['profile_uid']) ? populate_acl($a->user) : ''),
'$acl' => (($is_owner) ? populate_acl($a->user, $celeb) : ''),
'$profile_uid' => $a->profile['profile_uid']
));
}
@ -171,18 +184,15 @@ function profile_content(&$a, $update = 0) {
}
// TODO alter registration and settings and profile to update contact table when names and photos change.
// Construct permissions
// default permissions - anonymous user
$sql_extra = " AND `allow_cid` = '' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = '' ";
// Profile owner - everything is visible
if(local_user() && ($_SESSION['uid'] == $a->profile['profile_uid'])) {
if($is_owner) {
$sql_extra = '';
// Oh - while we're here... reset the Unseen messages
@ -231,8 +241,8 @@ function profile_content(&$a, $update = 0) {
$a->set_pager_total($r[0]['total']);
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`network`, `contact`.`rel`,
`contact`.`thumb`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
@ -246,7 +256,6 @@ function profile_content(&$a, $update = 0) {
);
$cmnt_tpl = load_view_file('view/comment_item.tpl');
$like_tpl = load_view_file('view/like.tpl');
@ -267,31 +276,8 @@ function profile_content(&$a, $update = 0) {
if(count($r)) {
foreach($r as $item) {
$sparkle = '';
if(($item['verb'] == ACTIVITY_LIKE) && ($item['id'] != $item['parent'])) {
$url = $item['url'];
if(($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'])) {
$url = $a->get_baseurl() . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle" ';
}
if(! is_array($alike[$item['parent'] . '-l']))
$alike[$item['parent'] . '-l'] = array();
$alike[$item['parent']] ++;
$alike[$item['parent'] . '-l'][] = '<a href="'. $url . '"'. $sparkle .'>' . $item['name'] . '</a>';
}
if(($item['verb'] == ACTIVITY_DISLIKE) && ($item['id'] != $item['parent'])) {
$url = $item['url'];
if(($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'])) {
$url = $a->get_baseurl() . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle" ';
}
if(! is_array($dlike[$item['parent'] . '-l']))
$dlike[$item['parent'] . '-l'] = array();
$dlike[$item['parent']] ++;
$dlike[$item['parent'] . '-l'][] = '<a href="'. $url . '"'. $sparkle .'>' . $item['name'] . '</a>';
}
like_puller($a,$item,$alike,'like');
like_puller($a,$item,$dlike,'dislike');
}
foreach($r as $item) {
@ -304,10 +290,11 @@ function profile_content(&$a, $update = 0) {
$redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
if((($item['verb'] == ACTIVITY_LIKE) || ($item['verb'] == ACTIVITY_DISLIKE)) && ($item['id'] != $item['parent']))
if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE)))
&& ($item['id'] != $item['parent']))
continue;
$lock = (($item['uid'] == get_uid()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
$lock = (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))
? '<div class="wall-item-lock"><img src="images/lock_icon.gif" class="lockview" alt="' . t('Private Message') . '" onclick="lockview(event,' . $item['id'] . ');" /></div>'
: '<div class="wall-item-lock"></div>');
@ -338,7 +325,7 @@ function profile_content(&$a, $update = 0) {
// I can go directly to their profile as an authenticated guest.
if(local_user() && ($item['contact-uid'] == $_SESSION['uid'])
&& ($item['rel'] == REL_VIP || $item['rel'] == REL_BUD) && (! $item['self'] )) {
&& ($item['network'] === 'dfrn') && (! $item['self'] )) {
$profile_url = $redirect_url;
$sparkle = ' sparkle';
}
@ -356,15 +343,22 @@ function profile_content(&$a, $update = 0) {
$drop = '';
$dropping = false;
if(($item['contact-id'] == $_SESSION['visitor_id']) || ($item['uid'] == $_SESSION['uid']))
if(($item['contact-id'] == remote_user()) || ($item['uid'] == local_user()))
$dropping = true;
$drop = replace_macros((($dropping)? $droptpl : $fakedrop), array('$id' => $item['id']));
$like = (($alike[$item['id']]) ? format_like($alike[$item['id']],$alike[$item['id'] . '-l'],'like',$item['id']) : '');
$dislike = (($dlike[$item['id']]) ? format_like($dlike[$item['id']],$dlike[$item['id'] . '-l'],'dislike',$item['id']) : '');
$like = ((isset($alike[$item['id']])) ? format_like($alike[$item['id']],$alike[$item['id'] . '-l'],'like',$item['id']) : '');
$dislike = ((isset($dlike[$item['id']])) ? format_like($dlike[$item['id']],$dlike[$item['id'] . '-l'],'dislike',$item['id']) : '');
$location = (($item['location']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['location']) . '">' . $item['location'] . '</a>' : '');
$coord = (($item['coord']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['coord']) . '">' . $item['coord'] . '</a>' : '');
if($coord) {
if($location)
$location .= '<br /><span class="smalltext">(' . $coord . ')</span>';
else
$location = '<span class="smalltext">' . $coord . '</span>';
}
$o .= replace_macros($template,array(
'$id' => $item['item_id'],
@ -376,7 +370,7 @@ function profile_content(&$a, $update = 0) {
'$body' => bbcode($item['body']),
'$ago' => relative_date($item['created']),
'$lock' => $lock,
'$location' => (($item['location']) ? '<a target="map" href="http://maps.google.com/?q=' . urlencode($item['location']) . '">' . $item['location'] . '</a>' : ''),
'$location' => $location,
'$indent' => (($item['parent'] != $item['item_id']) ? ' comment' : ''),
'$drop' => $drop,
'$like' => $like,

View file

@ -45,7 +45,7 @@ function profile_photo_post(&$a) {
//dbg(3);
$r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = %d LIMIT 1",
dbesc($image_id),
dbesc(get_uid()),
dbesc(local_user()),
intval($scale));
if(count($r)) {
@ -56,14 +56,14 @@ function profile_photo_post(&$a) {
if($im->is_valid()) {
$im->cropImage(175,$srcX,$srcY,$srcW,$srcH);
$r = $im->store(get_uid(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 4, 1);
$r = $im->store(local_user(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 4, 1);
if($r === false)
notice ( t('Image size reduction [175] failed.') . EOL );
$im->scaleImage(80);
$r = $im->store(get_uid(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 5, 1);
$r = $im->store(local_user(), 0, $base_image['resource-id'],$base_image['filename'], t('Profile Photos'), 5, 1);
if($r === false)
notice( t('Image size reduction [80] failed.') . EOL );
@ -72,12 +72,12 @@ function profile_photo_post(&$a) {
$r = q("UPDATE `photo` SET `profile` = 0 WHERE `profile` = 1 AND `resource-id` != '%s' AND `uid` = %d",
dbesc($base_image['resource-id']),
intval(get_uid())
intval(local_user())
);
$r = q("UPDATE `contact` SET `avatar-date` = '%s' WHERE `self` = 1 AND `uid` = %d LIMIT 1",
dbesc(datetime_convert()),
intval(get_uid())
intval(local_user())
);
// Update global directory in background
@ -123,7 +123,7 @@ function profile_photo_post(&$a) {
$smallest = 0;
$r = $ph->store(get_uid(), 0 , $hash, $filename, t('Profile Photos'), 0 );
$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 0 );
if($r)
notice( t('Image uploaded successfully.') . EOL );
@ -132,7 +132,7 @@ function profile_photo_post(&$a) {
if($width > 640 || $height > 640) {
$ph->scaleImage(640);
$r = $ph->store(get_uid(), 0 , $hash, $filename, t('Profile Photos'), 1 );
$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 1 );
if($r === false)
notice( t('Image size reduction [640] failed.') . EOL );

View file

@ -157,6 +157,7 @@ function profiles_post(&$a) {
function profiles_content(&$a) {
$o = '';
$o .= '<script> $(document).ready(function() { $(\'#nav-profiles-link\').addClass(\'nav-selected\'); });</script>';
if(! local_user()) {
notice( t('Permission denied.') . EOL);
@ -266,7 +267,7 @@ function profiles_content(&$a) {
}
if(intval($a->argv[1])) {
if(($a->argc > 1) && (intval($a->argv[1]))) {
$r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($a->argv[1]),
intval($_SESSION['uid'])

View file

@ -39,7 +39,7 @@ function pubsub_init(&$a) {
$hub_lease = notags(trim($_GET['hub_lease_seconds']));
$hub_verify = notags(trim($_GET['hub_verify_token']));
logger('pubsub: Subscription from' . $_SERVER['REMOTE_ADDR'] . print_r($_GET,true));
$subscribe = (($hub_mode === 'subscribe') ? 1 : 0);
@ -80,14 +80,14 @@ function pubsub_init(&$a) {
}
}
require_once('include/security.php');
function pubsub_post(&$a) {
$xml = file_get_contents('php://input');
$debugging = get_config('system','debugging');
if($debugging)
file_put_contents('pubsub.out',$xml,FILE_APPEND);
logger('pubsub: feed arrived from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $a->cmd );
logger('pubsub: data: ' . $xml, $LOGGER_DATA);
$nick = (($a->argc > 1) ? notags(trim($a->argv[1])) : '');
$contact_id = (($a->argc > 2) ? intval($a->argv[2]) : 0);
@ -100,7 +100,7 @@ function pubsub_post(&$a) {
$importer = $r[0];
$r = q("SELECT * FROM `contact` WHERE `subhub` = 1 AND `id` = %d AND `uid` = %d AND `blocked` = 0 LIMIT 1",
$r = q("SELECT * FROM `contact` WHERE `subhub` = 1 AND `id` = %d AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1",
intval($contact_id),
intval($importer['uid'])
);

View file

@ -4,14 +4,15 @@ function redir_init(&$a) {
if((! local_user()) || (! ($a->argc == 2)) || (! intval($a->argv[1])))
goaway($a->get_baseurl());
$r = q("SELECT `issued-id`, `dfrn-id`, `duplex`, `poll` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
$r = q("SELECT `network`, `issued-id`, `dfrn-id`, `duplex`, `poll` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($a->argv[1]),
intval($_SESSION['uid']));
if(! count($r))
intval(local_user())
);
if((! count($r)) || ($r[0]['network'] !== 'dfrn'))
goaway($a->get_baseurl());
$dfrn_id = $orig_id = (($r[0]['issued-id']) ? $r[0]['issued-id'] : $r[0]['dfrn-id']);
$dfrn_id = $orig_id = $r[0]['issued-id'];
if($r[0]['duplex'] && $r[0]['issued-id']) {
$orig_id = $r[0]['issued-id'];
$dfrn_id = '1:' . $orig_id;

View file

@ -59,21 +59,12 @@ function register_post(&$a) {
if(! preg_match("/^[a-zA-Z]* [a-zA-Z]*$/",$username))
$err .= t(' That doesn\'t appear to be your full name.');
$r = q("SELECT `uid` FROM `user`
WHERE `email` = '%s' LIMIT 1",
dbesc($email)
);
if(!eregi('[A-Za-z0-9._%-]+@[A-Za-z0-9._%-]+\.[A-Za-z]{2,6}',$email))
$err .= t(' Not valid email.');
if(! allowed_email($email))
$err .= t(' Your email domain is not among those allowed on this site.');
if($r !== false && count($r))
$err .= t(' Your email address is already registered on this system.') ;
$nickname = strtolower($nickname);
if(! preg_match("/^[a-z][a-z0-9\-\_]*$/",$nickname))
$err .= t(' Nickname <strong>must</strong> start with a letter and contain only letters, numbers, dashes, or underscore.') ;
@ -170,12 +161,13 @@ function register_post(&$a) {
intval($newuid));
return;
}
$r = q("INSERT INTO `contact` ( `uid`, `created`, `self`, `name`, `photo`, `thumb`, `blocked`, `pending`, `url`,
$r = q("INSERT INTO `contact` ( `uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `blocked`, `pending`, `url`,
`request`, `notify`, `poll`, `confirm`, `name-date`, `uri-date`, `avatar-date` )
VALUES ( %d, '%s', 1, '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
VALUES ( %d, '%s', 1, '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($newuid),
datetime_convert(),
dbesc($username),
dbesc($nickname),
dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"),
dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"),
dbesc($a->get_baseurl() . "/profile/$nickname"),
@ -259,7 +251,13 @@ function register_post(&$a) {
if(! function_exists('register_content')) {
function register_content(&$a) {
if($a->config['register_policy'] == REGISTER_CLOSED) {
// logged in users can register others (people/pages/groups)
// even with closed registrations, unless specifically prohibited by site policy.
// 'block_extended_register' blocks all registrations, period.
$block = get_config('system','block_extended_register');
if((($a->config['register_policy'] == REGISTER_CLOSED) && (! getuid())) || ($block)) {
notice("Permission denied." . EOL);
return;
}

View file

@ -1,12 +1,23 @@
<?php
// TODO:
// add relevant contacts so they can use this
// There is a lot of debug stuff in here because this is quite a
// complicated process to try and sort out.
require_once('include/salmon.php');
require_once('simplepie/simplepie.inc');
function salmon_return($val) {
if($val >= 500)
if($val >= 400)
$err = 'Error';
if($val == 200)
if($val >= 200 && $val < 300)
$err = 'OK';
logger('mod-salmon returns ' . $val);
header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err);
killme();
@ -15,10 +26,8 @@ function salmon_return($val) {
function salmon_post(&$a) {
$xml = file_get_contents('php://input');
$debugging = get_config('system','debugging');
if($debugging)
file_put_contents('salmon.out',$xml,FILE_APPEND);
logger('mod-salmon: new salmon ' . $xml);
$nick = (($a->argc > 1) ? notags(trim($a->argv[1])) : '');
$mentions = (($a->argc > 2 && $a->argv[2] === 'mention') ? true : false);
@ -31,22 +40,170 @@ function salmon_post(&$a) {
$importer = $r[0];
require_once('include/items.php');
// parse the xml
$dom = simplexml_load_string($xml,'SimpleXMLElement',0,NAMESPACE_SALMON_ME);
// figure out where in the DOM tree our data is hiding
if($dom->provenance->data)
$base = $dom->provenance;
elseif($dom->env->data)
$base = $dom->env;
elseif($dom->data)
$base = $dom;
if(! $base) {
logger('mod-salmon: unable to locate salmon data in xml ');
salmon_return(400);
}
// Stash the signature away for now. We have to find their key or it won't be good for anything.
$signature = base64url_decode($base->sig);
// unpack the data
// strip whitespace so our data element will return to one big base64 blob
$data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data);
// stash away some other stuff for later
$type = $base->data[0]->attributes()->type[0];
$keyhash = $base->sig[0]->attributes()->keyhash[0];
$encoding = $base->encoding;
$alg = $base->alg;
// If we're talking to status.net or one of their ilk, they aren't following the magic envelope spec
// and only signed the data element. We'll be nice and let them validate anyway.
$stnet_signed_data = $data;
$signed_data = $data . '.' . base64url_encode($type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($alg);
// decode the data
$data = base64url_decode($data);
// Remove the xml declaration
$data = preg_replace('/\<\?xml[^\?].*\?\>/','',$data);
// Create a fake feed wrapper so simplepie doesn't choke
$tpl = load_view_file('view/atom_feed.tpl');
$tpl = load_view_file('view/fake_feed.tpl');
$base = substr($xml,strpos($xml,'<entry'));
$base = substr($data,strpos($data,'<entry'));
$xml = $tpl . $base . '</feed>';
$feedxml = $tpl . $base . '</feed>';
salmon_return(500); // until the handler is finished
logger('mod-salmon: Processed feed: ' . $feedxml);
// consume_salmon($xml,$importer);
// Now parse it like a normal atom feed to scrape out the author URI
$feed = new SimplePie();
$feed->set_raw_data($feedxml);
$feed->enable_order_by_date(false);
$feed->init();
logger('mod-salmon: Feed parsed.');
if($feed->get_item_quantity()) {
foreach($feed->get_items() as $item) {
$author = $item->get_author();
$author_link = unxmlify($author->get_link());
break;
}
}
if(! $author_link) {
logger('mod-salmon: Could not retrieve author URI.');
salmon_return(400);
}
// Once we have the author URI, go to the web and try to find their public key
logger('mod-salmon: Fetching key for ' . $author_link );
$key = get_salmon_key($author_link,$keyhash);
if(! $key) {
logger('mod-salmon: Could not retrieve author key.');
salmon_return(400);
}
// Setup RSA stuff to verify the signature
set_include_path(get_include_path() . PATH_SEPARATOR . 'phpsec');
require_once('phpsec/Crypt/RSA.php');
$key_info = explode('.',$key);
$m = base64url_decode($key_info[1]);
$e = base64url_decode($key_info[2]);
logger('mod-salmon: key details: ' . print_r($key_info,true));
$rsa = new CRYPT_RSA();
$rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
$rsa->setHash('sha256');
$rsa->modulus = new Math_BigInteger($m, 256);
$rsa->k = strlen($rsa->modulus->toBytes());
$rsa->exponent = new Math_BigInteger($e, 256);
// We should have everything we need now. Let's see if it verifies.
// If it fails with the proper data format, try again using just the data
// (e.g. status.net)
$verify = $rsa->verify($signed_data,$signature);
if(! $verify)
$verify = $rsa->verify($stnet_signed_data,$signature);
if(! $verify) {
logger('mod-salmon: Message did not verify. Discarding.');
salmon_return(400);
}
logger('mod-salmon: Message verified.');
/*
*
* If we reached this point, the message is good. Now let's figure out if the author is allowed to send us stuff.
*
*/
$r = q("SELECT * FROM `contact` WHERE `network` = 'stat' AND ( `url` = '%s' OR `lrdd` = '%s')
AND `uid` = %d LIMIT 1",
dbesc($author_link),
dbesc($author_link),
intval($importer['uid'])
);
if(! count($r)) {
logger('mod-salmon: Author unknown to us.');
}
if((count($r)) && ($r[0]['readonly'])) {
logger('mod-salmon: Ignoring this author.');
salmon_return(202);
// NOTREACHED
}
require_once('include/items.php');
// Placeholder for hub discovery. We shouldn't find any hubs
// since we supplied the fake feed header - and it doesn't have any.
$hub = '';
// consume_feed will only accept a follow activity from this person if there is no contact record.
consume_feed($feedxml,$importer,((count($r)) ? $r[0] : null),$hub);
salmon_return(200);
}

View file

@ -15,7 +15,7 @@ function settings_post(&$a) {
notice( t('Permission denied.') . EOL);
return;
}
if(count($a->user) && x($a->user,'uid') && $a->user['uid'] != get_uid()) {
if(count($a->user) && x($a->user,'uid') && $a->user['uid'] != local_user()) {
notice( t('Permission denied.') . EOL);
return;
}
@ -39,7 +39,7 @@ function settings_post(&$a) {
$password = hash('whirlpool',$newpass);
$r = q("UPDATE `user` SET `password` = '%s' WHERE `uid` = %d LIMIT 1",
dbesc($password),
intval(get_uid())
intval(local_user())
);
if($r)
notice( t('Password changed.') . EOL);
@ -54,9 +54,11 @@ function settings_post(&$a) {
$timezone = notags(trim($_POST['timezone']));
$defloc = notags(trim($_POST['defloc']));
$allow_location = (($_POST['allow_location'] == 1) ? 1: 0);
$publish = (($_POST['profile_in_directory'] == 1) ? 1: 0);
$net_publish = (($_POST['profile_in_netdirectory'] == 1) ? 1: 0);
$old_visibility = ((intval($_POST['visibility']) == 1) ? 1 : 0);
$page_flags = ((intval($_POST['page-flags'])) ? intval($_POST['page-flags']) : 0);
$notify = 0;
@ -81,34 +83,29 @@ function settings_post(&$a) {
if(strlen($username) < 3)
$err .= t(' Name too short.');
}
if($email != $a->user['email']) {
$email_changed = true;
if(!eregi('[A-Za-z0-9._%-]+@[A-Za-z0-9._%-]+\.[A-Za-z]{2,6}',$email))
$err .= t(' Not valid email.');
$r = q("SELECT `uid` FROM `user`
WHERE `email` = '%s' LIMIT 1",
dbesc($email)
);
if($r !== NULL && count($r))
$err .= t(' This email address is already registered.');
}
if(strlen($err)) {
notice($err . EOL);
return;
}
if(strlen($err)) {
notice($err . EOL);
return;
}
if($timezone != $a->user['timezone']) {
if(strlen($timezone))
date_default_timezone_set($timezone);
}
$str_group_allow = perms2str($_POST['group_allow']);
$str_contact_allow = perms2str($_POST['contact_allow']);
$str_group_deny = perms2str($_POST['group_deny']);
$str_contact_deny = perms2str($_POST['contact_deny']);
$r = q("UPDATE `user` SET `username` = '%s', `email` = '%s', `timezone` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `notify-flags` = %d, `default-location` = '%s', `theme` = '%s' WHERE `uid` = %d LIMIT 1",
$r = q("UPDATE `user` SET `username` = '%s', `email` = '%s', `timezone` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `notify-flags` = %d, `page-flags` = %d, `default-location` = '%s', `allow_location` = %d, `theme` = '%s' WHERE `uid` = %d LIMIT 1",
dbesc($username),
dbesc($email),
dbesc($timezone),
@ -117,9 +114,11 @@ function settings_post(&$a) {
dbesc($str_contact_deny),
dbesc($str_group_deny),
intval($notify),
intval($page_flags),
dbesc($defloc),
intval($allow_location),
dbesc($theme),
intval(get_uid())
intval(local_user())
);
if($r)
notice( t('Settings updated.') . EOL);
@ -129,7 +128,7 @@ function settings_post(&$a) {
WHERE `is-default` = 1 AND `uid` = %d LIMIT 1",
intval($publish),
intval($net_publish),
intval(get_uid())
intval(local_user())
);
if($old_visibility != $net_publish) {
@ -155,6 +154,8 @@ function settings_post(&$a) {
if(! function_exists('settings_content')) {
function settings_content(&$a) {
$o = '';
$o .= '<script> $(document).ready(function() { $(\'#nav-settings-link\').addClass(\'nav-selected\'); });</script>';
if(! local_user()) {
@ -180,6 +181,18 @@ function settings_content(&$a) {
if(! strlen($a->user['timezone']))
$timezone = date_default_timezone_get();
$pageset_tpl = load_view_file('view/pagetypes.tpl');
$pagetype = replace_macros($pageset_tpl,array(
'$normal' => (($a->user['page-flags'] == PAGE_NORMAL) ? " checked=\"checked\" " : ""),
'$soapbox' => (($a->user['page-flags'] == PAGE_SOAPBOX) ? " checked=\"checked\" " : ""),
'$community' => (($a->user['page-flags'] == PAGE_COMMUNITY) ? " checked=\"checked\" " : ""),
'$freelove' => (($a->user['page-flags'] == PAGE_FREELOVE) ? " checked=\"checked\" " : ""),
'$page_normal' => PAGE_NORMAL,
'$page_soapbox' => PAGE_SOAPBOX,
'$page_community' => PAGE_COMMUNITY,
'$page_freelove' => PAGE_FREELOVE
));
$opt_tpl = load_view_file("view/profile-in-directory.tpl");
$profile_in_dir = replace_macros($opt_tpl,array(
@ -198,11 +211,13 @@ function settings_content(&$a) {
else
$profile_in_net_dir = '';
$loc_checked = (($a->user['allow_location'] == 1) ? " checked=\"checked\" " : "");
$invisible = (((! $profile['publish']) && (! $profile['net-publish']))
? true : false);
if($invisible)
notice( t('Profile is not published.') . EOL );
notice( t('Profile is <strong>not published</strong>.') . EOL );
$nickname_block = load_view_file("view/settings_nick_set.tpl");
@ -238,6 +253,8 @@ function settings_content(&$a) {
$stpl = load_view_file('view/settings.tpl');
$celeb = ((($a->user['page-flags'] == PAGE_SOAPBOX) || ($a->user['page-flags'] == PAGE_COMMUNITY)) ? true : false);
$o .= replace_macros($stpl,array(
'$baseurl' => $a->get_baseurl(),
'$uid' => $_SESSION['uid'],
@ -247,17 +264,19 @@ function settings_content(&$a) {
'$timezone' => $timezone,
'$zoneselect' => select_timezone($timezone),
'$defloc' => $defloc,
'$loc_checked' => $loc_checked,
'$profile_in_dir' => $profile_in_dir,
'$profile_in_net_dir' => $profile_in_net_dir,
'$permissions' => t('Default Post Permissions'),
'$visibility' => $profile['net-publish'],
'$aclselect' => populate_acl($a->user),
'$aclselect' => populate_acl($a->user,$celeb),
'$sel_notify1' => (($notify & NOTIFY_INTRO) ? ' checked="checked" ' : ''),
'$sel_notify2' => (($notify & NOTIFY_CONFIRM) ? ' checked="checked" ' : ''),
'$sel_notify3' => (($notify & NOTIFY_WALL) ? ' checked="checked" ' : ''),
'$sel_notify4' => (($notify & NOTIFY_COMMENT) ? ' checked="checked" ' : ''),
'$sel_notify5' => (($notify & NOTIFY_MAIL) ? ' checked="checked" ' : ''),
'$theme' => $theme_selector
'$theme' => $theme_selector,
'$pagetype' => $pagetype
));
return $o;

View file

@ -34,7 +34,7 @@ function wall_upload_post(&$a) {
$smallest = 0;
$r = $ph->store(get_uid(), 0, $hash, $filename, t('Wall Photos'), 0 );
$r = $ph->store(local_user(), 0, $hash, $filename, t('Wall Photos'), 0 );
if(! $r) {
echo ( t('Image upload failed.') . EOL);
@ -43,14 +43,14 @@ function wall_upload_post(&$a) {
if($width > 640 || $height > 640) {
$ph->scaleImage(640);
$r = $ph->store(get_uid(), 0, $hash, $filename, t('Wall Photos'), 1 );
$r = $ph->store(local_user(), 0, $hash, $filename, t('Wall Photos'), 1 );
if($r)
$smallest = 1;
}
if($width > 320 || $height > 320) {
$ph->scaleImage(320);
$r = $ph->store(get_uid(), 0, $hash, $filename, t('Wall Photos'), 2 );
$r = $ph->store(local_user(), 0, $hash, $filename, t('Wall Photos'), 2 );
if($r)
$smallest = 2;
}

View file

@ -5,11 +5,16 @@ require_once('salmon.php');
function xrd_content(&$a) {
$uri = urldecode(notags(trim($_GET['uri'])));
$local = str_replace('acct:', '', $uri);
if(substr($local,0,2) == '//')
$local = substr($local,2);
$name = substr($local,0,strpos($local,'@'));
if(substr($uri,0,4) === 'http')
$name = basename($uri);
else {
$local = str_replace('acct:', '', $uri);
if(substr($local,0,2) == '//')
$local = substr($local,2);
$name = substr($local,0,strpos($local,'@'));
}
$r = q("SELECT * FROM `user` WHERE `nickname` = '%s' LIMIT 1",
dbesc($name)
@ -28,7 +33,7 @@ function xrd_content(&$a) {
'$accturi' => $uri,
'$profile_url' => $a->get_baseurl() . '/profile/' . $r[0]['nickname'],
'$atom' => $a->get_baseurl() . '/dfrn_poll/' . $r[0]['nickname'],
'$photo' => $a->get_baseurl() . '/photo/profile/' . $r[0]['uid'],
'$photo' => $a->get_baseurl() . '/photo/profile/' . $r[0]['uid'] . '.jpg',
'$salmon' => $a->get_baseurl() . '/salmon/' . $r[0]['nickname'],
'$salmen' => $a->get_baseurl() . '/salmon/' . $r[0]['nickname'] . '/mention',
'$modexp' => 'data:application/magic-public-key,' . $salmon_key

View file

@ -63,3 +63,37 @@ function update_1006() {
}
}
}
function update_1007() {
q("ALTER TABLE `user` ADD `page-flags` INT NOT NULL DEFAULT '0' AFTER `notify-flags`");
q("ALTER TABLE `user` ADD INDEX ( `nickname` )");
}
function update_1008() {
q("ALTER TABLE `profile` ADD `with` TEXT NOT NULL AFTER `marital` ");
}
function update_1009() {
q("ALTER TABLE `user` ADD `allow_location` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `default-location` ");
}
function update_1010() {
q("ALTER TABLE `contact` ADD `lrdd` CHAR( 255 ) NOT NULL AFTER `url` ");
}
function update_1011() {
q("ALTER TABLE `contact` ADD `nick` CHAR( 255 ) NOT NULL AFTER `name` ");
$r = q("SELECT * FROM `contact` WHERE 1");
if(count($r)) {
foreach($r as $rr) {
q("UPDATE `contact` SET `nick` = '%s' WHERE `id` = %d LIMIT 1",
dbesc(basename($rr['url'])),
intval($rr['id'])
);
}
}
}
function update_1012() {
q("ALTER TABLE `item` ADD `inform` MEDIUMTEXT NOT NULL AFTER `tag` ");
}

View file

@ -1,13 +0,0 @@
-- Run this with mysql or import into phpmyadmin if you installed mistpark between Sep22 and Oct 6 2010.
-- The database schema was missing some updates
ALTER TABLE `item` DROP `like`, DROP `dislike` ;
ALTER TABLE `item` ADD `verb` CHAR( 255 ) NOT NULL AFTER `body` ,
ADD `object-type` CHAR( 255 ) NOT NULL AFTER `verb` ,
ADD `object` TEXT NOT NULL AFTER `object-type` ;
ALTER TABLE `intro` ADD `duplex` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `knowyou` ;
ALTER TABLE `contact` ADD `duplex` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `rel` ;
ALTER TABLE `contact` ADD `term-date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `avatar-date`;

View file

@ -18,6 +18,9 @@ $a->strings[' other people'] = ' other people';
$a->strings[' like this.'] = ' like this.';
$a->strings[' don\'t like this.'] = ' don\'t like this.';
$a->strings["Invite Friends"] = "Invite Friends";
$a->strings['Connect/Follow [profile address]'] = 'Connect/Follow [profile address]';
$a->strings['Example: bob@example.com, http://example.com/barbara'] = 'Example: bob@example.com, http://example.com/barbara';
$a->strings['Follow'] = 'Follow';
$a->strings['Could not access contact record.'] = 'Could not access contact record.';
$a->strings['Could not locate selected profile.'] = 'Could not locate selected profile.';
$a->strings['Contact updated.'] = 'Contact updated.';
@ -46,13 +49,13 @@ $a->strings['Find'] = 'Find';
$a->strings['Visit '] = 'Visit ';
$a->strings['\'s profile'] = '\'s profile';
$a->strings['Edit contact'] = 'Edit contact';
$a->strings['Profile not found.'] = 'Profile not found.';
$a->strings['Response from remote site was not understood.'] = 'Response from remote site was not understood.';
$a->strings['Unexpected response from remote site: '] = 'Unexpected response from remote site: ';
$a->strings["Confirmation completed successfully."] = "Confirmation completed successfully.";
$a->strings['Remote site reported: '] = 'Remote site reported: ';
$a->strings["Temporary failure. Please wait and try again."] = "Temporary failure. Please wait and try again.";
$a->strings["Introduction failed or was revoked."] = "Introduction failed or was revoked.";
$a->strings['Contact Photos'] = 'Contact Photos';
$a->strings['Unable to set contact photo.'] = 'Unable to set contact photo.';
$a->strings['No user record found for '] = 'No user record found for ';
$a->strings['Our site encryption key is apparently messed up.'] = 'Our site encryption key is apparently messed up.';
@ -81,6 +84,7 @@ $a->strings['Profile unavailable.'] = 'Profile unavailable.';
$a->strings["Invalid locator"] = "Invalid locator";
$a->strings["Unable to resolve your name at the provided location."] = "Unable to resolve your name at the provided location.";
$a->strings['You have already introduced yourself here.'] = 'You have already introduced yourself here.';
$a->strings['Apparently you are already friends with .'] = 'Apparently you are already friends with .';
$a->strings['Invalid profile URL.'] = 'Invalid profile URL.';
$a->strings['Disallowed profile URL.'] = 'Disallowed profile URL.';
$a->strings['Your introduction has been sent.'] = 'Your introduction has been sent.';
@ -92,6 +96,9 @@ $a->strings['Item not found.'] = 'Item not found.';
$a->strings['Private Message'] = 'Private Message';
$a->strings['This is you'] = 'This is you';
$a->strings['Item has been removed.'] = 'Item has been removed.';
$a->strings['The profile address specified does not provide adequate information.'] = 'The profile address specified does not provide adequate information.';
$a->strings['Unable to retrieve contact information.'] = 'Unable to retrieve contact information.';
$a->strings['following'] = 'following';
$a->strings['Group created.'] = 'Group created.';
$a->strings['Could not create group.'] = 'Could not create group.';
$a->strings['Group not found.'] = 'Group not found.';
@ -132,6 +139,7 @@ $a->strings['doesn\'t like'] = 'doesn\'t like';
$a->strings['\'s'] = '\'s';
$a->strings['Visible to:'] = 'Visible to:';
$a->strings['No recipient selected.'] = 'No recipient selected.';
$a->strings['[no subject]'] = '[no subject]';
$a->strings['Unable to locate contact information.'] = 'Unable to locate contact information.';
$a->strings['Message sent.'] = 'Message sent.';
$a->strings['Message could not be sent.'] = 'Message could not be sent.';
@ -159,10 +167,14 @@ $a->strings['Discard'] = 'Discard';
$a->strings['Ignore'] = 'Ignore';
$a->strings['Show Ignored Requests'] = 'Show Ignored Requests';
$a->strings['Hide Ignored Requests'] = 'Hide Ignored Requests';
$a->strings['Claims to be known to you: '] = 'Claims to be known to you: ';
$a->strings['yes'] = 'yes';
$a->strings['no'] = 'no';
$a->strings['Friend/Connect Request'] = 'Friend/Connect Request';
$a->strings['New Follower'] = 'New Follower';
$a->strings['No notifications.'] = 'No notifications.';
$a->strings['Photo Albums'] = 'Photo Albums';
$a->strings['Contact Photos'] = 'Contact Photos';
$a->strings['Profile Photos'] = 'Profile Photos';
$a->strings['Album not found.'] = 'Album not found.';
$a->strings['Delete Album'] = 'Delete Album';
@ -181,9 +193,10 @@ $a->strings['View Photo'] = 'View Photo';
$a->strings['Photo not available'] = 'Photo not available';
$a->strings['Edit photo'] = 'Edit photo';
$a->strings['View Full Size'] = 'View Full Size';
$a->strings['In this photo: '] = 'In this photo: ';
$a->strings['Tags: '] = 'Tags: ';
$a->strings['Caption'] = 'Caption';
$a->strings['Tags'] = 'Tags';
$a->strings['Add a Tag'] = 'Add a Tag';
$a->strings['Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping'] = 'Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping';
$a->strings['Recent Photos'] = 'Recent Photos';
$a->strings['Upload New Photos'] = 'Upload New Photos';
$a->strings['View Album'] = 'View Album';
@ -194,7 +207,6 @@ $a->strings['Image size reduction [80] failed.'] = 'Image size reduction [80] fa
$a->strings['Unable to process image'] = 'Unable to process image';
$a->strings['Image uploaded successfully.'] = 'Image uploaded successfully.';
$a->strings['Image size reduction [640] failed.'] = 'Image size reduction [640] failed.';
$a->strings['Profile not found.'] = 'Profile not found.';
$a->strings['Profile Name is required.'] = 'Profile Name is required.';
$a->strings['Profile updated.'] = 'Profile updated.';
$a->strings['Profile deleted.'] = 'Profile deleted.';
@ -210,7 +222,6 @@ $a->strings[' Name too short.'] = ' Name too short.';
$a->strings[' That doesn\'t appear to be your full name.'] = ' That doesn\'t appear to be your full name.';
$a->strings[' Not valid email.'] = ' Not valid email.';
$a->strings[' Your email domain is not among those allowed on this site.'] = ' Your email domain is not among those allowed on this site.';
$a->strings[' Your email address is already registered on this system.'] = ' Your email address is already registered on this system.';
$a->strings[' Nickname <strong>must</strong> start with a letter and contain only letters, numbers, dashes, or underscore.'] = ' Nickname <strong>must</strong> start with a letter and contain only letters, numbers, dashes, or underscore.';
$a->strings[' Nickname is already registered. Please choose another.'] = ' Nickname is already registered. Please choose another.';
$a->strings['An error occurred during registration. Please try again.'] = 'An error occurred during registration. Please try again.';
@ -229,9 +240,8 @@ $a->strings['Passwords do not match. Password unchanged.'] = 'Passwords do not m
$a->strings['Empty passwords are not allowed. Password unchanged.'] = 'Empty passwords are not allowed. Password unchanged.';
$a->strings['Password changed.'] = 'Password changed.';
$a->strings['Password update failed. Please try again.'] = 'Password update failed. Please try again.';
$a->strings[' This email address is already registered.'] = ' This email address is already registered.';
$a->strings['Settings updated.'] = 'Settings updated.';
$a->strings['Profile is not published.'] = 'Profile is not published.';
$a->strings['Profile is <strong>not published</strong>.'] = 'Profile is <strong>not published</strong>.';
$a->strings['Default Post Permissions'] = 'Default Post Permissions';
$a->strings['View Contacts'] = 'View Contacts';
$a->strings['No contacts.'] = 'No contacts.';

View file

@ -5,6 +5,11 @@
include 'boot.php';
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
ini_set('display_errors', '1');
ini_set('log_errors','0');
$a = new App();
$files = glob('mod/*.php');

View file

@ -30,27 +30,30 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) {
function contact_select($selname, $selclass, $preselected = false, $size = 4, $privmail = false) {
function contact_select($selname, $selclass, $preselected = false, $size = 4, $privmail = false, $celeb = false) {
$o = '';
// When used for private messages, we limit correspondence to mutual friends and the selector
// to one recipient. By default our selector allows multiple selects amongst all contacts.
if($privmail) {
$sql_extra = '';
if($privmail || $celeb) {
$sql_extra = sprintf(" AND `rel` = %d ", intval(REL_BUD));
$o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"$size\" >\r\n";
}
else {
$sql_extra = '';
$o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" >\r\n";
}
$r = q("SELECT `id`, `name`, `url` FROM `contact`
if($privmail)
$o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"$size\" >\r\n";
else
$o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" >\r\n";
$r = q("SELECT `id`, `name`, `url`, `network` FROM `contact`
WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0
$sql_extra
ORDER BY `name` ASC ",
$_SESSION['uid']
intval(local_user())
);
if(count($r)) {
@ -59,7 +62,11 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p
$selected = " selected=\"selected\" ";
else
$selected = '';
$o .= "<option value=\"{$rr['id']}\" $selected title=\"{$rr['url']}\" >{$rr['name']}</option>\r\n";
if($rr['network'] === 'stat')
$disabled = ' disabled="true" ' ;
else
$disabled = '';
$o .= "<option value=\"{$rr['id']}\" $selected $disabled title=\"{$rr['url']}\" >{$rr['name']}</option>\r\n";
}
}
@ -73,7 +80,7 @@ function fixacl(&$item) {
$item = intval(str_replace(array('<','>'),array('',''),$item));
}
function populate_acl($user = null) {
function populate_acl($user = null,$celeb = false) {
$allow_cid = $allow_gid = $deny_cid = $deny_gid = false;
@ -104,7 +111,7 @@ function populate_acl($user = null) {
$o .= '</div>';
$o .= '<div id="contact_allow_wrapper">';
$o .= '<label id="acl-allow-contact-label" for="contact_allow" >' . t('Contacts') . '</label>';
$o .= contact_select('contact_allow','contact_allow',$allow_cid);
$o .= contact_select('contact_allow','contact_allow',$allow_cid,4,false,$celeb);
$o .= '</div>';
$o .= '</div>' . "\r\n";
$o .= '<div id="acl-allow-end"></div>' . "\r\n";
@ -119,7 +126,7 @@ function populate_acl($user = null) {
$o .= '</div>';
$o .= '<div id="contact_deny_wrapper" >';
$o .= '<label id="acl-deny-contact-label" for="contact_deny" >' . t('Contacts') . '</label>';
$o .= contact_select('contact_deny','contact_deny', $deny_cid);
$o .= contact_select('contact_deny','contact_deny', $deny_cid,4,false, $celeb);
$o .= '</div>';
$o .= '</div>' . "\r\n";
$o .= '<div id="acl-deny-end"></div>' . "\r\n";

View file

@ -16,5 +16,6 @@
<dfrn:comment-allow>$comment_allow</dfrn:comment-allow>
<as:verb>$verb</as:verb>
$actobj
$mentioned
</entry>

View file

@ -4,7 +4,9 @@
xmlns:at="http://purl.org/atompub/tombstones/1.0"
xmlns:media="http://purl.org/syndication/atommedia"
xmlns:dfrn="http://purl.org/macgirvin/dfrn/1.0"
xmlns:as="http://activitystrea.ms/spec/1.0/" >
xmlns:as="http://activitystrea.ms/spec/1.0/"
xmlns:georss="http://www.georss.org/georss"
xmlns:poco="http://portablecontacts.net/spec/1.0" >
<id>$feed_id</id>
<title>$feed_title</title>

View file

@ -19,8 +19,10 @@
<content type="$type" >$content</content>
<link rel="alternate" href="$alt" />
<dfrn:location>$location</dfrn:location>
<georss:point>$coord</georss:point>
<dfrn:comment-allow>$comment_allow</dfrn:comment-allow>
<as:verb>$verb</as:verb>
$actobj
$mentioned
</entry>

29
view/auto_request.tpl Normal file
View file

@ -0,0 +1,29 @@
<h1>Friend/Connection Request</h1>
<p id="dfrn-request-intro">
Please enter your profile address from one of the following supported social networks:<br />
<ul id="dfrn-request-networks">
<li><a href="http://dfrn.org">Mistpark/DFRN</a> (fully supported)</li>
<li><a href="http://ostatus.org">StatusNet/GNU-social/Federation</a> (limited - experimental)</li>
</ul>
</p>
<form action="dfrn_request/$nickname" method="post" />
<div id="dfrn-request-url-wrapper" >
<label id="dfrn-url-label" for="dfrn-url" >Your profile address:</label>
<input type="text" name="dfrn_url" id="dfrn-url" size="32" value="$myaddr" />
<div id="dfrn-request-url-end"></div>
</div>
<div id="dfrn-request-info-wrapper" >
</div>
<div id="dfrn-request-submit-wrapper">
<input type="submit" name="submit" id="dfrn-request-submit-button" value="Submit Request" />
<input type="submit" name="cancel" id="dfrn-request-cancel-button" value="Cancel" />
</div>
</form>

View file

@ -1,23 +1,21 @@
<div class="comment-$wwedit-wrapper" id="comment-edit-wrapper-$id" style="display: block;">
<form class="comment-edit-form" id="comment-edit-form-$id" action="item" method="post" >
<input type="hidden" name="type" value="$type" />
<input type="hidden" name="profile_uid" value="$profile_uid" />
<input type="hidden" name="parent" value="$parent" />
<input type="hidden" name="return" value="$return_path" />
<div class="comment-edit-photo" id="comment-edit-photo-$id" >
<a class="comment-edit-photo-link" href="$mylink" title="$mytitle"><img class="my-comment-photo" src="$myphoto" alt="$mytitle" title="$mytitle" /></a>
</div>
<div class="comment-edit-photo-end"></div>
<textarea id="comment-edit-text-$id" class="comment-edit-text-empty" name="body" onFocus="commentOpen(this,$id);" onBlur="commentClose(this,$id);" >Comment</textarea>
<div class="comment-$wwedit-wrapper" id="comment-edit-wrapper-$id" style="display: block;">
<form class="comment-edit-form" id="comment-edit-form-$id" action="item" method="post" >
<input type="hidden" name="type" value="$type" />
<input type="hidden" name="profile_uid" value="$profile_uid" />
<input type="hidden" name="parent" value="$parent" />
<input type="hidden" name="return" value="$return_path" />
<div class="comment-edit-text-end"></div>
<div class="comment-edit-submit-wrapper" id="comment-edit-submit-wrapper-$id" style="display: none;" >
<input type="submit" id="comment-edit-submit-$id" class="comment-edit-submit" name="submit" value="Submit" />
</div>
<div class="comment-edit-photo" id="comment-edit-photo-$id" >
<a class="comment-edit-photo-link" href="$mylink" title="$mytitle"><img class="my-comment-photo" src="$myphoto" alt="$mytitle" title="$mytitle" /></a>
<div class="comment-edit-end"></div>
</form>
</div>
<div class="comment-edit-photo-end"></div>
<textarea id="comment-edit-text-$id" class="comment-edit-text-empty" name="body" onFocus="commentOpen(this,$id);" onBlur="commentClose(this,$id);" >Comment</textarea>
<div class="comment-edit-text-end"></div>
<div class="comment-edit-submit-wrapper" id="comment-edit-submit-wrapper-$id" style="display: none;" >
<input type="submit" id="comment-edit-submit-$id" class="comment-edit-submit" name="submit" value="Submit" />
</div>
<div class="comment-edit-end"></div>
</form>
</div>

View file

@ -31,6 +31,7 @@
</div>
<div id="contact-edit-end" ></div>
$insecure
$blocked
$ignored

View file

@ -1,10 +1,13 @@
<?php
function contact_profile_assign($current) {
function contact_profile_assign($current,$foreign_net) {
$o = '';
$o .= "<select id=\"contact-profile-selector\" name=\"profile-assign\" />\r\n";
$disabled = (($foreign_net) ? ' disabled="true" ' : '');
$o .= "<select id=\"contact-profile-selector\" $disabled name=\"profile-assign\" />\r\n";
$r = q("SELECT `id`, `profile-name` FROM `profile` WHERE `uid` = %d",
intval($_SESSION['uid']));

View file

@ -1,17 +1,17 @@
<!DOCTYPE html >
<html>
<head>
<title><?php echo $page['title'] ?></title>
<?php echo $page['htmlhead'] ?>
<title><?php if(x($page,'title')) echo $page['title'] ?></title>
<?php if(x($page,'htmlhead')) echo $page['htmlhead'] ?>
</head>
<body>
<header><?php echo $page['header']; ?></header>
<nav><div id="top-margin"></div><?php echo $page['nav']; ?></nav>
<aside><?php echo $page['aside']; ?></aside>
<section><?php echo $page['content']; ?>
<header><?php if(x($page,'header')) echo $page['header']; ?></header>
<nav><div id="top-margin"></div><?php if(x($page,'nav')) echo $page['nav']; ?></nav>
<aside><?php if(x($page,'aside')) echo $page['aside']; ?></aside>
<section><?php if(x($page,'content')) echo $page['content']; ?>
<div id="page-footer"></div>
</section>
<footer><?php echo $page['footer']; ?></footer>
<footer><?php if(x($page,'footer')) echo $page['footer']; ?></footer>
</body>
</html>

View file

@ -6,7 +6,7 @@ You may request a connection with this member if you have a valid profile addres
on one of the following social networks:<br />
<ul id="dfrn-request-networks">
<li><a href="http://dfrn.org">Mistpark/DFRN</a> (fully supported)</li>
<li><a href="http://ostatus.org">Federation/OStatus/Diaspora/GNU-social</a> (limited - experimental)</li>
<li><a href="http://ostatus.org">StatusNet/GNU-social/Federation</a> (limited - experimental)</li>
</ul>
</p>
@ -14,7 +14,7 @@ on one of the following social networks:<br />
<div id="dfrn-request-url-wrapper" >
<label id="dfrn-url-label" for="dfrn-url" >Your profile address:</label>
<input type="text" name="dfrn_url" id="dfrn-url" size="32" />
<input type="text" name="dfrn_url" id="dfrn-url" size="32" value="$myaddr" />
<div id="dfrn-request-url-end"></div>
</div>
@ -25,7 +25,7 @@ Please answer the following:
<div id="dfrn-request-info-wrapper" >
<p id="doiknowyou">
Do I know you?
Does $name know you?
</p>
<div id="dfrn-request-know-yes-wrapper">

13
view/fake_feed.tpl Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" >
<id>fake feed</id>
<title>fake title</title>
<updated>1970-01-01T00:00:00Z</updated>
<author>
<name>Fake Name</name>
<uri>http://example.com</uri>
</author>

10
view/follow.tpl Normal file
View file

@ -0,0 +1,10 @@
<div class="side-follow-wrapper" id="side-follow-wrapper" >
<form action="follow" method="post" />
<label id="side-follow-label" for="side-follow-url" >$label</label>
<input id="side-follow-url" type="text" name="url" size="24" title="$hint" />
<div class="side-follow-input-end"></div>
<input id="side-follow-submit" type="submit" name="submit" value="$follow" />
</form>
</div>
<div class="side-follow-end"></div>

24
view/follow_slap.tpl Normal file
View file

@ -0,0 +1,24 @@
<entry>
<author>
<name>$name</name>
<uri>$profile_page</uri>
<link rel="photo" type="image/jpeg" media:width="80" media:height="80" href="$thumb" />
<link rel="avatar" type="image/jpeg" media:width="80" media:height="80" href="$thumb" />
</author>
<id>$item_id</id>
<title>$title</title>
<published>$published</published>
<content type="$type" >$content</content>
<as:actor>
<as:object-type>http://activitystrea.ms/schema/1.0/person</as:object-type>
<id>$profile_page</id>
<title></title>
<link rel="avatar" type="image/jpeg" media:width="175" media:height="175" href="$photo"/>
<link rel="avatar" type="image/jpeg" media:width="80" media:height="80" href="$thumb"/>
<poco:preferredUsername>$nick</poco:preferredUsername>
<poco:displayName>$name</poco:displayName>
</as:actor>
<as:verb>$verb</as:verb>
</entry>

11
view/insecure_net.tpl Normal file
View file

@ -0,0 +1,11 @@
<div id="profile-edit-insecure">
<p>
The social network that $name belongs to is an <strong>open network</strong> with no privacy controls.
$name will only be able to view your public posts and will <strong>not</strong> be allowed to
participate in private conversations or use other secure features within this network.
</p>
<p>
$name <strong>may</strong> also have been automatically set to "ignored" as a spam prevention measure. You may
change this (using the above settings) if you wish to allow incoming messages from $name.
</p>
</div>

View file

@ -1,27 +1,19 @@
Dear $username,
I've got good news and bad news... first the good news.
'$fn' at '$dfrn_url' has accepted your connection request at
'$sitename'.
'$fn' at '$dfrn_url' has accepted
your connection request at '$sitename'.
The bad news is that '$fn' did not make you a "full friend",
but rather accepted you as a "fan". [Maybe you were expecting this,
maybe not.]
'$fn' has chosen to accept you a "fan", which restricts
some forms of communication - such as private messaging and some profile
interactions. If this is a celebrity or community page, these settings were
applied automatically.
What this means is that '$fn' can communicate with you at any
time and comment on your activities, but your communications to
'$fn' may be restricted. In particular, you do NOT have the
ability to exchange private mail. You are only able to communicate
with '$fn' via your own status updates.
'$fn' may choose to extend this into a two-way or more permissive
relationship in the future.
In the future, '$fn' MAY decide to seek a full connection and make
a reciprocal request. If you approve such a request, you will then be
considered mutual friends with full communication ability.
The network at $sitename allows many types of relationships -
as opposed to older social networks where friendship is either
"yes" or "no" - with nothing in between.
You will start receiving public status updates from '$fn',
which will appear on your 'Network' page at
$siteurl

View file

@ -1,12 +1,12 @@
<div class="intro-wrapper" id="intro-$contact-id" >
<div class="intro-wrapper" id="intro-$contact_id" >
<p class="intro-desc">Notification type: Friend/Connect Request</p>
<div class="intro-fullname" id="intro-fullname-$contact-id" >$fullname</div>
<a class="intro-url-link" id="intro-url-link-$contact-id" href="$url" ><img id="photo-$contact-id" class="intro-photo" src="$photo" width="175" height=175" name="$fullname" alt="fullname" /></a>
<div class="intro-knowyou">Presumably known to you? <strong>$knowyou</strong></div>
<div class="intro-note" id="intro-note-$contact-id">$note</div>
<div class="intro-wrapper-end" id="intro-wrapper-end-$contact-id"></div>
<p class="intro-desc">Notification type: $notify_type</p>
<div class="intro-fullname" id="intro-fullname-$contact_id" >$fullname</div>
<a class="intro-url-link" id="intro-url-link-$contact_id" href="$url" ><img id="photo-$contact_id" class="intro-photo" src="$photo" width="175" height=175" name="$fullname" alt="fullname" /></a>
<div class="intro-knowyou">$knowyou</div>
<div class="intro-note" id="intro-note-$contact_id">$note</div>
<div class="intro-wrapper-end" id="intro-wrapper-end-$contact_id"></div>
<form class="intro-form" action="notifications/$intro_id" method="post">
<input class="intro-submit-ignore" type="submit" name="submit" value="Ignore" />
<input class="intro-submit-discard" type="submit" name="submit" value="Discard" />
@ -14,23 +14,11 @@
<div class="intro-form-end"></div>
<form class="intro-approve-form" action="dfrn_confirm" method="post">
<input type="hidden" name="dfrn_id" value="$dfrn-id" >
<input type="hidden" name="dfrn_id" value="$dfrn_id" >
<input type="hidden" name="intro_id" value="$intro_id" >
<input type="hidden" name="contact_id" value="$contact_id" >
<div class="intro-approve-as-friend-desc">Approve as: </div>
<div class="intro-approve-as-friend-wrapper">
<label class="intro-approve-as-friend-label" for="intro-approve-as-friend-$intro_id">Friend</label>
<input type="radio" name="duplex" id="intro-approve-as-friend-$intro_id" class="intro-approve-as-friend" checked="checked" value="1" />
<div class="intro-approve-friend-break" ></div>
</div>
<div class="intro-approve-as-friend-end"></div>
<div class="intro-approve-as-fan-wrapper">
<label class="intro-approve-as-fan-label" for="intro-approve-as-fan-$intro_id">Fan/Admirer</label>
<input type="radio" name="duplex" id="intro-approve-as-fan-$intro_id" class="intro-approve-as-fan" $fan_selected value="0" />
<div class="intro-approve-fan-break"></div>
</div>
<div class="intro-approve-as-end"></div>
$dfrn_text
<input class="intro-submit-approve" type="submit" name="submit" value="Approve" />
</form>

View file

@ -118,6 +118,12 @@ tinyMCE.init({
}
}
function jotClearLocation() {
$('#jot-coord').val('');
$('#profile-nolocation-wrapper').hide();
}
$geotag
</script>

View file

@ -11,6 +11,7 @@
<input type="hidden" name="profile_uid" value="$profile_uid" />
<input type="hidden" name="return" value="$return_path" />
<input type="hidden" name="location" id="jot-location" value="$defloc" />
<input type="hidden" name="coord" id="jot-coord" value="" />
<textarea rows="5" cols="64" class="profile-jot-text" id="profile-jot-text" name="body" ></textarea>
@ -26,7 +27,10 @@
<img id="profile-video" src="images/youtube_icon.gif" alt="Insert YouTube video" title="Insert YouTube video" onclick="jotGetVideo();" />
</div>
<div id="profile-location-wrapper" style="display: $visitor;" >
<img id="profile-location" src="images/globe.gif" alt="Set your location" title="Set your lcoation" onclick="jotGetLocation();" />
<img id="profile-location" src="images/globe.gif" alt="Set your location" title="Set your location" onclick="jotGetLocation();" />
</div>
<div id="profile-nolocation-wrapper" style="display: none;" >
<img id="profile-nolocation" src="images/noglobe.gif" alt="Clear Browser Location" title="Clear Browser Location" onclick="jotClearLocation();" />
</div>
<div id="profile-rotator-wrapper" style="display: $visitor;" >
<img id="profile-rotator" src="images/rotator.gif" alt="Please wait" title="Please wait" style="display: none;" />

8
view/jot_geotag.tpl Normal file
View file

@ -0,0 +1,8 @@
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
$('#jot-coord').val(position.coords.latitude + position.coords.longitude);
$('#profile-nolocation-wrapper').show();
});
}

View file

@ -1,5 +1,5 @@
<div class="wall-item-like-buttons" id="wall-item-like-buttons-$id">
<img src="images/like.gif" alt="I like this" title="I like this [toggle]" onclick="dolike($id,'like');" />
<img src="images/dislike.gif" alt="I don't like this" title="I don't like this [toggle]" onclick="dolike($id,'dislike');" />
<img id="like-rotator-$id" class="like-rotator" src="images/rotator.gif" alt="Please wait" title="Please wait" style="display: none;" />
</div>
<img src="images/like.gif" alt="I like this" title="I like this [toggle]" onclick="dolike($id,'like');" />
<img src="images/dislike.gif" alt="I don't like this" title="I don't like this [toggle]" onclick="dolike($id,'dislike');" />
<img id="like-rotator-$id" class="like-rotator" src="images/rotator.gif" alt="Please wait" title="Please wait" style="display: none;" />
</div>

View file

@ -2,7 +2,7 @@
<form action="" method="post" >
<input type="hidden" name="auth-params" value="login" />
<div id="login-name-wrapper">
<label for="login-name" id="label-login-name">Email address: </label>
<label for="login-name" id="label-login-name">Nickname or Email: </label>
<input type="text" maxlength="60" name="login-name" id="login-name" value="" />
</div>
<div id="login-name-end" ></div>

View file

@ -6,7 +6,7 @@ Enter your email address and submit to have your password reset. Then check your
<form action="lostpass" method="post" >
<div id="login-name-wrapper">
<label for="login-name" id="label-login-name">Email address: </label>
<label for="login-name" id="label-login-name">Nickname or Email: </label>
<input type="text" maxlength="60" name="login-name" id="login-name" value="" />
</div>
<div id="login-extra-end"></div>

9
view/magicsig.tpl Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<me:env xmlns:me="http://salmon-protocol.org/ns/magic-env">
<me:data type="application/atom+xml">
$data
</me:data>
<me:encoding>$encoding</me:encoding>
<me:alg>$algorithm</me:alg>
<me:sig keyhash="$keyhash">$signature</me:sig>
</me:env>

14
view/netfriend.tpl Normal file
View file

@ -0,0 +1,14 @@
<div class="intro-approve-as-friend-desc">Approve as: </div>
<div class="intro-approve-as-friend-wrapper">
<label class="intro-approve-as-friend-label" for="intro-approve-as-friend-$intro_id">Friend</label>
<input type="radio" name="duplex" id="intro-approve-as-friend-$intro_id" class="intro-approve-as-friend" $friend_selected value="1" />
<div class="intro-approve-friend-break" ></div>
</div>
<div class="intro-approve-as-friend-end"></div>
<div class="intro-approve-as-fan-wrapper">
<label class="intro-approve-as-fan-label" for="intro-approve-as-fan-$intro_id">Fan/Admirer</label>
<input type="radio" name="duplex" id="intro-approve-as-fan-$intro_id" class="intro-approve-as-fan" $fan_selected value="0" />
<div class="intro-approve-fan-break"></div>
</div>
<div class="intro-approve-as-end"></div>

25
view/pagetypes.tpl Normal file
View file

@ -0,0 +1,25 @@
<div id="settings-normal-wrapper">
<label id="settings-normal-label" for="settings-normal">Normal Profile</label>
<input type="radio" name="page-flags" id="settings-normal" $normal_selected value="$page_normal" />
<span id="settings-normal-desc">This account is a normal personal profile</span>
</div>
<div id="settings-normal-break" ></div>
<div id="settings-soapbox-wrapper">
<label id="settings-soapbox-label" for="settings-soapbox">Soapbox Profile</label>
<input type="radio" name="page-flags" id="settings-soapbox" $soapbox_selected value="$page_soapbox" />
<span id="settings-soapbox-desc">Automatically approve all connection/friend requests as read-only fans</span>
</div>
<div id="settings-soapbox-break" ></div>
<div id="settings-community-wrapper">
<label id="settings-community-label" for="settings-community">Community/Celebrity Profile</label>
<input type="radio" name="page-flags" id="settings-community" $community_selected value="$page_community" />
<span id="settings-community-desc">Automatically approve all connection/friend requests as read-write fans</span>
</div>
<div id="settings-community-break" ></div>
<div id="settings-freelove-wrapper">
<label id="settings-freelove-label" for="settings-freelove">Automatic Friend Profile</label>
<input type="radio" name="page-flags" id="settings-freelove" $freelove_selected value="$page_freelove" />
<span id="settings-freelove-desc">Automatically approve all connection/friend requests as friends</span>
</div>
<div id="settings-freelove-break" ></div>

View file

@ -8,8 +8,8 @@
<div id="photo-edit-caption-end"></div>
<label id="photo-edit-tags-label" for="photo-edit-tags-textarea" >$tag_label</label>
<textarea name="tags" id="photo-edit-tags-textarea" rows="3" cols="64" >$tags</textarea>
<label id="photo-edit-tags-label" for="photo-edit-newtag" >$tag_label</label>
<input name="newtag" id="photo-edit-newtag" size="84" title="$help_tags" type="text" />
<div id="photo-edit-tags-end"></div>
<input id="photo-edit-submit-button" type="submit" name="submit" value="$submit" />

View file

@ -1,12 +1,12 @@
<!DOCTYPE html ><?php // This is a perfect example of why I prefer to use template files rather than mixed PHP/HTML ?>
<html>
<head>
<title><?php echo $page['title']; ?></title>
<?php echo $page['htmlhead']; ?>
<title><?php if(x($page,'title')) echo $page['title']; ?></title>
<?php if(x($page,'htmlhead')) echo $page['htmlhead']; ?>
</head>
<body>
<header><?php echo $page['header']; ?></header>
<nav><div id="top-margin"></div><?php echo $page['nav']; ?></nav>
<header><?php if(x($page,'header')) echo $page['header']; ?></header>
<nav><div id="top-margin"></div><?php if(x($page,'nav')) echo $page['nav']; ?></nav>
<aside>
<?php if((is_array($profile)) && count($profile)) { ?>
<div class="vcard">
@ -57,17 +57,17 @@
<?php if(strlen($profile['marital'])) { ?>
<div class="marital"><span class="marital-label"><span class="heart">&hearts;</span> Status: </span><span class="marital-text"><?php echo $profile['marital']; ?></span></div>
<?php } ?>
<?php if(strlen($profile['url'])) { ?>
<?php if(strlen($profile['homepage'])) { ?>
<div class="homepage"><span class="homepage-label">Homepage: </span><span class="homepage-url"><?php echo $profile['homepage']; ?></span></div>
<?php } ?>
<?php echo $page['aside'] ?>
<?php if(x($page,'aside')) echo $page['aside'] ?>
</aside>
<section>
<?php echo $page['content']; ?>
<?php if(x($page,'content')) echo $page['content']; ?>
<div id="page-footer"></div>
</section>
<footer>
<?php echo $page['footer']; ?>
<?php if(x($page,'footer')) echo $page['footer']; ?>
</footer>
</body>
</html>

View file

@ -2,6 +2,7 @@
function gender_selector($current="",$suffix="") {
$o = '';
$select = array('', t('Male'), t('Female'), t('Transsexual'), t('Hermaphrodite'), t('Neuter'), t('Other'), t('Undecided'));
$o .= "<select name=\"gender$suffix\" id=\"gender-select$suffix\" size=\"1\" >";
@ -14,6 +15,7 @@ function gender_selector($current="",$suffix="") {
}
function sexpref_selector($current="",$suffix="") {
$o = '';
$select = array('', t('Males'), t('Females'), t('Bisexual'), t('Autosexual'), t('Abstinent'), t('Virgin'), t('Nonsexual'));
$o .= "<select name=\"sexual$suffix\" id=\"sexual-select$suffix\" size=\"1\" >";
@ -27,6 +29,7 @@ function sexpref_selector($current="",$suffix="") {
function marital_selector($current="",$suffix="") {
$o = '';
$select = array('', t('Single'), t('Lonely'), t('Available'), t('Unavailable'), t('Dating'), t('Unfaithful'), t('Sex Addict'), t('Friends'), t('Friends/Benefits'), t('Casual'), t('Engaged'), t('Married'), t('Partners'), t('Cohabiting'), t('Happy'), t('Not Looking'), t('Swinger'), t('Betrayed'), t('Separated'), t('Unstable'), t('Divorced'), t('Widowed'), t('Uncertain'), t('Complicated'), t('Don\'t care'), t('Ask me') );
$o .= "<select name=\"marital\" id=\"marital-select\" size=\"1\" >";

View file

@ -5,8 +5,11 @@ $nickname_block
<form action="settings" id="settings-form" method="post" >
<h3 class="settings-heading">Basic Settings</h3>
<div id="settings-username-wrapper" >
<label id="settings-username-label" for="settings-username" >Username: </label>
<label id="settings-username-label" for="settings-username" >Full Name: </label>
<input type="text" name="username" id="settings-username" value="$username" />
</div>
<div id="settings-username-end" ></div>
@ -31,6 +34,14 @@ $zoneselect
</div>
<div id="settings-defloc-end" ></div>
<div id="settings-allowloc-wrapper" >
<label id="settings-allowloc-label" for="settings-allowloc" >Use Browser Location: </label>
<input type="checkbox" name="allow_location" id="settings-allowloc" value="1" $loc_checked />
</div>
<div id="settings-allowloc-end" ></div>
<div id="settings-theme-select">
<label id="settings-theme-label" for="theme-select" >Display Theme: </label>
@ -38,14 +49,22 @@ $theme
</div>
<div id="settings-theme-end"></div>
<div id="settings-submit-wrapper" >
<input type="submit" name="submit" id="settings-submit" value="Submit" />
</div>
<h3 class="settings-heading">Privacy Settings</h3>
<input type="hidden" name="visibility" value="$visibility" />
$profile_in_dir
$profile_in_net_dir
<div id="settings-default-perms" class="settings-default-perms fakelink" >
<div id="settings-default-perms-menu" onClick="openClose('settings-default-perms-select');" >$permissions</div>
<div id="settings-default-perms" class="settings-default-perms" >
<div id="settings-default-perms-menu" class="fakelink" onClick="openClose('settings-default-perms-select');" >$permissions</div>
<div id="settings-default-perms-menu-end"></div>
<div id="settings-default-perms-select" style="display: none;" >
@ -56,26 +75,43 @@ $profile_in_net_dir
</div>
<div id="settings-default-perms-end"></div>
<div id="settings-submit-wrapper" >
<input type="submit" name="submit" id="settings-submit" value="Submit" />
</div>
<h3 class="settings-heading">Notification Settings</h3>
<div id="settings-notify-wrapper">
<div id="settings-notify-desc">Send me a notification email when: </div>
<label for="notify1" id="settings-label-notify1">I receive an introduction</label>
<div id="settings-notify-desc">Send a notification email when: </div>
<label for="notify1" id="settings-label-notify1">You receive an introduction</label>
<input id="notify1" type="checkbox" $sel_notify1 name="notify1" value="1" />
<div id="notify1-end"></div>
<label for="notify2" id="settings-label-notify2">My introductions are confirmed</label>
<label for="notify2" id="settings-label-notify2">Your introductions are confirmed</label>
<input id="notify2" type="checkbox" $sel_notify2 name="notify2" value="2" />
<div id="notify2-end"></div>
<label for="notify3" id="settings-label-notify3">Someone writes on my profile wall</label>
<label for="notify3" id="settings-label-notify3">Someone writes on your profile wall</label>
<input id="notify3" type="checkbox" $sel_notify3 name="notify3" value="4" />
<div id="notify3-end"></div>
<label for="notify4" id="settings-label-notify4">Someone writes a followup comment</label>
<input id="notify4" type="checkbox" $sel_notify4 name="notify4" value="8" />
<div id="notify4-end"></div>
<label for="notify5" id="settings-label-notify5">I receive a private message</label>
<label for="notify5" id="settings-label-notify5">You receive a private message</label>
<input id="notify5" type="checkbox" $sel_notify5 name="notify5" value="16" />
<div id="notify5-end"></div>
</div>
<div id="settings=notify-end"></div>
<div id="settings-submit-wrapper" >
<input type="submit" name="submit" id="settings-submit" value="Submit" />
</div>
<h3 class="settings-heading">Password Settings</h3>
<div id="settings-password-wrapper" >
<p id="settings-password-desc" >
Leave password fields blank unless changing
@ -92,14 +128,20 @@ Leave password fields blank unless changing
<div id="settings-confirm-end" ></div>
<div id="settings-submit-wrapper" >
<input type="submit" name="submit" id="settings-submit" value="Submit" />
</div>
<h3 class="settings-heading">Advanced Page Settings</h3>
$pagetype
<div id="settings-submit-wrapper" >
<input type="submit" name="submit" id="settings-submit" value="Submit" />
</div>
</form>

30
view/tag_slap.tpl Normal file
View file

@ -0,0 +1,30 @@
<entry>
<author>
<name>$name</name>
<uri>$profile_page</uri>
<link rel="photo" type="image/jpeg" media:width="80" media:height="80" href="$thumb" />
<link rel="avatar" type="image/jpeg" media:width="80" media:height="80" href="$thumb" />
</author>
<id>$item_id</id>
<title>$title</title>
<published>$published</published>
<content type="$type" >$content</content>
<link rel="mentioned" href="$accturi" />
<as:actor>
<as:object-type>http://activitystrea.ms/schema/1.0/person</as:object-type>
<id>$profile_page</id>
<title></title>
<link rel="avatar" type="image/jpeg" media:width="175" media:height="175" href="$photo"/>
<link rel="avatar" type="image/jpeg" media:width="80" media:height="80" href="$thumb"/>
<poco:preferredUsername>$nick</poco:preferredUsername>
<poco:displayName>$name</poco:displayName>
</as:actor>
<as:verb>$verb</as:verb>
<as:object>
<as:object-type></as:object-type>
</as:object>
<as:target>
<as:object-type></as:object-type>
</as:target>
</entry>

View file

@ -32,9 +32,12 @@ input, select {
border: 1px solid #858585;
}
input:hover {
background-color: #29BBF2;
color: #F5F6FB;
border: 1px solid #F5F6FB;
/* background-color: #49dbFa; */
color: black;
/* color: #F5F6FB; */
/* border: 1px solid #F5F6FB; */
cursor: pointer;
}
option {
@ -79,7 +82,8 @@ blockquote:before {
}
#jot-perms-icon,
#profile-location,
#profile-location,
#profile-nolocation,
#profile-video,
#profile-link,
#wall-image-upload,
@ -105,7 +109,9 @@ blockquote:before {
text-decoration: none;
cursor: pointer;
}
.smalltext {
font-size: 0.7em;
}
#sysmsg {
width: 600px;
margin-bottom: 10px;
@ -439,6 +445,7 @@ input#dfrn-url {
#settings-email-end,
#settings-nick-end,
#settings-defloc-end,
#settings-allowloc-end,
#settings-timezone-end,
#settings-theme-end,
#settings-password-end,
@ -456,6 +463,7 @@ input#dfrn-url {
#settings-email-label,
#settings-nick-label,
#settings-defloc-label,
#settings-allowloc-label,
#settings-timezone-label,
#settings-theme-label,
#settings-password-label,
@ -473,6 +481,7 @@ input#dfrn-url {
#settings-email,
#settings-nick,
#settings-defloc,
#settings-allowloc,
#timezone-select,
#theme-select,
#settings-password,
@ -521,6 +530,10 @@ input#dfrn-url {
clear: both;
}
.intro-wrapper {
margin-top: 20px;
}
.intro-fullname {
font-size: 1.1em;
font-weight: bold;
@ -528,6 +541,7 @@ input#dfrn-url {
}
.intro-desc {
margin-bottom: 20px;
font-weight: bold;
}
.intro-note {
@ -550,6 +564,10 @@ input#dfrn-url {
.intro-submit-approve, .intro-submit-ignore {
margin-right: 20px;
}
.intro-submit-approve {
margin-top: 15px;
}
.intro-approve-as-friend-label, .intro-approve-as-fan-label {
float: left;
width: 100px;
@ -666,7 +684,11 @@ input#dfrn-url {
#profile-in-netdir-yes,
#profile-in-netdir-no,
#hide-friends-yes,
#hide-friends-no {
#hide-friends-no,
#settings-normal,
#settings-soapbox,
#settings-community,
#settings-freelove {
float: left;
margin-bottom: 20px;
}
@ -686,6 +708,20 @@ input#dfrn-url {
float: left;
margin-bottom: 35px;
}
#settings-normal-label,
#settings-soapbox-label,
#settings-community-label,
#settings-freelove-label {
float: left;
width: 200px;
}
#settings-normal-desc,
#settings-soapbox-desc,
#settings-community-desc,
#settings-freelove-desc {
float: left;
margin-left: 75px;
}
#profile-edit-profile-name-end,
#profile-edit-name-end,
@ -706,7 +742,11 @@ input#dfrn-url {
#profile-in-netdir-break,
#profile-in-netdir-end,
#hide-friends-break,
#hide-friends-end {
#hide-friends-end,
#settings-normal-break,
#settings-soapbox-break,
#settings-community-break,
#settings-freelove-break {
clear: both;
}
@ -916,6 +956,10 @@ input#dfrn-url {
float: left;
margin-left: 20px;
}
#profile-nolocation-wrapper {
float: left;
margin-left: 20px;
}
#profile-jot-perms {
float: left;
@ -1244,9 +1288,8 @@ input#dfrn-url {
margin-left: 50px;
}
#block-message, #ignore-message {
#block-message, #ignore-message, #profile-edit-insecure {
margin-top: 20px;
width: 180px;
color: #FF0000;
font-size: 1.1em;
border: 1px solid #FF8888;
@ -1254,6 +1297,14 @@ input#dfrn-url {
padding: 10px;
}
#block-message, #ignore-message {
width: 180px;
}
#profile-edit-insecure {
width: 600px;
}
.profile-tabs {
float: left;
padding: 4px;
@ -1509,6 +1560,16 @@ a.mail-list-link:hover {
margin-top: 10px;
}
#side-follow-wrapper {
margin-top: 20px;
}
#side-follow-url {
margin-top: 5px;
}
#side-follow-submit {
margin-top: 15px;
}
.photo-album-image-wrapper {
float: left;
margin-top: 15px;
@ -1619,9 +1680,9 @@ a.mail-list-link:hover {
float: left;
width: 150px;
}
#photo-edit-caption, #photo-edit-tags-textarea {
#photo-edit-caption, #photo-edit-newtag {
float: left;
margin-bottom: 15px;
margin-bottom: 25px;
}
#photo-edit-caption-end, #photo-edit-tags-end {
@ -1631,6 +1692,9 @@ a.mail-list-link:hover {
#photo-edit-delete-button {
margin-left: 200px;
}
#photo-edit-end {
margin-bottom: 35px;
}
#photo-caption {
font-size: 110%;
font-weight: bold;

View file

@ -1,2 +1,2 @@
<div class="wall-item-delete-wrapper" id="wall-item-delete-wrapper-$id" ><a href="item/drop/$id" onclick="return confirmDelete();" ><img src="images/b_drophide.gif" alt="Delete" title="Delete" id="wall-item-delete-icon-$id" class="wall-item-delete-icon" onmouseover="imgbright(this);" onmouseout="imgdull(this);" ></a></div>
<div class="wall-item-delete-end"></div>
<div class="wall-item-delete-end"></div>

View file

@ -17,6 +17,7 @@
type="text/html"
href="$profile_url" />
<Link rel="http://webfinger.net/rel/avatar"
type="image/jpeg"
href="$photo" />
<Link rel="salmon"
href="$salmon" />