aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/ItemObject.php1
-rw-r--r--include/account.php23
-rw-r--r--include/bb2diaspora.php11
-rw-r--r--include/chat.php11
-rw-r--r--include/conversation.php199
-rwxr-xr-xinclude/diaspora.php74
-rw-r--r--include/follow.php15
-rw-r--r--include/hubloc.php73
-rw-r--r--include/identity.php101
-rwxr-xr-xinclude/items.php63
-rw-r--r--include/js_strings.php1
-rw-r--r--include/menu.php10
-rw-r--r--include/nav.php15
-rw-r--r--include/network.php32
-rw-r--r--include/notifier.php37
-rw-r--r--include/onepoll.php2
-rw-r--r--include/permissions.php290
-rw-r--r--include/photos.php1
-rw-r--r--include/poller.php3
-rw-r--r--include/security.php13
-rw-r--r--include/widgets.php10
-rw-r--r--include/zot.php467
22 files changed, 1084 insertions, 368 deletions
diff --git a/include/ItemObject.php b/include/ItemObject.php
index 451e369b0..96abe4df6 100644
--- a/include/ItemObject.php
+++ b/include/ItemObject.php
@@ -250,6 +250,7 @@ class Item extends BaseObject {
'osparkle' => $osparkle,
'sparkle' => $sparkle,
'title' => $item['title'],
+ 'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
'ago' => relative_date($item['created']),
'app' => $item['app'],
'str_app' => sprintf( t(' from %s'), $item['app']),
diff --git a/include/account.php b/include/account.php
index a3d6ef025..df484e608 100644
--- a/include/account.php
+++ b/include/account.php
@@ -616,6 +616,29 @@ function service_class_fetch($uid,$property) {
return((array_key_exists($property,$arr)) ? $arr[$property] : false);
}
+// like service_class_fetch but queries by account rather than channel
+
+function account_service_class_fetch($aid,$property) {
+
+ $r = q("select account_service_class as service_class from account where account_id = %d limit 1",
+ intval($aid)
+ );
+ if($r !== false && count($r)) {
+ $service_class = $r[0]['service_class'];
+ }
+
+ if(! x($service_class))
+ return false; // everything is allowed
+
+ $arr = get_config('service_class',$service_class);
+
+ if(! is_array($arr) || (! count($arr)))
+ return false;
+
+ return((array_key_exists($property,$arr)) ? $arr[$property] : false);
+}
+
+
function upgrade_link($bbcode = false) {
$l = get_config('service_class','upgrade_link');
if(! $l)
diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php
index 9c884926a..e60f72add 100644
--- a/include/bb2diaspora.php
+++ b/include/bb2diaspora.php
@@ -266,11 +266,15 @@ function bb2dmention_callback($match) {
function bb2diaspora_itemwallwall(&$item) {
if(($item['mid'] == $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (is_array($item['author']))) {
+ logger('bb2diaspora_itemwallwall: author: ' . print_r($item['author'],true), LOGGER_DEBUG);
+ }
+
+ if(($item['mid'] == $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_m']) {
logger('bb2diaspora_itemwallwall: wall to wall post',LOGGER_DEBUG);
// post will come across with the owner's identity. Throw a preamble onto the post to indicate the true author.
$item['body'] = "\n\n"
- . '[img]' . $item['author']['photo']['src'] . '[/img]'
- . '[url=' . $item['author']['url'] . ']' . $item['author']['name'] . '[/url]' . "\n\n"
+ . '[img]' . $item['author']['xchan_photo_m'] . '[/img]'
+ . '[url=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/url]' . "\n\n"
. $item['body'];
}
}
@@ -292,7 +296,8 @@ function bb2diaspora_itembody($item) {
logger('bb2diaspora_itembody: cached ');
$newitem = $item;
$newitem['body'] = $meta['body'];
- bb2diaspora_itemwallwall($newitem);
+// this won't work - the post is now in markdown
+// bb2diaspora_itemwallwall($newitem);
return $newitem['body'];
}
}
diff --git a/include/chat.php b/include/chat.php
index b8fb185df..5c3d0c9d9 100644
--- a/include/chat.php
+++ b/include/chat.php
@@ -189,6 +189,17 @@ function chatroom_list($uid) {
return $r;
}
+function chatroom_list_count($uid) {
+ require_once('include/security.php');
+ $sql_extra = permissions_sql($uid);
+
+ $r = q("select count(*) as total from chatroom where cr_uid = %d $sql_extra",
+ intval($uid)
+ );
+
+ return $r[0]['total'];
+}
+
/**
* create a chat message via API.
* It is the caller's responsibility to enter the room.
diff --git a/include/conversation.php b/include/conversation.php
index 05ae72d61..b0a388a68 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -440,7 +440,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
for($x = 0; $x < count($arr_blocked); $x ++)
$arr_blocked[$x] = trim($arr_blocked[$x]);
}
-
}
@@ -458,59 +457,53 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$profile_owner = local_user();
$page_writeable = true;
- if(!$update) {
- // The special div is needed for liveUpdate to kick in for this page.
- // We only launch liveUpdate if you aren't filtering in some incompatible
- // way and also you aren't writing a comment (discovered in javascript).
-
- $live_update_div = '<div id="live-network"></div>' . "\r\n"
- . "<script> var profile_uid = " . $_SESSION['uid']
- . "; var netargs = '" . substr($a->cmd,8)
- . '?f='
- . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '')
- . ((x($_GET,'search')) ? '&search=' . $_GET['search'] : '')
- . ((x($_GET,'star')) ? '&star=' . $_GET['star'] : '')
- . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : '')
- . ((x($_GET,'bmark')) ? '&bmark=' . $_GET['bmark'] : '')
- . ((x($_GET,'liked')) ? '&liked=' . $_GET['liked'] : '')
- . ((x($_GET,'conv')) ? '&conv=' . $_GET['conv'] : '')
- . ((x($_GET,'spam')) ? '&spam=' . $_GET['spam'] : '')
- . ((x($_GET,'nets')) ? '&nets=' . $_GET['nets'] : '')
- . ((x($_GET,'cmin')) ? '&cmin=' . $_GET['cmin'] : '')
- . ((x($_GET,'cmax')) ? '&cmax=' . $_GET['cmax'] : '')
- . ((x($_GET,'file')) ? '&file=' . $_GET['file'] : '')
- . ((x($_GET,'uri')) ? '&uri=' . $_GET['uri'] : '')
-
- . "'; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
- }
-
-
+ if(!$update) {
+ // The special div is needed for liveUpdate to kick in for this page.
+ // We only launch liveUpdate if you aren't filtering in some incompatible
+ // way and also you aren't writing a comment (discovered in javascript).
+
+ $live_update_div = '<div id="live-network"></div>' . "\r\n"
+ . "<script> var profile_uid = " . $_SESSION['uid']
+ . "; var netargs = '" . substr($a->cmd,8)
+ . '?f='
+ . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '')
+ . ((x($_GET,'search')) ? '&search=' . $_GET['search'] : '')
+ . ((x($_GET,'star')) ? '&star=' . $_GET['star'] : '')
+ . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : '')
+ . ((x($_GET,'bmark')) ? '&bmark=' . $_GET['bmark'] : '')
+ . ((x($_GET,'liked')) ? '&liked=' . $_GET['liked'] : '')
+ . ((x($_GET,'conv')) ? '&conv=' . $_GET['conv'] : '')
+ . ((x($_GET,'spam')) ? '&spam=' . $_GET['spam'] : '')
+ . ((x($_GET,'nets')) ? '&nets=' . $_GET['nets'] : '')
+ . ((x($_GET,'cmin')) ? '&cmin=' . $_GET['cmin'] : '')
+ . ((x($_GET,'cmax')) ? '&cmax=' . $_GET['cmax'] : '')
+ . ((x($_GET,'file')) ? '&file=' . $_GET['file'] : '')
+ . ((x($_GET,'uri')) ? '&uri=' . $_GET['uri'] : '')
+ . "'; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
+ }
}
elseif($mode === 'channel') {
$profile_owner = $a->profile['profile_uid'];
$page_writeable = ($profile_owner == local_user());
- if(!$update) {
- $tab = notags(trim($_GET['tab']));
- if($tab === 'posts') {
- // This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
- // because browser prefetching might change it on us. We have to deliver it with the page.
-
- $live_update_div = '<div id="live-channel"></div>' . "\r\n"
- . "<script> var profile_uid = " . $a->profile['profile_uid']
- . "; var netargs = '?f='; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
- }
- }
+ if(!$update) {
+ $tab = notags(trim($_GET['tab']));
+ if($tab === 'posts') {
+ // This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
+ // because browser prefetching might change it on us. We have to deliver it with the page.
+ $live_update_div = '<div id="live-channel"></div>' . "\r\n"
+ . "<script> var profile_uid = " . $a->profile['profile_uid']
+ . "; var netargs = '?f='; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
+ }
+ }
}
elseif($mode === 'display') {
$profile_owner = local_user();
$page_writeable = false;
-
- $live_update_div = '<div id="live-display"></div>' . "\r\n";
-
+ $live_update_div = '<div id="live-display"></div>' . "\r\n";
}
elseif($mode === 'page') {
@@ -519,10 +512,10 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$live_update_div = '<div id="live-page"></div>' . "\r\n";
}
+ elseif($mode === 'search') {
+ $live_update_div = '<div id="live-search"></div>' . "\r\n";
+ }
- elseif($mode === 'search') {
- $live_update_div = '<div id="live-search"></div>' . "\r\n";
- }
elseif($mode === 'photos') {
$profile_onwer = $a->profile['profile_uid'];
$page_writeable = ($profile_owner == local_user());
@@ -555,7 +548,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$alike = array();
$dlike = array();
-
// array with html for each thread (parent+comments)
$threads = array();
$threadsid = -1;
@@ -603,12 +595,11 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
}
else
$nickname = $a->user['nickname'];
-
+
$profile_name = ((strlen($item['author-name'])) ? $item['author-name'] : $item['name']);
if($item['author-link'] && (! $item['author-name']))
$profile_name = $item['author-link'];
-
$tags=array();
$hashtags = array();
@@ -631,7 +622,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$profile_link = $item['author']['xchan_url'];
$profile_avatar = $item['author']['xchan_photo_m'];
-
$location = format_location($item);
localize_item($item);
@@ -663,7 +653,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$unverified = '';
-
$tags=array();
$terms = get_terms_oftype($item['term'],array(TERM_HASHTAG,TERM_MENTION,TERM_UNKNOWN));
if(count($terms))
@@ -694,12 +683,11 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
'verified' => $verified,
'unverified' => $unverified,
'txt_cats' => t('Categories:'),
- 'txt_folders' => t('Filed under:'),
- 'has_cats' => ((count($categories)) ? 'true' : ''),
- 'has_folders' => ((count($folders)) ? 'true' : ''),
- 'categories' => $categories,
- 'folders' => $folders,
-
+ 'txt_folders' => t('Filed under:'),
+ 'has_cats' => ((count($categories)) ? 'true' : ''),
+ 'has_folders' => ((count($folders)) ? 'true' : ''),
+ 'categories' => $categories,
+ 'folders' => $folders,
'text' => strip_tags($body),
'ago' => relative_date($item['created']),
'app' => $item['app'],
@@ -743,10 +731,10 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
// Normal View
// logger('conv: items: ' . print_r($items,true));
- require_once('include/ConversationObject.php');
- require_once('include/ItemObject.php');
+ require_once('include/ConversationObject.php');
+ require_once('include/ItemObject.php');
- $conv = new Conversation($mode, $preview, $prepared_item);
+ $conv = new Conversation($mode, $preview, $prepared_item);
// In the display mode we don't have a profile owner.
@@ -754,12 +742,12 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$conv->set_profile_owner($items[0]['uid']);
- // get all the topmost parents
- // this shouldn't be needed, as we should have only them in our array
- // But for now, this array respects the old style, just in case
+ // get all the topmost parents
+ // this shouldn't be needed, as we should have only them in our array
+ // But for now, this array respects the old style, just in case
- $threads = array();
- foreach($items as $item) {
+ $threads = array();
+ foreach($items as $item) {
// Check for any blocked authors
@@ -774,7 +762,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
if($blocked)
continue;
}
-
+
// Check all the kids too
if($arr_blocked && $item['children']) {
@@ -786,46 +774,43 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
}
}
+ like_puller($a, $item, $alike, 'like');
+ if(feature_enabled($profile_owner, 'dislike'))
+ like_puller($a, $item, $dlike, 'dislike');
- like_puller($a,$item,$alike,'like');
-
- if(feature_enabled($profile_owner,'dislike'))
- like_puller($a,$item,$dlike,'dislike');
-
- if(! visible_activity($item)) {
- continue;
- }
+ if(! visible_activity($item)) {
+ continue;
+ }
- $item['pagedrop'] = $page_dropping;
+ $item['pagedrop'] = $page_dropping;
- if($item['id'] == $item['parent']) {
+ if($item['id'] == $item['parent']) {
// $tx1 = dba_timer();
- $item_object = new Item($item);
- $conv->add_thread($item_object);
+ $item_object = new Item($item);
+ $conv->add_thread($item_object);
if($page_mode === 'list')
$item_object->set_template('conv_list.tpl');
// $tx2 = dba_timer();
// if($mode === 'network')
// profiler($tx1,$tx2,'add thread ' . $item['id']);
- }
- }
+ }
+ }
$t2 = dba_timer();
- $threads = $conv->get_template_data($alike, $dlike);
- if(!$threads) {
- logger('[ERROR] conversation : Failed to get template data.', LOGGER_DEBUG);
- $threads = array();
- }
+ $threads = $conv->get_template_data($alike, $dlike);
+ if(!$threads) {
+ logger('[ERROR] conversation : Failed to get template data.', LOGGER_DEBUG);
+ $threads = array();
+ }
$t3 = dba_timer();
if($mode === 'network') {
profiler($t1,$t2,'Conversation prepare');
profiler($t2,$t3,'Conversation get_template');
}
-
- }
- }
+ }
+ }
if($page_mode === 'traditional' || $page_mode === 'preview') {
$page_template = get_markup_template("threaded_conversation.tpl");
@@ -867,8 +852,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
if($page_mode === 'preview')
logger('preview: ' . $o);
- return $o;
-
+ return $o;
}
@@ -981,26 +965,43 @@ function item_photo_menu($item){
return $o;
}
-
-function like_puller($a,$item,&$arr,$mode) {
+/**
+ * @brief Returns a like/dislike entry.
+ * It gives back a HTML link to the channel that liked/disliked.
+ *
+ * @param array $a (not used)
+ * @param array $item
+ * @param array &$arr
+ * @param string $mode like/dislike
+ * @return void
+ */
+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 = chanlink_url($item['author']['xchan_url']);
+ if((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) {
+
+ if($item['author']['xchan_url'])
+ $url = chanlink_url($item['author']['xchan_url']);
if(! $item['thr_parent'])
$item['thr_parent'] = $item['parent_mid'];
if(! ((isset($arr[$item['thr_parent'] . '-l'])) && (is_array($arr[$item['thr_parent'] . '-l']))))
$arr[$item['thr_parent'] . '-l'] = array();
+
if(! isset($arr[$item['thr_parent']]))
$arr[$item['thr_parent']] = 1;
else
$arr[$item['thr_parent']] ++;
- $arr[$item['thr_parent'] . '-l'][] = '<a href="'. $url . '">' . $item['author']['xchan_name'] . '</a>';
+
+ $name = (($item['author']['xchan_name']) ? $item['author']['xchan_name'] : t('Unknown'));
+
+ if($url)
+ $arr[$item['thr_parent'] . '-l'][] = '<a href="'. $url . '">' . $name . '</a>';
+ else
+ $arr[$item['thr_parent'] . '-l'][] = '<a href="#" class="disabled">' . $name . '</a>';
}
return;
}
@@ -1545,8 +1546,8 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
}
require_once('include/chat.php');
- $chats = chatroom_list($uid);
- if (count($chats)) {
+ $has_chats = chatroom_list_count($uid);
+ if ($has_chats) {
$tabs[] = array(
'label' => t('Chatrooms'),
'url' => $a->get_baseurl() . '/chat/' . $nickname,
@@ -1556,7 +1557,9 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
);
}
- if($is_owner) {
+ require_once('include/menu.php');
+ $has_bookmarks = menu_list_count(local_user(),'',MENU_BOOKMARK) + menu_list_count(local_user(),'',MENU_SYSTEM|MENU_BOOKMARK);
+ if($is_owner && $has_bookmarks) {
$tabs[] = array(
'label' => t('Bookmarks'),
'url' => $a->get_baseurl() . '/bookmarks',
diff --git a/include/diaspora.php b/include/diaspora.php
index 8a3eaf873..6f504b460 100755
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -58,7 +58,7 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
$xmlbase = $parsed_xml->post;
- logger('diaspora_dispatch: ' . print_r($xmlbase,true), LOGGER_DEBUG);
+ logger('diaspora_dispatch: ' . print_r($xmlbase,true), LOGGER_DATA);
if($xmlbase->request) {
@@ -142,6 +142,7 @@ function diaspora_process_outbound($arr) {
'cmd' => $cmd,
'expire' => $expire,
'mail' => $mail,
+ 'location' => $location,
'fsuggest' => $fsuggest,
'normal_mode' => $normal_mode,
'packet_type' => $packet_type,
@@ -150,6 +151,10 @@ function diaspora_process_outbound($arr) {
*/
+ if($arr['location'])
+ return;
+
+
$target_item = $arr['target_item'];
if($target_item && array_key_exists('item_flags',$target_item) && ($target_item['item_flags'] & ITEM_OBSCURED)) {
@@ -161,6 +166,7 @@ function diaspora_process_outbound($arr) {
}
+
if($arr['env_recips']) {
$hashes = array();
@@ -539,7 +545,7 @@ function diaspora_decode($importer,$xml) {
* </decrypted_header>
*/
- logger('decrypted: ' . $decrypted, LOGGER_DEBUG);
+ logger('decrypted: ' . $decrypted, LOGGER_DATA);
$idom = parse_xml_string($decrypted,false);
$inner_iv = base64_decode($idom->iv);
@@ -906,7 +912,7 @@ function diaspora_post($importer,$xml,$msg) {
function diaspora_reshare($importer,$xml,$msg) {
- logger('diaspora_reshare: init: ' . print_r($xml,true));
+ logger('diaspora_reshare: init: ' . print_r($xml,true), LOGGER_DATA);
$a = get_app();
$guid = notags(unxmlify($xml->guid));
@@ -949,7 +955,7 @@ function diaspora_reshare($importer,$xml,$msg) {
logger('diaspora_reshare: unable to fetch source url ' . $source_url);
return;
}
- logger('diaspora_reshare: source: ' . $x['body']);
+ logger('diaspora_reshare: source: ' . $x['body'], LOGGER_DATA);
$source_xml = parse_xml_string($x['body'],false);
@@ -1425,7 +1431,8 @@ function diaspora_conversation($importer,$xml,$msg) {
return;
}
- if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
+
+ if(! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_mail')) {
logger('diaspora_conversation: Ignoring this author.');
return 202;
}
@@ -1525,7 +1532,7 @@ function diaspora_conversation($importer,$xml,$msg) {
continue;
}
- q("insert into mail ( `uid`, `convid`, `from_xchan`,`to_xchan`,`title`,`body`,`mail_flags`,`mid`,`parent_mid`,`created`) values ( %d, %d, '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s')",
+ q("insert into mail ( `channel_id`, `convid`, `from_xchan`,`to_xchan`,`title`,`body`,`mail_flags`,`mid`,`parent_mid`,`created`) values ( %d, %d, '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s')",
intval($importer['channel_id']),
intval($conversation['id']),
dbesc($person['xchan_hash']),
@@ -1639,19 +1646,15 @@ function diaspora_message($importer,$xml,$msg) {
return;
}
- q("insert into mail ( `uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) values ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
+ q("insert into mail ( `channel_id`, `convid`, `from_xchan`,`to_xchan`,`title`,`body`,`mail_flags`,`mid`,`parent_mid`,`created`) values ( %d, %d, '%s', '%s', '%s', '%s', '%d','%s','%s','%s')",
intval($importer['channel_id']),
- dbesc($msg_guid),
intval($conversation['id']),
- dbesc($person['name']),
- dbesc($person['photo']),
- dbesc($person['url']),
- intval($contact['id']),
+ dbesc($person['xchan_hash']),
+ dbesc($importer['xchan_hash']),
dbesc($conversation['subject']),
dbesc($body),
0,
- 1,
- dbesc($message_id),
+ dbesc($msg_guid),
dbesc($parent_uri),
dbesc($msg_created_at)
);
@@ -1966,19 +1969,16 @@ function diaspora_retraction($importer,$xml) {
if($type === 'Person') {
require_once('include/Contact.php');
- contact_remove($contact['id']);
+ contact_remove($importer['channel_id'],$contact['abook_id']);
}
elseif($type === 'Post') {
- $r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1",
+ $r = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc('guid'),
intval($importer['channel_id'])
);
if(count($r)) {
- if(link_compare($r[0]['author-link'],$contact['url'])) {
- q("update item set `deleted` = 1, `changed` = '%s' where `id` = %d",
- dbesc(datetime_convert()),
- intval($r[0]['id'])
- );
+ if(link_compare($r[0]['author_xchan'],$contact['xchan_hash'])) {
+ drop_item($r[0]['id'],false);
}
}
}
@@ -2040,35 +2040,33 @@ function diaspora_signed_retraction($importer,$xml,$msg) {
}
if($type === 'StatusMessage' || $type === 'Comment' || $type === 'Like') {
- $r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1",
+ $r = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($guid),
intval($importer['channel_id'])
);
- if(count($r)) {
- if(link_compare($r[0]['author-link'],$contact['url'])) {
- q("update item set `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = '' where `id` = %d",
- dbesc(datetime_convert()),
- dbesc(datetime_convert()),
- intval($r[0]['id'])
- );
+ if($r) {
+ if($r[0]['author_xchan'] == $contact['xchan_hash']) {
+
+ drop_item($r[0]['id'],false, DROPITEM_PHASE1);
// Now check if the retraction needs to be relayed by us
//
// The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always
// return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent.
// The only item with `parent` and `id` as the parent id is the parent item.
- $p = q("select origin from item where parent = %d and id = %d limit 1",
+ $p = q("select item_flags from item where parent = %d and id = %d limit 1",
$r[0]['parent'],
$r[0]['parent']
);
- if(count($p)) {
- if(($p[0]['origin']) && (! $parent_author_signature)) {
- q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
- $r[0]['id'],
- dbesc($signed_data),
- dbesc($sig),
- dbesc($diaspora_handle)
- );
+ if($p) {
+ if(($p[0]['item_flags'] & ITEM_ORIGIN) && (! $parent_author_signature)) {
+// FIXME so we can relay this
+// q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
+// $r[0]['id'],
+// dbesc($signed_data),
+// dbesc($sig),
+// dbesc($diaspora_handle)
+// );
// the existence of parent_author_signature would have meant the parent_author or owner
// is already relaying.
diff --git a/include/follow.php b/include/follow.php
index 18a9e66ea..38525982e 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -63,6 +63,13 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
$my_perms = PERMS_W_STREAM|PERMS_W_MAIL;
+ $role = get_pconfig($uid,'system','permissions_role');
+ if($role) {
+ $x = get_role_perms($role);
+ if($x['perms_follow'])
+ $my_perms = $x['perms_follow'];
+ }
+
logger('follow: ' . $url . ' ' . print_r($j,true), LOGGER_DEBUG);
@@ -136,7 +143,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
if(! $r) {
// attempt network auto-discovery
- if(strpos($url,'@')) {
+ if(strpos($url,'@') && (! $is_http)) {
$r = discover_by_webbie($url);
}
elseif($is_http) {
@@ -153,6 +160,12 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
$xchan_hash = $r[0]['xchan_hash'];
$their_perms = 0;
$my_perms = PERMS_W_STREAM|PERMS_W_MAIL;
+ $role = get_pconfig($uid,'system','permissions_role');
+ if($role) {
+ $x = get_role_perms($role);
+ if($x['perms_follow'])
+ $my_perms = $x['perms_follow'];
+ }
}
}
diff --git a/include/hubloc.php b/include/hubloc.php
index 566875ce9..cdc9de4af 100644
--- a/include/hubloc.php
+++ b/include/hubloc.php
@@ -42,4 +42,75 @@ function prune_hub_reinstalls() {
}
}
}
-} \ No newline at end of file
+}
+
+function remove_obsolete_hublocs() {
+
+ logger('remove_obsolete_hublocs',LOGGER_DEBUG);
+
+ // Get rid of any hublocs which are ours but aren't valid anymore -
+ // e.g. they point to a different and perhaps transient URL that we aren't using.
+
+ // I need to stress that this shouldn't happen. fix_system_urls() fixes hublocs
+ // when it discovers the URL has changed. So it's unclear how we could end up
+ // with URLs pointing to the old site name. But it happens. This may be an artifact
+ // of an old bug or maybe a regression in some newer code. In any event, they
+ // mess up communications and we have to take action if we find any.
+
+ // First make sure we have any hublocs (at all) with this URL and sitekey.
+ // We don't want to perform this operation while somebody is in the process
+ // of renaming their hub or installing certs.
+
+ $r = q("select hubloc_id from hubloc where hubloc_url = '%s' and hubloc_sitekey = '%s'",
+ dbesc(z_root()),
+ dbesc(get_config('system','pubkey'))
+ );
+ if((! $r) || (! count($r)))
+ return;
+
+ $channels = array();
+
+ // Good. We have at least one *valid* hubloc.
+
+ // Do we have any invalid ones?
+
+ $r = q("select hubloc_id from hubloc where hubloc_sitekey = '%s' and hubloc_url != '%s'",
+ dbesc(get_config('system','pubkey')),
+ dbesc(z_root())
+ );
+ $p = q("select hubloc_id from hubloc where hubloc_sitekey != '%s' and hubloc_url = '%s'",
+ dbesc(get_config('system','pubkey')),
+ dbesc(z_root())
+ );
+ if(is_array($r) && is_array($p))
+ $r = array_merge($r,$p);
+
+ if(! $r)
+ return;
+
+ // We've got invalid hublocs. Get rid of them.
+
+ logger('remove_obsolete_hublocs: removing ' . count($r) . ' hublocs.');
+
+ $interval = ((get_config('system','delivery_interval') !== false)
+ ? intval(get_config('system','delivery_interval')) : 2 );
+
+ foreach($r as $rr) {
+ q("update hubloc set hubloc_flags = (hubloc_flags | %d) where hubloc_id = %d limit 1",
+ intval(HUBLOC_FLAGS_DELETED),
+ intval($rr['hubloc_id'])
+ );
+
+ $x = q("select channel_id from channel where channel_hash = '%s' limit 1",
+ dbesc($rr['hubloc_hash'])
+ );
+ if($x) {
+// proc_run('php','include/notifier.php','location',$x[0]['channel_id']);
+// if($interval)
+// @time_sleep_until(microtime(true) + (float) $interval);
+ }
+ }
+}
+
+
+ \ No newline at end of file
diff --git a/include/identity.php b/include/identity.php
index d8f59e56c..50c5d13b9 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -215,18 +215,38 @@ function create_identity($arr) {
if(array_key_exists('primary', $arr))
$primary = intval($arr['primary']);
+
$perms_sql = '';
- $defperms = site_default_perms();
+ $role_permissions = null;
$global_perms = get_perms();
- foreach($defperms as $p => $v) {
- $perms_keys .= ', ' . $global_perms[$p][0];
- $perms_vals .= ', ' . intval($v);
+
+ if(array_key_exists('permissions_role',$arr) && $arr['permissions_role']) {
+ $role_permissions = get_role_perms($arr['permissions_role']);
+
+ if($role_permissions) {
+ foreach($role_permissions as $p => $v) {
+ if(strpos($p,'channel_') !== false) {
+ $perms_keys .= ', ' . $p;
+ $perms_vals .= ', ' . intval($v);
+ }
+ if($p === 'directory_publish')
+ $publish = intval($v);
+ }
+ }
}
+ else {
+ $defperms = site_default_perms();
+ foreach($defperms as $p => $v) {
+ $perms_keys .= ', ' . $global_perms[$p][0];
+ $perms_vals .= ', ' . intval($v);
+ }
+ }
+
$expire = get_config('system', 'default_expire_days');
$expire = (($expire===false)? '0': $expire);
-
+
$r = q("insert into channel ( channel_account_id, channel_primary,
channel_name, channel_address, channel_guid, channel_guid_sig,
channel_hash, channel_prvkey, channel_pubkey, channel_pageflags, channel_expire_days $perms_keys )
@@ -246,8 +266,6 @@ function create_identity($arr) {
);
-
-
$r = q("select * from channel where channel_account_id = %d
and channel_guid = '%s' limit 1",
intval($arr['account_id']),
@@ -322,24 +340,55 @@ function create_identity($arr) {
dbesc($a->get_baseurl() . "/photo/profile/m/{$newuid}")
);
- $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_flags )
- values ( %d, %d, '%s', %d, '%s', '%s', %d ) ",
+ $myperms = 0;
+ if($role_permissions) {
+ $myperms = ((array_key_exists('perms_auto',$role_permissions) && $role_permissions['perms_auto']) ? intval($role_permissions['perms_accept']) : 0);
+ }
+
+ $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_flags, abook_my_perms )
+ values ( %d, %d, '%s', %d, '%s', '%s', %d, %d ) ",
intval($ret['channel']['channel_account_id']),
intval($newuid),
dbesc($hash),
intval(0),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
- intval(ABOOK_FLAG_SELF)
+ intval(ABOOK_FLAG_SELF),
+ intval($myperms)
);
if(intval($ret['channel']['channel_account_id'])) {
- // Create a group with no members. This allows somebody to use it
+ // Save our permissions role so we can perhaps call it up and modify it later.
+
+ if($role_permissions) {
+ set_pconfig($newuid,'system','permissions_role',$arr['permissions_role']);
+ if(array_key_exists('online',$role_permissions))
+ set_pconfig('system','hide_presence',1-intval($role_permissions['online']));
+ }
+
+ // Create a group with yourself as a member. This allows somebody to use it
// right away as a default group for new contacts.
require_once('include/group.php');
group_add($newuid, t('Friends'));
+ group_add_member($newuid,t('Friends'),$ret['channel']['channel_hash']);
+
+ // if our role_permissions indicate that we're using a default collection ACL, add it.
+
+ if(is_array($role_permissions) && $role_permissions['default_collection']) {
+ $r = q("select hash from groups where uid = %d and name = '%s' limit 1",
+ intval($newuid),
+ dbesc( t('Friends') )
+ );
+ if($r) {
+ q("update channel set channel_allow_gid = '%s' where channel_id = %d limit 1",
+ dbesc('<' . $r[0]['hash'] . '>'),
+ intval($newuid)
+ );
+ }
+ }
+
call_hooks('register_account', $newuid);
@@ -396,7 +445,7 @@ function set_default_login_identity($account_id,$channel_id,$force = true) {
*
*/
-function identity_basic_export($channel_id) {
+function identity_basic_export($channel_id, $items = false) {
/*
* Red basic channel export
@@ -468,8 +517,36 @@ function identity_basic_export($channel_id) {
$ret['photo'] = array('type' => $r[0]['type'], 'data' => base64url_encode($r[0]['data']));
}
+ if(! $items)
+ return $ret;
+
+
+ $r = q("select * from item_id where uid = %d",
+ intval($channel_id)
+ );
+
+ if($r)
+ $ret['item_id'] = $r;
+
+ $key = get_config('system','prvkey');
+
+ // warning: this may run into memory limits on smaller systems
+
+ $r = q("select * from item where (item_flags & %d) and not (item_restrict & %d) and uid = %d",
+ intval(ITEM_WALL),
+ intval(ITEM_DELETED),
+ intval($channel_id)
+ );
+ if($r) {
+ $ret['item'] = array();
+ xchan_query($r);
+ $r = fetch_post_tags($r,true);
+ foreach($r as $rr)
+ $ret['item'][] = encode_item($rr,true);
+ }
return $ret;
+
}
diff --git a/include/items.php b/include/items.php
index 166303cac..53a0b25a9 100755
--- a/include/items.php
+++ b/include/items.php
@@ -68,13 +68,31 @@ function collect_recipients($item,&$private_envelope) {
$private_envelope = false;
if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') {
- $r = q("select abook_xchan from abook where abook_channel = %d and not (abook_flags & %d) ",
+ $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and not (abook_flags & %d) ",
intval($item['uid']),
intval(ABOOK_FLAG_SELF|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED)
);
if($r) {
+
+ // filter out restrictive public_policy settings from remote networks
+ // which don't have this concept and will treat them as public.
+
+ $policy = substr($item['public_policy'],0,3);
foreach($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
+ switch($policy) {
+ case 'net':
+ case 'aut':
+ case 'sit':
+ case 'any':
+ case 'con':
+ if($rr['xchan_network'] != 'zot')
+ break;
+ case 'pub':
+ case '':
+ default:
+ $recipients[] = $rr['abook_xchan'];
+ break;
+ }
}
}
}
@@ -989,8 +1007,7 @@ function import_author_unknown($x) {
}
-
-function encode_item($item) {
+function encode_item($item,$mirror = false) {
$x = array();
$x['type'] = 'activity';
$x['encoding'] = 'zot';
@@ -1012,14 +1029,37 @@ function encode_item($item) {
$c_scope = map_scope($comment_scope);
+ $key = get_config('system','prvkey');
+
if(array_key_exists('item_flags',$item) && ($item['item_flags'] & ITEM_OBSCURED)) {
- $key = get_config('system','prvkey');
if($item['title'])
$item['title'] = crypto_unencapsulate(json_decode_plus($item['title']),$key);
if($item['body'])
$item['body'] = crypto_unencapsulate(json_decode_plus($item['body']),$key);
}
+ // If we're trying to backup an item so that it's recoverable or for export/imprt,
+ // add all the attributes we need to recover it
+
+ if($mirror) {
+ $x['id'] = $item['id'];
+ $x['parent'] = $item['parent'];
+ $x['uid'] = $item['uid'];
+ $x['allow_cid'] = $item['allow_cid'];
+ $x['allow_gid'] = $item['allow_gid'];
+ $x['deny_cid'] = $item['deny_cid'];
+ $x['deny_gid'] = $item['deny_gid'];
+ $x['revision'] = $item['revision'];
+ $x['layout_mid'] = $item['layout_mid'];
+ $x['postopts'] = $item['postopts'];
+ $x['resource_id'] = $item['resource_id'];
+ $x['resource_type'] = $item['resource_type'];
+ $x['item_restrict'] = $item['item_restrict'];
+ $x['item_flags'] = $item['item_flags'];
+ $x['diaspora_meta'] = crypto_unencapsulate(json_decode($item['diaspora_meta'],true),$key);
+ $x['attach'] = $item['attach'];
+ }
+
$x['message_id'] = $item['mid'];
$x['message_top'] = $item['parent_mid'];
@@ -1751,6 +1791,7 @@ function get_atom_elements($feed,$item,&$author) {
call_hooks('parse_atom', $arr);
logger('get_atom_elements: author: ' . print_r($author,true),LOGGER_DATA);
+
logger('get_atom_elements: ' . print_r($res,true),LOGGER_DATA);
return $res;
@@ -2429,18 +2470,10 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id)
return;
}
- $body = $datarray['body'];
- if(array_key_exists('item_flags',$datarray) && ($datarray['item_flags'] & ITEM_OBSCURED)) {
- $key = get_config('system','prvkey');
- if($datarray['body'])
- $body = crypto_unencapsulate(json_decode($datarray['body'],true),$key);
- }
-
- logger('mod_item: storing diaspora comment signature',LOGGER_DEBUG);
-
require_once('include/bb2diaspora.php');
+ $signed_body = bb2diaspora_itembody($datarray);
- $signed_body = html_entity_decode(bb2diaspora($body));
+ logger('mod_item: storing diaspora comment signature',LOGGER_DEBUG);
$diaspora_handle = $channel['channel_address'] . '@' . get_app()->get_hostname();
diff --git a/include/js_strings.php b/include/js_strings.php
index cda66a09c..f4c0a631d 100644
--- a/include/js_strings.php
+++ b/include/js_strings.php
@@ -15,6 +15,7 @@ function js_strings() {
'$passhint' => t('Passphrase hint'),
'$permschange' => t('Notice: Permissions have changed but have not yet been submitted.'),
'$closeAll' => t('close all'),
+ '$nothingnew' => t('Nothing new here'),
'$t01' => ((t('timeago.prefixAgo') != 'timeago.prefixAgo') ? t('timeago.prefixAgo') : ''),
'$t02' => ((t('timeago.prefixFromNow') != 'timeago.prefixFromNow') ? t('timeago.prefixFromNow') : ''),
diff --git a/include/menu.php b/include/menu.php
index 4b0a11f10..8997d2e39 100644
--- a/include/menu.php
+++ b/include/menu.php
@@ -124,7 +124,17 @@ function menu_list($channel_id, $name = '', $flags = 0) {
return $r;
}
+function menu_list_count($channel_id, $name = '', $flags = 0) {
+ $sel_options = '';
+ $sel_options .= (($name) ? " and menu_name = '" . protect_sprintf(dbesc($name)) . "' " : '');
+ $sel_options .= (($flags) ? " and menu_flags = " . intval($flags) . " " : '');
+
+ $r = q("select count(*) as total from menu where menu_channel_id = %d $sel_options",
+ intval($channel_id)
+ );
+ return $r[0]['total'];
+}
function menu_edit($arr) {
diff --git a/include/nav.php b/include/nav.php
index 799faf5ce..98d1b644e 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -105,14 +105,19 @@ EOT;
$nav['usermenu'][] = Array('cloud/' . $channel['channel_address'],t('Files'),"",t('Your files'));
require_once('include/chat.php');
- $chats = chatroom_list(local_user());
- if (count($chats)) {
+ $has_chats = chatroom_list_count(local_user());
+ if($has_chats) {
$nav['usermenu'][] = Array('chat/' . $channel['channel_address'],t('Chat'),"",t('Your chatrooms'));
}
- $nav['usermenu'][] = Array('bookmarks', t('Bookmarks'), "", t('Your bookmarks'));
+ require_once('include/menu.php');
+ $has_bookmarks = menu_list_count(local_user(),'',MENU_BOOKMARK) + menu_list_count(local_user(),'',MENU_SYSTEM|MENU_BOOKMARK);
+ if($has_bookmarks) {
+ $nav['usermenu'][] = Array('bookmarks', t('Bookmarks'), "", t('Your bookmarks'));
+ }
+
if(feature_enabled($channel['channel_id'],'webpages'))
- $nav['usermenu'][] = Array('webpages/' . $channel['channel_address'],t('Webpages'),"",t('Your webpages'));
+ $nav['usermenu'][] = Array('webpages/' . $channel['channel_address'],t('Webpages'),"",t('Your webpages'));
}
else {
if(! get_account_id())
@@ -241,7 +246,7 @@ EOT;
'$sitelocation' => $sitelocation,
'$nav' => $x['nav'],
'$banner' => $banner,
- '$emptynotifications' => t('Nothing new here'),
+ '$emptynotifications' => t('Loading...'),
'$userinfo' => $x['usermenu'],
'$localuser' => local_user(),
'$sel' => $a->nav_sel,
diff --git a/include/network.php b/include/network.php
index 0191f203d..7286f0b12 100644
--- a/include/network.php
+++ b/include/network.php
@@ -38,6 +38,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
return false;
@curl_setopt($ch, CURLOPT_HEADER, true);
+ @curl_setopt($ch, CURLINFO_HEADER_OUT, true);
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
@curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
@@ -47,11 +48,8 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
if($ciphers)
@curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers);
- if (x($opts,'accept_content')){
- @curl_setopt($ch,CURLOPT_HTTPHEADER, array (
- "Accept: " . $opts['accept_content']
- ));
- }
+ if(x($opts,'headers'))
+ @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
@@ -126,6 +124,10 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
}
$ret['body'] = substr($s,strlen($header));
$ret['header'] = $header;
+
+ if(x($opts,'debug')) {
+ $ret['debug'] = $curl_info;
+ }
@curl_close($ch);
return($ret);
@@ -166,6 +168,7 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
return ret;
@curl_setopt($ch, CURLOPT_HEADER, true);
+ @curl_setopt($ch, CURLINFO_HEADER_OUT, true);
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
@curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
@curl_setopt($ch, CURLOPT_POST,1);
@@ -176,12 +179,6 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
if($ciphers)
@curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers);
-
- if (x($opts,'accept_content')){
- @curl_setopt($ch,CURLOPT_HTTPHEADER, array (
- "Accept: " . $opts['accept_content']
- ));
- }
if(x($opts,'headers'))
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
@@ -258,11 +255,24 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
$ret['body'] = substr($s,strlen($header));
$ret['header'] = $header;
+
+ if(x($opts,'debug')) {
+ $ret['debug'] = $curl_info;
+ }
+
+
curl_close($ch);
return($ret);
}
+function z_post_url_json($url,$params,$redirects = 0, $opts = array()) {
+
+ $opts = array_merge($opts,array('headers' => array('Content-Type: application/json')));
+ return z_post_url($url,json_encode($params),$redirects,$opts);
+
+}
+
function json_return_and_die($x) {
header("content-type: application/json");
diff --git a/include/notifier.php b/include/notifier.php
index 88bb9a0cb..0c7a15452 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -57,6 +57,7 @@ require_once('include/html2plain.php');
* purge_all channel_id
* expire channel_id
* relay item_id (item was relayed to owner, we will deliver it as owner)
+ * location channel_id
*
*/
@@ -144,6 +145,7 @@ function notifier_run($argv, $argc){
$mail = false;
$fsuggest = false;
$top_level = false;
+ $location = false;
$recipients = array();
$url_recipients = array();
$normal_mode = true;
@@ -230,6 +232,30 @@ function notifier_run($argv, $argc){
$private = false;
$packet_type = 'refresh';
}
+ elseif($cmd === 'location') {
+ logger('notifier: location: ' . $item_id);
+ $s = q("select * from channel where channel_id = %d limit 1",
+ intval($item_id)
+ );
+ if($s)
+ $channel = $s[0];
+ $uid = $item_id;
+ $recipients = array();
+ $r = q("select abook_xchan from abook where abook_channel = %d",
+ intval($item_id)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ $recipients[] = $rr['abook_xchan'];
+ }
+ }
+
+ $encoded_item = array('locations' => zot_encode_locations($channel),'type' => 'location', 'encoding' => 'zot');
+ $target_item = array('aid' => $channel['channel_account_id'],'uid' => $channel['channel_id']);
+ $private = false;
+ $packet_type = 'location';
+ $location = true;
+ }
elseif($cmd === 'purge_all') {
logger('notifier: purge_all: ' . $item_id);
$s = q("select * from channel where channel_id = %d limit 1",
@@ -429,8 +455,10 @@ function notifier_run($argv, $argc){
// for public posts always include our own hub
+// this shouldn't be needed any more. collect_recipients should take care of it.
+// $sql_extra = (($private) ? "" : " or hubloc_url = '" . dbesc(z_root()) . "' ");
- $sql_extra = (($private) ? "" : " or hubloc_url = '" . dbesc(z_root()) . "' ");
+ logger('notifier: hub choice: ' . intval($relay_to_owner) . ' ' . intval($private) . ' ' . $cmd, LOGGER_DEBUG);
if($relay_to_owner && (! $private) && ($cmd !== 'relay')) {
@@ -450,7 +478,10 @@ function notifier_run($argv, $argc){
}
else {
$r = q("select hubloc_guid, hubloc_url, hubloc_sitekey, hubloc_network, hubloc_flags, hubloc_callback, hubloc_host from hubloc
- where hubloc_hash in (" . implode(',',$recipients) . ") $sql_extra group by hubloc_sitekey");
+ where hubloc_hash in (" . implode(',',$recipients) . ") and not (hubloc_flags & %d) and not (hubloc_status & %d) group by hubloc_sitekey",
+ intval(HUBLOC_FLAGS_DELETED),
+ intval(HUBLOC_OFFLINE)
+ );
}
if(! $r) {
@@ -465,6 +496,7 @@ function notifier_run($argv, $argc){
foreach($hubs as $hub) {
// don't try to deliver to deleted hublocs - and inexplicably SQL "distinct" and "group by"
// both return records with duplicate keys in rare circumstances
+// FIXME this is probably redundant now.
if((! ($hub['hubloc_flags'] & HUBLOC_FLAGS_DELETED)) && (! in_array($hub['hubloc_sitekey'],$keys))) {
$hublist[] = $hub['hubloc_host'];
$keys[] = $hub['hubloc_sitekey'];
@@ -514,6 +546,7 @@ function notifier_run($argv, $argc){
'cmd' => $cmd,
'expire' => $expire,
'mail' => $mail,
+ 'location' => $location,
'fsuggest' => $fsuggest,
'normal_mode' => $normal_mode,
'packet_type' => $packet_type,
diff --git a/include/onepoll.php b/include/onepoll.php
index 1f28852e9..98d52db93 100644
--- a/include/onepoll.php
+++ b/include/onepoll.php
@@ -135,7 +135,7 @@ function onepoll_run($argv, $argc){
foreach($j['messages'] as $message) {
$results = process_delivery(array('hash' => $contact['xchan_hash']), get_item_elements($message),
array(array('hash' => $importer['xchan_hash'])), false);
- logger('onepoll: feed_update: process_delivery: ' . print_r($results,true));
+ logger('onepoll: feed_update: process_delivery: ' . print_r($results,true), LOGGER_DATA);
$total ++;
}
logger("onepoll: $total messages processed");
diff --git a/include/permissions.php b/include/permissions.php
index 8e4676f51..438b807d0 100644
--- a/include/permissions.php
+++ b/include/permissions.php
@@ -419,11 +419,12 @@ function site_default_perms() {
*
* Given a string for the channel role ('social','forum', etc)
* return an array of all permission fields pre-filled for this role.
- * This includes the channel permission scope indicators as well as
- * perms_auto: The permissions to apply automatically on receipt of a connection request
+ * This includes the channel permission scope indicators (anything beginning with 'channel_') as well as
+ * perms_auto: true or false to create auto-permissions for this channel
* perms_follow: The permissions to apply when initiating a connection request to another channel
* perms_accept: The permissions to apply when accepting a connection request from another channel (not automatic)
- *
+ * default_collection: true or false to make the default ACL include the channel's default collection
+ * directory_publish: true or false to publish this channel in the directory
* Any attributes may be extended (new roles defined) and modified (specific permissions altered) by plugins
*
*/
@@ -436,7 +437,10 @@ function get_role_perms($role) {
switch($role) {
case 'social':
- $ret['perms_auto'] = 0;
+ $ret['perms_auto'] = false;
+ $ret['default_collection'] = false;
+ $ret['directory_publish'] = true;
+ $ret['online'] = true;
$ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
|PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
|PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
@@ -462,6 +466,259 @@ function get_role_perms($role) {
$ret['channel_w_like'] = PERMS_NETWORK;
break;
+
+
+ case 'social_restricted':
+ $ret['perms_auto'] = false;
+ $ret['default_collection'] = true;
+ $ret['directory_publish'] = true;
+ $ret['online'] = true;
+ $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
+ $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
+ $ret['channel_r_stream'] = PERMS_PUBLIC;
+ $ret['channel_r_profile'] = PERMS_PUBLIC;
+ $ret['channel_r_photos'] = PERMS_PUBLIC;
+ $ret['channel_r_abook'] = PERMS_PUBLIC;
+ $ret['channel_w_stream'] = PERMS_CONTACTS;
+ $ret['channel_w_wall'] = PERMS_CONTACTS;
+ $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
+ $ret['channel_w_comment'] = PERMS_CONTACTS;
+ $ret['channel_w_mail'] = PERMS_CONTACTS;
+ $ret['channel_w_photos'] = 0;
+ $ret['channel_w_chat'] = PERMS_CONTACTS;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_r_pages'] = PERMS_PUBLIC;
+ $ret['channel_w_pages'] = 0;
+ $ret['channel_a_republish'] = PERMS_SPECIFIC;
+ $ret['channel_w_like'] = PERMS_CONTACTS;
+
+ break;
+
+
+ case 'social_private':
+ $ret['perms_auto'] = false;
+ $ret['default_collection'] = true;
+ $ret['directory_publish'] = false;
+ $ret['online'] = false;
+ $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
+ $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
+ $ret['channel_r_stream'] = PERMS_PUBLIC;
+ $ret['channel_r_profile'] = PERMS_PUBLIC;
+ $ret['channel_r_photos'] = PERMS_PUBLIC;
+ $ret['channel_r_abook'] = PERMS_CONTACTS;
+ $ret['channel_w_stream'] = PERMS_CONTACTS;
+ $ret['channel_w_wall'] = PERMS_CONTACTS;
+ $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
+ $ret['channel_w_comment'] = PERMS_CONTACTS;
+ $ret['channel_w_mail'] = PERMS_SPECIFIC;
+ $ret['channel_w_photos'] = 0;
+ $ret['channel_w_chat'] = PERMS_SPECIFIC;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_r_pages'] = PERMS_PUBLIC;
+ $ret['channel_w_pages'] = 0;
+ $ret['channel_a_republish'] = PERMS_SPECIFIC;
+ $ret['channel_w_like'] = PERMS_CONTACTS;
+
+ break;
+
+ case 'forum':
+ $ret['perms_auto'] = true;
+ $ret['default_collection'] = false;
+ $ret['directory_publish'] = true;
+ $ret['online'] = false;
+ $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE|PERMS_W_TAGWALL;
+ $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE|PERMS_W_TAGWALL;
+ $ret['channel_r_stream'] = PERMS_PUBLIC;
+ $ret['channel_r_profile'] = PERMS_PUBLIC;
+ $ret['channel_r_photos'] = PERMS_PUBLIC;
+ $ret['channel_r_abook'] = PERMS_PUBLIC;
+ $ret['channel_w_stream'] = PERMS_CONTACTS;
+ $ret['channel_w_wall'] = PERMS_CONTACTS;
+ $ret['channel_w_tagwall'] = PERMS_CONTACTS;
+ $ret['channel_w_comment'] = PERMS_CONTACTS;
+ $ret['channel_w_mail'] = PERMS_CONTACTS;
+ $ret['channel_w_photos'] = 0;
+ $ret['channel_w_chat'] = PERMS_CONTACTS;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_r_pages'] = PERMS_PUBLIC;
+ $ret['channel_w_pages'] = 0;
+ $ret['channel_a_republish'] = PERMS_SPECIFIC;
+ $ret['channel_w_like'] = PERMS_NETWORK;
+
+ break;
+
+ case 'forum_restricted':
+ $ret['perms_auto'] = false;
+ $ret['default_collection'] = true;
+ $ret['directory_publish'] = true;
+ $ret['online'] = false;
+ $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE|PERMS_W_TAGWALL;
+ $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE|PERMS_W_TAGWALL;
+ $ret['channel_r_stream'] = PERMS_PUBLIC;
+ $ret['channel_r_profile'] = PERMS_PUBLIC;
+ $ret['channel_r_photos'] = PERMS_PUBLIC;
+ $ret['channel_r_abook'] = PERMS_PUBLIC;
+ $ret['channel_w_stream'] = PERMS_CONTACTS;
+ $ret['channel_w_wall'] = PERMS_CONTACTS;
+ $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
+ $ret['channel_w_comment'] = PERMS_CONTACTS;
+ $ret['channel_w_mail'] = PERMS_CONTACTS;
+ $ret['channel_w_photos'] = 0;
+ $ret['channel_w_chat'] = PERMS_CONTACTS;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_r_pages'] = PERMS_PUBLIC;
+ $ret['channel_w_pages'] = 0;
+ $ret['channel_a_republish'] = PERMS_SPECIFIC;
+ $ret['channel_w_like'] = PERMS_CONTACTS;
+
+ break;
+
+
+ case 'forum_private':
+ $ret['perms_auto'] = false;
+ $ret['default_collection'] = true;
+ $ret['directory_publish'] = false;
+ $ret['online'] = false;
+ $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
+ $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
+ $ret['channel_r_stream'] = PERMS_PUBLIC;
+ $ret['channel_r_profile'] = PERMS_CONTACTS;
+ $ret['channel_r_photos'] = PERMS_CONTACTS;
+ $ret['channel_r_abook'] = PERMS_CONTACTS;
+ $ret['channel_w_stream'] = PERMS_CONTACTS;
+ $ret['channel_w_wall'] = PERMS_CONTACTS;
+ $ret['channel_w_tagwall'] = 0;
+ $ret['channel_w_comment'] = PERMS_CONTACTS;
+ $ret['channel_w_mail'] = PERMS_SPECIFIC;
+ $ret['channel_w_photos'] = 0;
+ $ret['channel_w_chat'] = PERMS_SPECIFIC;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_CONTACTS;
+ $ret['channel_r_pages'] = PERMS_CONTACTS;
+ $ret['channel_w_pages'] = 0;
+ $ret['channel_a_republish'] = PERMS_SPECIFIC;
+ $ret['channel_w_like'] = PERMS_CONTACTS;
+
+ break;
+
+ case 'feed':
+ $ret['perms_auto'] = true;
+ $ret['default_collection'] = false;
+ $ret['directory_publish'] = true;
+ $ret['online'] = false;
+ $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
+ $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
+ $ret['channel_r_stream'] = PERMS_PUBLIC;
+ $ret['channel_r_profile'] = PERMS_PUBLIC;
+ $ret['channel_r_photos'] = PERMS_PUBLIC;
+ $ret['channel_r_abook'] = PERMS_PUBLIC;
+ $ret['channel_w_stream'] = PERMS_CONTACTS;
+ $ret['channel_w_wall'] = PERMS_CONTACTS;
+ $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
+ $ret['channel_w_comment'] = PERMS_CONTACTS;
+ $ret['channel_w_mail'] = PERMS_CONTACTS;
+ $ret['channel_w_photos'] = 0;
+ $ret['channel_w_chat'] = PERMS_CONTACTS;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_r_pages'] = PERMS_PUBLIC;
+ $ret['channel_w_pages'] = 0;
+ $ret['channel_a_republish'] = PERMS_NETWORK;
+ $ret['channel_w_like'] = PERMS_NETWORK;
+
+ break;
+
+ case 'feed_restricted':
+
+ $ret['perms_auto'] = false;
+ $ret['default_collection'] = true;
+ $ret['directory_publish'] = false;
+ $ret['online'] = false;
+ $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
+ $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
+ $ret['channel_r_stream'] = PERMS_PUBLIC;
+ $ret['channel_r_profile'] = PERMS_PUBLIC;
+ $ret['channel_r_photos'] = PERMS_PUBLIC;
+ $ret['channel_r_abook'] = PERMS_PUBLIC;
+ $ret['channel_w_stream'] = PERMS_CONTACTS;
+ $ret['channel_w_wall'] = PERMS_CONTACTS;
+ $ret['channel_w_tagwall'] = PERMS_SPECIFIC;
+ $ret['channel_w_comment'] = PERMS_CONTACTS;
+ $ret['channel_w_mail'] = PERMS_CONTACTS;
+ $ret['channel_w_photos'] = 0;
+ $ret['channel_w_chat'] = PERMS_CONTACTS;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_r_pages'] = PERMS_PUBLIC;
+ $ret['channel_w_pages'] = 0;
+ $ret['channel_a_republish'] = PERMS_SPECIFIC;
+ $ret['channel_w_like'] = PERMS_NETWORK;
+
+ break;
+
+ case 'soapbox':
+ $ret['perms_auto'] = true;
+ $ret['default_collection'] = false;
+ $ret['directory_publish'] = true;
+ $ret['online'] = false;
+ $ret['perms_follow'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
+ $ret['perms_accept'] = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
+ |PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_A_REPUBLISH|PERMS_W_LIKE;
+ $ret['channel_r_stream'] = PERMS_PUBLIC;
+ $ret['channel_r_profile'] = PERMS_PUBLIC;
+ $ret['channel_r_photos'] = PERMS_PUBLIC;
+ $ret['channel_r_abook'] = PERMS_PUBLIC;
+ $ret['channel_w_stream'] = 0;
+ $ret['channel_w_wall'] = 0;
+ $ret['channel_w_tagwall'] = 0;
+ $ret['channel_w_comment'] = 0;
+ $ret['channel_w_mail'] = 0;
+ $ret['channel_w_photos'] = 0;
+ $ret['channel_w_chat'] = 0;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_r_pages'] = PERMS_PUBLIC;
+ $ret['channel_w_pages'] = 0;
+ $ret['channel_a_republish'] = PERMS_SPECIFIC;
+ $ret['channel_w_like'] = PERMS_NETWORK;
+
+ break;
+
+ default:
+ break;
}
@@ -471,3 +728,28 @@ function get_role_perms($role) {
}
+function role_selector($current) {
+ $roles = array(
+ 'social' => array( t('Social Networking'),
+ array('social' => t('Mostly Public'), 'social_restricted' => t('Restricted'), 'social_private' => t('Private'))),
+ 'forum' => array( t('Community Forum'),
+ array('forum' => t('Mostly Public'), 'forum_restricted' => t('Restricted'), 'forum_private' => t('Private'))),
+ 'feed' => array( t('Feed Republish'),
+ array('feed' => t('Mostly Public'), 'feed_restricted' => t('Restricted'))),
+ 'soapbox' => array( t('Celebrity/Soapbox'),
+ array('soapbox' => t('Mostly Public'))),
+ 'other' => array( t('Other'),
+ array('custom' => t('Custom/Expert Mode'))));
+ $o = '<select name="permissions_role" id="privacy-role-select">';
+ foreach($roles as $k => $v) {
+ $o .= '<optgroup label="'. htmlspecialchars($v[0]) . '" >';
+ foreach($v[1] as $kk => $vv) {
+ $selected = (($kk === $current) ? ' selected="selected" ' : '');
+ $o .= '<option value="' . $kk . '" ' . $selected . '>' . htmlspecialchars($vv) . '</option>';
+ }
+ $o .= '</optgroup>';
+ }
+ $o .= '</select>';
+ return $o;
+}
+
diff --git a/include/photos.php b/include/photos.php
index 06a99457a..badbbd791 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -266,6 +266,7 @@ function photo_upload($channel, $observer, $args) {
proc_run('php', "include/notifier.php", 'wall-new', $item_id);
$ret['success'] = true;
+ $ret['item'] = $arr;
$ret['body'] = $arr['body'];
$ret['resource_id'] = $photo_hash;
$ret['photoitem_id'] = $item_id;
diff --git a/include/poller.php b/include/poller.php
index c90e48d6b..f689059b9 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -171,6 +171,9 @@ function poller_run($argv, $argc){
proc_run('php','include/expire.php');
proc_run('php','include/cli_suggest.php');
+ require_once('include/hubloc.php');
+ remove_obsolete_hublocs();
+
/**
* End Cron Daily
*/
diff --git a/include/security.php b/include/security.php
index 0f2edc708..e83cc7061 100644
--- a/include/security.php
+++ b/include/security.php
@@ -82,6 +82,19 @@ function change_channel($change_channel) {
intval(PAGE_REMOVED)
);
+ // It's not there. Is this an administrator, and is this the sys channel?
+ if (is_developer()) {
+ if (! $r) {
+ if (is_site_admin()) {
+ $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel_id = %d and ( channel_pageflags & %d) and not (channel_pageflags & %d ) limit 1",
+ intval($change_channel),
+ intval(PAGE_SYSTEM),
+ intval(PAGE_REMOVED)
+ );
+ }
+ }
+ }
+
if($r) {
$hash = $r[0]['channel_hash'];
$_SESSION['uid'] = intval($r[0]['channel_id']);
diff --git a/include/widgets.php b/include/widgets.php
index 1aa018fb6..f1c9ceada 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -481,11 +481,11 @@ function widget_settings_menu($arr) {
'selected' => ''
),
-// array(
-// 'label' => t('Export account'),
-// 'url' => $a->get_baseurl(true) . '/uexport/complete',
-// 'selected' => ''
-// ),
+ array(
+ 'label' => t('Export content'),
+ 'url' => $a->get_baseurl(true) . '/uexport/complete',
+ 'selected' => ''
+ ),
array(
'label' => t('Automatic Permissions (Advanced)'),
diff --git a/include/zot.php b/include/zot.php
index 644d20ec2..b7ffe14e4 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -661,6 +661,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
}
$xchan_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']);
+ $arr['hash'] = $xchan_hash;
+
$import_photos = false;
if(! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key'])) {
@@ -843,174 +845,16 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
// what we are missing for true hub independence is for any changes in the primary hub to
// get reflected not only in the hublocs, but also to update the URLs and addr in the appropriate xchan
- if($arr['locations']) {
-
- $xisting = q("select hubloc_id, hubloc_url, hubloc_sitekey from hubloc where hubloc_hash = '%s'",
- dbesc($xchan_hash)
- );
-
- // See if a primary is specified
-
- $has_primary = false;
- foreach($arr['locations'] as $location) {
- if($location['primary']) {
- $has_primary = true;
- break;
- }
- }
-
- foreach($arr['locations'] as $location) {
- if(! rsa_verify($location['url'],base64url_decode($location['url_sig']),$arr['key'])) {
- logger('import_xchan: Unable to verify site signature for ' . $location['url']);
- $ret['message'] .= sprintf( t('Unable to verify site signature for %s'), $location['url']) . EOL;
- continue;
- }
-
- // Ensure that they have one primary hub
-
- if(! $has_primary)
- $location['primary'] = true;
-
-
- for($x = 0; $x < count($xisting); $x ++) {
- if(($xisting[$x]['hubloc_url'] === $location['url']) && ($xisting[$x]['hubloc_sitekey'] === $location['sitekey'])) {
- $xisting[$x]['updated'] = true;
- }
- }
-
- if(! $location['sitekey']) {
- logger('import_xchan: empty hubloc sitekey. ' . print_r($location,true));
- continue;
- }
-
- // Catch some malformed entries from the past which still exist
-
- if(strpos($location['address'],'/') !== false)
- $location['address'] = substr($location['address'],0,strpos($location['address'],'/'));
-
- // match as many fields as possible in case anything at all changed.
-
- $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
- dbesc($xchan_hash),
- dbesc($arr['guid']),
- dbesc($arr['guid_sig']),
- dbesc($location['url']),
- dbesc($location['url_sig']),
- dbesc($location['host']),
- dbesc($location['address']),
- dbesc($location['callback']),
- dbesc($location['sitekey'])
- );
- if($r) {
- logger('import_xchan: hub exists: ' . $location['url']);
- // update connection timestamp if this is the site we're talking to
- if($location['url'] == $arr['site']['url']) {
- q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d limit 1",
- dbesc(datetime_convert()),
- dbesc(datetime_convert()),
- intval($r[0]['hubloc_id'])
- );
- }
- if($r[0]['hubloc_status'] & HUBLOC_OFFLINE) {
- q("update hubloc set hubloc_status = (hubloc_status ^ %d) where hubloc_id = %d limit 1",
- intval(HUBLOC_OFFLINE),
- intval($r[0]['hubloc_id'])
- );
- if($r[0]['hubloc_flags'] & HUBLOC_FLAGS_ORPHANCHECK) {
- q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where hubloc_id = %d limit 1",
- intval(HUBLOC_FLAGS_ORPHANCHECK),
- intval($r[0]['hubloc_id'])
- );
- }
- q("update xchan set xchan_flags = (xchan_flags ^ %d) where (xchan_flags & %d) and xchan_hash = '%s' limit 1",
- intval(XCHAN_FLAGS_ORPHAN),
- intval(XCHAN_FLAGS_ORPHAN),
- dbesc($xchan_hash)
- );
-
- }
-
- // Remove pure duplicates
- if(count($r) > 1) {
- for($h = 1; $h < count($r); $h ++) {
- q("delete from hubloc where hubloc_id = %d limit 1",
- intval($r[$h]['hubloc_id'])
- );
- }
- }
-
- if((($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) && (! $location['primary']))
- || ((! ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY)) && ($location['primary']))) {
- $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1",
- intval(HUBLOC_FLAGS_PRIMARY),
- dbesc(datetime_convert()),
- intval($r[0]['hubloc_id'])
- );
- $what = 'primary_hub ';
- $changed = true;
- }
- if((($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED) && (! $location['deleted']))
- || ((! ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED)) && ($location['deleted']))) {
- $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1",
- intval(HUBLOC_FLAGS_DELETED),
- dbesc(datetime_convert()),
- intval($r[0]['hubloc_id'])
- );
- $what = 'delete_hub ';
- $changed = true;
- }
- continue;
- }
- // new hub claiming to be primary. Make it so.
-
- if(intval($location['primary'])) {
- $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_hash = '%s' and (hubloc_flags & %d )",
- intval(HUBLOC_FLAGS_PRIMARY),
- dbesc(datetime_convert()),
- dbesc($xchan_hash),
- intval(HUBLOC_FLAGS_PRIMARY)
- );
- }
- logger('import_xchan: new hub: ' . $location['url']);
- $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_flags, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_updated, hubloc_connected)
- values ( '%s','%s','%s','%s', '%s', %d ,'%s','%s','%s','%s','%s','%s','%s')",
- dbesc($arr['guid']),
- dbesc($arr['guid_sig']),
- dbesc($xchan_hash),
- dbesc($location['address']),
- dbesc('zot'),
- intval((intval($location['primary'])) ? HUBLOC_FLAGS_PRIMARY : 0),
- dbesc($location['url']),
- dbesc($location['url_sig']),
- dbesc($location['host']),
- dbesc($location['callback']),
- dbesc($location['sitekey']),
- dbesc(datetime_convert()),
- dbesc(datetime_convert())
- );
- $what .= 'newhub ';
- $changed = true;
-
- }
-
- // get rid of any hubs we have for this channel which weren't reported.
- // This was needed at one time to resolve complicated cross-site inconsistencies, but can cause sync conflict.
- // currently disabled.
-
-// if($xisting) {
-// foreach($xisting as $x) {
-// if(! array_key_exists('updated',$x)) {
-// logger('import_xchan: removing unreferenced hub location ' . $x['hubloc_url']);
-// $r = q("delete from hubloc where hubloc_id = %d limit 1",
-// intval($x['hubloc_id'])
-// );
-// $what .= 'removed_hub';
-// $changed = true;
-// }
-// }
-// }
+ $s = sync_locations($arr,$arr);
+ if($s) {
+ if($s['change_message'])
+ $what .= $s['change_message'];
+ if($s['changed'])
+ $changed = $s['changed'];
+ if($s['message'])
+ $ret['message'] .= $s['message'];
}
// Which entries in the update table are we interested in updating?
@@ -1189,7 +1033,8 @@ function zot_fetch($arr) {
* we will verify the sender and url in each returned message structure and also verify
* that all the messages returned match the site url that we are currently processing.
*
- * The message types handled here are 'activity' (e.g. posts), 'mail' , 'profile', and 'channel_sync'
+ * The message types handled here are 'activity' (e.g. posts), 'mail' , 'profile', 'location',
+ * and 'channel_sync'
*
* @returns array => array ( [0] => string $channel_hash, [1] => string $delivery_status, [2] => string $address )
* suitable for logging remotely, enumerating the processing results of each message/recipient combination.
@@ -1276,6 +1121,11 @@ function zot_import($arr, $sender_url) {
$deliveries = allowed_public_recips($i);
+ if($i['message'] && array_key_exists('type',$i['message']) && $i['message']['type'] === 'location') {
+ $sys = get_sys_channel();
+ $deliveries = array(array('hash' => $sys['xchan_hash']));
+ }
+
// if the scope is anything but 'public' we're going to store it as private regardless
// of the private flag on the post.
@@ -1348,7 +1198,7 @@ function zot_import($arr, $sender_url) {
}
elseif($i['message']['type'] === 'channel_sync') {
-// $arr = get_channelsync_elements($i['message']);
+ // $arr = get_channelsync_elements($i['message']);
$arr = $i['message'];
@@ -1357,6 +1207,15 @@ function zot_import($arr, $sender_url) {
$result = process_channel_sync_delivery($i['notify']['sender'],$arr,$deliveries);
}
+ elseif($i['message']['type'] === 'location') {
+ $arr = $i['message'];
+
+ logger('Location message received: ' . print_r($arr,true), LOGGER_DATA);
+ logger('Location message recipients: ' . print_r($deliveries,true), LOGGER_DATA);
+
+ $result = process_location_delivery($i['notify']['sender'],$arr,$deliveries);
+ }
+
}
if($result){
$return = array_merge($return,$result);
@@ -1800,6 +1659,238 @@ function process_profile_delivery($sender,$arr,$deliveries) {
import_directory_profile($sender['hash'],$arr,$r[0]['xchan_addr'], UPDATE_FLAGS_UPDATED, 0);
}
+function process_location_delivery($sender,$arr,$deliveries) {
+
+ // deliveries is irrelevant
+ logger('process_location_delivery', LOGGER_DEBUG);
+
+ $r = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1",
+ dbesc($sender['hash'])
+ );
+ if($r)
+ $sender['key'] = $r[0]['xchan_pubkey'];
+
+ $x = sync_locations($sender,$arr,true);
+ logger('process_location_delivery: results: ' . print_r($x,true), LOGGER_DATA);
+}
+
+// We need to merge this code with that in the import_xchan function so as to make it
+// easier to maintain changes.
+
+function sync_locations($sender,$arr,$absolute = false) {
+
+ $ret = array();
+
+ if($arr['locations']) {
+
+ $xisting = q("select hubloc_id, hubloc_url, hubloc_sitekey from hubloc where hubloc_hash = '%s'",
+ dbesc($sender['hash'])
+ );
+
+ // See if a primary is specified
+
+ $has_primary = false;
+ foreach($arr['locations'] as $location) {
+ if($location['primary']) {
+ $has_primary = true;
+ break;
+ }
+ }
+
+ foreach($arr['locations'] as $location) {
+ if(! rsa_verify($location['url'],base64url_decode($location['url_sig']),$sender['key'])) {
+ logger('sync_locations: Unable to verify site signature for ' . $location['url']);
+ $ret['message'] .= sprintf( t('Unable to verify site signature for %s'), $location['url']) . EOL;
+ continue;
+ }
+
+ // Ensure that they have one primary hub
+
+ if(! $has_primary)
+ $location['primary'] = true;
+
+ for($x = 0; $x < count($xisting); $x ++) {
+ if(($xisting[$x]['hubloc_url'] === $location['url'])
+ && ($xisting[$x]['hubloc_sitekey'] === $location['sitekey'])) {
+ $xisting[$x]['updated'] = true;
+ }
+ }
+
+ if(! $location['sitekey']) {
+ logger('sync_locations: empty hubloc sitekey. ' . print_r($location,true));
+ continue;
+ }
+
+ // Catch some malformed entries from the past which still exist
+
+ if(strpos($location['address'],'/') !== false)
+ $location['address'] = substr($location['address'],0,strpos($location['address'],'/'));
+
+ // match as many fields as possible in case anything at all changed.
+
+ $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
+ dbesc($sender['hash']),
+ dbesc($sender['guid']),
+ dbesc($sender['guid_sig']),
+ dbesc($location['url']),
+ dbesc($location['url_sig']),
+ dbesc($location['host']),
+ dbesc($location['address']),
+ dbesc($location['callback']),
+ dbesc($location['sitekey'])
+ );
+ if($r) {
+ logger('sync_locations: hub exists: ' . $location['url'], LOGGER_DEBUG);
+
+ // update connection timestamp if this is the site we're talking to
+ // This only happens when called from import_xchan
+
+ if(array_key_exists('site',$arr) && $location['url'] == $arr['site']['url']) {
+ q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d limit 1",
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ intval($r[0]['hubloc_id'])
+ );
+ }
+
+ // if it's marked offline/dead, bring it back
+ // Should we do this? It's basically saying that the channel knows better than
+ // the directory server if the site is alive.
+
+ if($r[0]['hubloc_status'] & HUBLOC_OFFLINE) {
+ q("update hubloc set hubloc_status = (hubloc_status ^ %d) where hubloc_id = %d limit 1",
+ intval(HUBLOC_OFFLINE),
+ intval($r[0]['hubloc_id'])
+ );
+ if($r[0]['hubloc_flags'] & HUBLOC_FLAGS_ORPHANCHECK) {
+ q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where hubloc_id = %d limit 1",
+ intval(HUBLOC_FLAGS_ORPHANCHECK),
+ intval($r[0]['hubloc_id'])
+ );
+ }
+ q("update xchan set xchan_flags = (xchan_flags ^ %d) where (xchan_flags & %d) and xchan_hash = '%s' limit 1",
+ intval(XCHAN_FLAGS_ORPHAN),
+ intval(XCHAN_FLAGS_ORPHAN),
+ dbesc($sender['hash'])
+ );
+ }
+
+ // Remove pure duplicates
+ if(count($r) > 1) {
+ for($h = 1; $h < count($r); $h ++) {
+ q("delete from hubloc where hubloc_id = %d limit 1",
+ intval($r[$h]['hubloc_id'])
+ );
+ }
+ }
+
+ if((($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) && (! $location['primary']))
+ || ((! ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY)) && ($location['primary']))) {
+ $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1",
+ intval(HUBLOC_FLAGS_PRIMARY),
+ dbesc(datetime_convert()),
+ intval($r[0]['hubloc_id'])
+ );
+ $what .= 'primary_hub ';
+ $changed = true;
+ }
+ if((($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED) && (! $location['deleted']))
+ || ((! ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED)) && ($location['deleted']))) {
+ $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1",
+ intval(HUBLOC_FLAGS_DELETED),
+ dbesc(datetime_convert()),
+ intval($r[0]['hubloc_id'])
+ );
+ $what .= 'delete_hub ';
+ $changed = true;
+ }
+ continue;
+ }
+
+ // new hub claiming to be primary. Make it so.
+
+ if(intval($location['primary'])) {
+ $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_hash = '%s' and (hubloc_flags & %d )",
+ intval(HUBLOC_FLAGS_PRIMARY),
+ dbesc(datetime_convert()),
+ dbesc($sender['hash']),
+ intval(HUBLOC_FLAGS_PRIMARY)
+ );
+ }
+ logger('sync_locations: new hub: ' . $location['url']);
+ $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_flags, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_updated, hubloc_connected)
+ values ( '%s','%s','%s','%s', '%s', %d ,'%s','%s','%s','%s','%s','%s','%s')",
+ dbesc($sender['guid']),
+ dbesc($sender['guid_sig']),
+ dbesc($sender['hash']),
+ dbesc($location['address']),
+ dbesc('zot'),
+ intval((intval($location['primary'])) ? HUBLOC_FLAGS_PRIMARY : 0),
+ dbesc($location['url']),
+ dbesc($location['url_sig']),
+ dbesc($location['host']),
+ dbesc($location['callback']),
+ dbesc($location['sitekey']),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert())
+ );
+ $what .= 'newhub ';
+ $changed = true;
+
+ }
+
+ // get rid of any hubs we have for this channel which weren't reported.
+
+ if($absolute && $xisting) {
+ foreach($xisting as $x) {
+ if(! array_key_exists('updated',$x)) {
+ logger('sync_locations: deleting unreferenced hub location ' . $x['hubloc_url']);
+ $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1",
+ intval(HUBLOC_FLAGS_DELETED),
+ dbesc(datetime_convert()),
+ intval($x['hubloc_id'])
+ );
+ $what .= 'removed_hub';
+ $changed = true;
+ }
+ }
+ }
+ }
+
+ $ret['change_message'] = $what;
+ $ret['changed'] = $changed;
+
+ return $ret;
+
+}
+
+
+function zot_encode_locations($channel) {
+ $ret = array();
+
+ $x = zot_get_hublocs($channel['channel_hash']);
+ if($x && count($x)) {
+ foreach($x as $hub) {
+ if(! ($hub['hubloc_flags'] & HUBLOC_FLAGS_UNVERIFIED)) {
+ $ret[] = array(
+ 'host' => $hub['hubloc_host'],
+ 'address' => $hub['hubloc_addr'],
+ 'primary' => (($hub['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) ? true : false),
+ 'url' => $hub['hubloc_url'],
+ 'url_sig' => $hub['hubloc_url_sig'],
+ 'callback' => $hub['hubloc_callback'],
+ 'sitekey' => $hub['hubloc_sitekey'],
+ 'deleted' => (($hub['hubloc_flags'] & HUBLOC_FLAGS_DELETED) ? true : false)
+ );
+ }
+ }
+ }
+ return $ret;
+}
+
+
+
+
/*
* @function import_directory_profile
@@ -2247,7 +2338,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
function process_channel_sync_delivery($sender,$arr,$deliveries) {
// FIXME - this will sync red structures (channel, pconfig and abook). Eventually we need to make this application agnostic.
-// TODO: missing group membership changes
+
$result = array();
@@ -2263,6 +2354,10 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
$channel = $r[0];
+ $max_friends = service_class_fetch($channel['channel_id'],'total_channels');
+ $max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds');
+
+
if($channel['channel_hash'] != $sender['hash']) {
logger('process_channel_sync_delivery: possible forgery. Sender ' . $sender['hash'] . ' is not ' . $channel['channel_hash']);
$result[] = array($d['hash'],'channel mismatch',$channel['channel_name'],'');
@@ -2296,6 +2391,19 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
if(array_key_exists('abook',$arr) && is_array($arr['abook']) && count($arr['abook'])) {
+ $total_friends = 0;
+ $total_feeds = 0;
+
+ $r = q("select abook_id, abook_flags from abook where abook_channel = %d",
+ intval($channel['channel_id'])
+ );
+ if($r) {
+ // don't count yourself
+ $total_friends = ((count($r) > 0) ? $count($r) - 1 : 0);
+ foreach($r as $rr)
+ if($rr['abook_flags'] & ABOOK_FLAG_FEED)
+ $total_feeds ++;
+ }
$disallowed = array('abook_id','abook_account','abook_channel');
@@ -2306,14 +2414,18 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
logger('process_channel_sync_delivery: removing abook entry for ' . $abook['abook_xchan']);
require_once('include/Contact.php');
- $r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d and not ( abook_flags & %d ) limit 1",
+ $r = q("select abook_id, abook_flags from abook where abook_xchan = '%s' and abook_channel = %d and not ( abook_flags & %d ) limit 1",
dbesc($abook['abook_xchan']),
intval($channel['channel_id']),
intval(ABOOK_FLAG_SELF)
);
- if($r)
+ if($r) {
contact_remove($channel['channel_id'],$r[0]['abook_id']);
-
+ if($total_friends)
+ $total_friends --;
+ if($r[0]['abook_flags'] & ABOOK_FLAG_FEED)
+ $total_feeds --;
+ }
continue;
}
@@ -2360,10 +2472,21 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
// make sure we have an abook entry for this xchan on this system
if(! $r) {
+ if($max_friends !== false && $total_friends > $max_friends) {
+ logger('process_channel_sync_delivery: total_channels service class limit exceeded');
+ continue;
+ }
+ if($max_feeds !== false && ($clean['abook_flags'] & ABOOK_FLAG_FEED) && $total_feeds > $max_feeds) {
+ logger('process_channel_sync_delivery: total_feeds service class limit exceeded');
+ continue;
+ }
q("insert into abook ( abook_xchan, abook_channel ) values ('%s', %d ) ",
dbesc($clean['abook_xchan']),
intval($channel['channel_id'])
);
+ $total_friends ++;
+ if($clean['abook_flags'] & ABOOK_FLAG_FEED)
+ $total_feeds ++;
}
if(count($clean)) {