aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Contact.php21
-rw-r--r--include/Import/Importer.php94
-rw-r--r--include/Import/refimport.php282
-rw-r--r--include/RedDAV/RedBrowser.php1
-rw-r--r--include/api.php12
-rw-r--r--include/bb2diaspora.php35
-rw-r--r--include/conversation.php26
-rw-r--r--include/deliver.php28
-rwxr-xr-xinclude/diaspora.php21
-rw-r--r--include/event.php14
-rw-r--r--include/follow.php13
-rw-r--r--include/html2bbcode.php4
-rw-r--r--include/hubloc.php90
-rw-r--r--include/identity.php24
-rwxr-xr-xinclude/items.php59
-rw-r--r--include/notifier.php34
-rw-r--r--include/onepoll.php21
-rw-r--r--include/permissions.php51
-rw-r--r--include/photos.php4
-rw-r--r--include/poller.php20
-rw-r--r--include/reddav.php4
-rw-r--r--include/session.php5
-rw-r--r--include/taxonomy.php24
-rw-r--r--include/widgets.php43
-rw-r--r--include/zot.php191
25 files changed, 990 insertions, 131 deletions
diff --git a/include/Contact.php b/include/Contact.php
index 4440369dc..20e5e1a1e 100644
--- a/include/Contact.php
+++ b/include/Contact.php
@@ -245,11 +245,13 @@ function channel_remove($channel_id, $local = true, $unset_session=true) {
intval($channel_id)
);
+
$r = q("update hubloc set hubloc_flags = (hubloc_flags | %d) where hubloc_hash = '%s'",
intval(HUBLOC_FLAGS_DELETED),
dbesc($channel['channel_hash'])
);
+
$r = q("update xchan set xchan_flags = (xchan_flags | %d) where xchan_hash = '%s'",
intval(XCHAN_FLAGS_DELETED),
dbesc($channel['channel_hash'])
@@ -257,7 +259,6 @@ function channel_remove($channel_id, $local = true, $unset_session=true) {
proc_run('php','include/notifier.php','purge_all',$channel_id);
-
}
q("DELETE FROM `groups` WHERE `uid` = %d", intval($channel_id));
@@ -291,11 +292,23 @@ function channel_remove($channel_id, $local = true, $unset_session=true) {
dbesc(z_root())
);
- $r = q("update xchan set xchan_flags = (xchan_flags | %d) where xchan_hash = '%s' ",
- intval(XCHAN_FLAGS_DELETED),
- dbesc($channel['channel_hash'])
+ // Do we have any valid hublocs remaining?
+
+ $hublocs = 0;
+
+ $r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and not (hubloc_flags & %d)",
+ dbesc($channel['channel_hash']),
+ intval(HUBLOC_FLAGS_DELETED)
);
+ if($r)
+ $hublocs = count($r);
+ if(! $hublocs) {
+ $r = q("update xchan set xchan_flags = (xchan_flags | %d) where xchan_hash = '%s' ",
+ intval(XCHAN_FLAGS_DELETED),
+ dbesc($channel['channel_hash'])
+ );
+ }
proc_run('php','include/directory.php',$channel_id);
diff --git a/include/Import/Importer.php b/include/Import/Importer.php
new file mode 100644
index 000000000..c42344236
--- /dev/null
+++ b/include/Import/Importer.php
@@ -0,0 +1,94 @@
+<?php /** @file */
+
+namespace Redmatrix\Import;
+
+
+class Import {
+
+ $credentials = null;
+ $itemlist = null;
+ $src_items = null;
+
+ $items = null;
+
+ function get_credentials() {
+
+ }
+
+ function get_itemlist() {
+
+
+ }
+
+
+ function get_item_ident($item) {
+
+ }
+
+ function get_item($item_ident) {
+
+ }
+
+ function get_taxonomy($item_ident) {
+
+ }
+
+ function get_children($item_ident) {
+
+ }
+
+ function convert_item($item_ident) {
+
+ }
+
+ function convert_taxonomy($item_ident) {
+
+
+ }
+
+ function convert_child($child) {
+
+ }
+
+ function store($item,$update = false) {
+
+ }
+
+ function run() {
+
+ $this->credentials = $this->get_credentials();
+ $this->itemlist = $this->get_itemlist();
+ if($this->itemlist) {
+ $this->src_items = array();
+ $this->items = array();
+ $cnt = 0;
+ foreach($this->itemlist as $item) {
+ $ident = $item->get_item_ident($item);
+ $this->src_items[$ident]['item'] = $this->get_item($ident);
+ $this->src_items[$ident]['taxonomy'] = $this->get_taxonomy($ident);
+ $this->src_items[$ident]['children'] = $this->get_children($ident);
+ $this->items[$cnt]['item'] = $this->convert_item($ident);
+ $this->items[$cnt]['item']['term'] = $this->convert_taxonomy($ident);
+ if($this->src_items[$ident]['children']) {
+ $this->items[$cnt]['children'] = array();
+ foreach($this->src_items[$ident]['children'] as $child) {
+ $this[$cnt]['children'][] = $this->convert_child($child);
+ }
+ }
+ $cnt ++;
+ }
+
+
+
+
+ }
+
+
+
+
+
+
+ }
+
+
+} \ No newline at end of file
diff --git a/include/Import/refimport.php b/include/Import/refimport.php
new file mode 100644
index 000000000..4f2572660
--- /dev/null
+++ b/include/Import/refimport.php
@@ -0,0 +1,282 @@
+<?php
+
+require_once('include/html2bbcode.php');
+require_once('include/hubloc.php');
+
+// Sample module for importing conversation data from Reflection CMS. Some preparation was used to
+// dump relevant posts, categories and comments into individual JSON files, and also JSON dump of
+// the user table to search for avatars. Importation was also batched in sets of 20 posts per page
+// visit so as to survive shared hosting process limits. This provides some clues as how to handle
+// WordPress imports, which use a somewhat similar DB structure. The batching and individual files
+// might not be needed in VPS environments. As such this could be considered an extreme test case, but
+// the importation was successful in all regards using this code. The module URL was visited repeatedly
+// with a browser until all the posts had been imported.
+
+
+
+
+define('REDMATRIX_IMPORTCHANNEL','mike');
+define('REFLECT_EXPORTUSERNAME','mike');
+define('REFLECT_BLOGNAME','Diary and Other Rantings');
+define('REFLECT_BASEURL','http://example.com/');
+define('REFLECT_USERFILE','user.json');
+
+// set to true if you need to process everything again
+define('REFLECT_OVERWRITE',false);
+
+// we'll only process a small number of posts at a time on a shared host.
+
+define('REFLECT_MAXPERRUN',30);
+
+function reflect_get_channel() {
+
+ // this will be the channel_address or nickname of the red channel
+
+ $c = q("select * from channel left join xchan on channel_hash = xchan_hash
+ where channel_address = '%s' limit 1",
+ dbesc(REDMATRIX_IMPORTCHANNEL)
+ );
+ return $c[0];
+}
+
+
+function refimport_content(&$a) {
+
+ $channel = reflect_get_channel();
+
+ // load the user file. We need that to find the commenter's avatars
+
+ $u = file_get_contents(REFLECT_USERFILE);
+ if($u) {
+ $users = json_decode($u,true);
+ }
+
+ $ignored = 0;
+ $processed = 0;
+
+ $files = glob('article/*');
+ if(! $files)
+ return;
+
+ foreach($files as $f) {
+ $s = file_get_contents($f);
+ $j = json_decode($s,true);
+
+ if(! $j)
+ continue;
+
+ $arr = array();
+
+ // see if this article was already processed
+ $r = q("select * from item where mid = '%s' and uid = %d limit 1",
+ dbesc($j['guid']),
+ intval($channel['channel_id'])
+ );
+ if($r) {
+ if(REFLECT_OVERWRITE)
+ $arr['id'] = $r[0]['id'];
+ else {
+ $ignored ++;
+ rename($f,str_replace('article','done',$f));
+ continue;
+ }
+ }
+
+ $arr['uid'] = $channel['channel_account_id'];
+ $arr['aid'] = $channel['channel_id'];
+ $arr['mid'] = $arr['parent_mid'] = $j['guid'];
+ $arr['created'] = $j['created'];
+ $arr['edited'] = $j['edited'];
+ $arr['author_xchan'] = $channel['channel_hash'];
+ $arr['owner_xchan'] = $channel['channel_hash'];
+ $arr['app'] = REFLECT_BLOGNAME;
+ $arr['item_flags'] = ITEM_ORIGIN|ITEM_WALL|ITEM_THREAD_TOP;
+ $arr['verb'] = ACTIVITY_POST;
+
+ // this is an assumption
+ $arr['comment_policy'] = 'contacts';
+
+
+ // import content. In this case the content is XHTML.
+
+ $arr['title'] = html2bbcode($j['title']);
+ $arr['title'] = htmlspecialchars($arr['title'],ENT_COMPAT,'UTF-8',false);
+
+
+ $arr['body'] = html2bbcode($j['body']);
+ $arr['body'] = htmlspecialchars($arr['body'],ENT_COMPAT,'UTF-8',false);
+
+
+ // convert relative urls to other posts on that service to absolute url on our service.
+ $arr['body'] = preg_replace_callback("/\[url\=\/+article\/(.*?)\](.*?)\[url\]/",'reflect_article_callback',$arr['body']);
+
+ // also import any photos
+ $arr['body'] = preg_replace_callback("/\[img(.*?)\](.*?)\[\/img\]/",'reflect_photo_callback',$arr['body']);
+
+
+ // add categories
+
+ if($j['taxonomy'] && is_array($j['taxonomy']) && count($j['taxonomy'])) {
+ $arr['term'] = array();
+ foreach($j['taxonomy'] as $tax) {
+ $arr['term'][] = array(
+ 'uid' => $channel['channel_id'],
+ 'type' => TERM_CATEGORY,
+ 'otype' => TERM_OBJ_POST,
+ 'term' => trim($tax['name']),
+ 'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($tax['name']))
+ );
+ }
+ }
+
+ // store the item
+
+ if($arr['id'])
+ item_store_update($arr);
+ else
+ item_store($arr);
+
+ // if there are any comments, process them
+ // $comment['registered'] is somebody with an account on the system. Others are mostly anonymous
+
+ if($j['comments']) {
+ foreach($j['comments'] as $comment) {
+ $user = (($comment['registered']) ? reflect_find_user($users,$comment['author']) : null);
+ reflect_comment_store($channel,$arr,$comment,$user);
+ }
+ }
+ $processed ++;
+
+ if(REFLECT_MAXPERRUN && $processed > REFLECT_MAXPERRUN)
+ break;
+ }
+ return 'processed: ' . $processed . EOL . 'completed: ' . $ignored . EOL;
+
+}
+
+function reflect_article_callback($matches) {
+ return '[zrl=' . z_root() . '/display/'. $matches[1] . ']' . $matches[2] . '[/zrl]';
+}
+
+function reflect_photo_callback($matches) {
+
+ if(strpos($matches[2],'http') !== false)
+ return $matches[0];
+
+ $prefix = REFLECT_BASEURL;
+ $x = z_fetch_url($prefix.$matches[2],true);
+
+ $hash = basename($matches[2]);
+
+ if($x['success']) {
+ $channel = reflect_get_channel();
+ require_once('include/photos.php');
+ $p = photo_upload($channel,$channel,
+ array('data' => $x['body'],
+ 'resource_id' => str_replace('-','',$hash),
+ 'filename' => $hash . '.jpg',
+ 'type' => 'image/jpeg',
+ 'not_visible' => true
+ )
+ );
+
+ if($p['success'])
+ $newlink = $p['resource_id'] . '-0.jpg';
+
+
+ // import photo and locate the link for it.
+ return '[zmg]' . z_root() . '/photo/' . $newlink . '[/zmg]';
+
+ }
+ // no replacement. Leave it alone.
+ return $matches[0];
+}
+
+function reflect_find_user($users,$name) {
+ if($users) {
+ foreach($users as $x) {
+ if($x['name'] === $name) {
+ return $x;
+ }
+ }
+ }
+
+ return false;
+
+}
+
+function reflect_comment_store($channel,$post,$comment,$user) {
+
+ // if the commenter was the channel owner, use their redmatrix xchan
+
+ if($comment['author'] === REFLECT_EXPORTUSERNAME && $comment['registered'])
+ $hash = $channel['xchan_hash'];
+ else {
+ // we need a unique hash for the commenter. We don't know how many may have supplied
+ // http://yahoo.com as their URL, so we'll use their avatar guid if they have one.
+ // anonymous folks may get more than one xchan_hash if they commented more than once.
+
+ $hash = (($comment['registered'] && $user) ? $user['avatar'] : '');
+ if(! $hash)
+ $hash = random_string() . '.unknown';
+
+ // create an xchan for them which will also import their profile photo
+ // they will have a network type 'unknown'.
+
+ $x = array(
+ 'hash' => $hash,
+ 'guid' => $hash,
+ 'url' => (($comment['url']) ? $comment['url'] : z_root()),
+ 'photo' => (($user) ? REFLECT_BASEURL . $user['avatar'] : z_root() . '/' . get_default_profile_photo()),
+ 'name' => $comment['author']
+ );
+ xchan_store($x);
+
+ }
+
+ $arr = array();
+
+ $r = q("select * from item where mid = '%s' and uid = %d limit 1",
+ dbesc($comment['guid']),
+ intval($channel['channel_id'])
+ );
+ if($r) {
+ if(REFLECT_OVERWRITE)
+ $arr['id'] = $r[0]['id'];
+ else
+ return;
+ }
+
+ // this is a lot like storing the post except for subtle differences, like parent_mid, flags, author_xchan,
+ // and we don't have a comment edited field so use creation date
+
+ $arr['uid'] = $channel['channel_account_id'];
+ $arr['aid'] = $channel['channel_id'];
+ $arr['mid'] = $comment['guid'];
+ $arr['parent_mid'] = $post['mid'];
+ $arr['created'] = $comment['created'];
+ $arr['edited'] = $comment['created'];
+ $arr['author_xchan'] = $hash;
+ $arr['owner_xchan'] = $channel['channel_hash'];
+ $arr['item_flags'] = ITEM_ORIGIN|ITEM_WALL;
+ $arr['verb'] = ACTIVITY_POST;
+ $arr['comment_policy'] = 'contacts';
+
+
+ $arr['title'] = html2bbcode($comment['title']);
+ $arr['title'] = htmlspecialchars($arr['title'],ENT_COMPAT,'UTF-8',false);
+
+
+ $arr['body'] = html2bbcode($comment['body']);
+ $arr['body'] = htmlspecialchars($arr['body'],ENT_COMPAT,'UTF-8',false);
+ $arr['body'] = preg_replace_callback("/\[url\=\/+article\/(.*?)\](.*?)\[url\]/",'reflect_article_callback',$arr['body']);
+ $arr['body'] = preg_replace_callback("/\[img(.*?)\](.*?)\[\/img\]/",'reflect_photo_callback',$arr['body']);
+
+ // logger('comment: ' . print_r($arr,true));
+
+ if($arr['id'])
+ item_store_update($arr);
+ else
+ item_store($arr);
+
+}
diff --git a/include/RedDAV/RedBrowser.php b/include/RedDAV/RedBrowser.php
index 6ec5c978d..21ea76aed 100644
--- a/include/RedDAV/RedBrowser.php
+++ b/include/RedDAV/RedBrowser.php
@@ -259,6 +259,7 @@ class RedBrowser extends DAV\Browser\Plugin {
$html .= $output;
get_app()->page['content'] = $html;
+ load_pdl(get_app());
construct_page(get_app());
}
diff --git a/include/api.php b/include/api.php
index 8b52253dd..9fe2ef47d 100644
--- a/include/api.php
+++ b/include/api.php
@@ -621,7 +621,19 @@ require_once('include/items.php');
api_register_func('api/red/group','api_group', true);
+ function api_red_xchan(&$a,$type) {
+ if(api_user() === false)
+ return false;
+ require_once('include/hubloc.php');
+ if($_SERVER['request_method'] === 'POST') {
+ $r = xchan_store($_REQUEST);
+ }
+ $r = xchan_fetch($_REQUEST);
+ json_return_and_die($r);
+ };
+ api_register_func('api/red/xchan','api_red_xchan',true);
+
function api_statuses_mediap(&$a, $type) {
if (api_user() === false) {
diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php
index 9a87de5b2..3c4f07568 100644
--- a/include/bb2diaspora.php
+++ b/include/bb2diaspora.php
@@ -116,6 +116,8 @@ function diaspora_mention_callback($matches) {
function diaspora2bb($s,$use_zrl = false) {
+ $s = str_replace("&#xD;\n&gt;","",$s);
+
$s = html_entity_decode($s,ENT_COMPAT,'UTF-8');
// Too many new lines. So deactivated the following line
@@ -275,7 +277,7 @@ 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);
+ logger('bb2diaspora_itemwallwall: author: ' . print_r($item['author'],true), LOGGER_DATA);
}
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']) {
@@ -290,14 +292,18 @@ function bb2diaspora_itemwallwall(&$item) {
// We have to do something similar for wall-to-wall comments. ITEM_WALL|ITEM_ORIGIN indicates that it was posted on this site.
// Regular matrix comments may have one of these bits set, but not both.
- if(($item['mid'] != $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && ($item['item_flags'] & (ITEM_WALL|ITEM_ORIGIN)) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_m']) {
- logger('bb2diaspora_itemwallwall: wall to wall comment',LOGGER_DEBUG);
+ // Update: this is getting triggered way too often and unnecessarily. Commenting out until we find a better solution.
+ // It's not an easy problem. For now we'll live with the mis-attributions, as wall to wall comments are much less frequent
+ // than wall-to-wall posts.
+
+// if(($item['mid'] != $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (($item['item_flags'] & (ITEM_WALL|ITEM_ORIGIN)) == (ITEM_WALL|ITEM_ORIGIN)) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_m']) {
+// logger('bb2diaspora_itemwallwall: wall to wall comment',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']['xchan_photo_m'] . '[/img]'
- . '[url=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/url]' . "\n\n"
- . $item['body'];
- }
+// $item['body'] = "\n\n"
+// . '[img]' . $item['author']['xchan_photo_m'] . '[/img]'
+// . '[url=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/url]' . "\n\n"
+// . $item['body'];
+// }
// $item['author'] might cause a surprise further down the line if it wasn't expected to be here.
@@ -334,8 +340,13 @@ function bb2diaspora_itembody($item,$force_update = false) {
if(array_key_exists('item_flags',$item) && ($item['item_flags'] & ITEM_OBSCURED)) {
$key = get_config('system','prvkey');
- $newitem['title'] = (($item['title']) ? crypto_unencapsulate(json_decode($item['title'],true),$key) : '');
- $newitem['body'] = (($item['body']) ? crypto_unencapsulate(json_decode($item['body'],true),$key) : '');
+ $b = json_decode($item['body'],true);
+ // if called from diaspora_process_outbound, this decoding has already been done.
+ // Everything else that calls us will not yet be decoded.
+ if($b && is_array($b) && array_key_exists('iv',$b)) {
+ $newitem['title'] = (($item['title']) ? crypto_unencapsulate(json_decode($item['title'],true),$key) : '');
+ $newitem['body'] = (($item['body']) ? crypto_unencapsulate(json_decode($item['body'],true),$key) : '');
+ }
}
bb2diaspora_itemwallwall($newitem);
@@ -377,7 +388,7 @@ function bb2diaspora_itembody($item,$force_update = false) {
}
}
- logger('bb2diaspora_itembody : ' . $body);
+// logger('bb2diaspora_itembody : ' . $body, LOGGER_DATA);
return html_entity_decode($body);
@@ -451,7 +462,7 @@ function format_event_diaspora($ev) {
$bd_format = t('l F d, Y \@ g:i A') ; // Friday January 18, 2011 @ 8 AM
- $o = 'Friendica event notification:' . "\n";
+ $o = t('Redmatrix event notification:') . "\n";
$o .= '**' . (($ev['summary']) ? bb2diaspora($ev['summary']) : bb2diaspora($ev['desc'])) . '**' . "\n";
diff --git a/include/conversation.php b/include/conversation.php
index b22b570a1..a531de9ba 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -827,8 +827,8 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
$threads = null;
}
- if($page_mode === 'preview')
- logger('preview: ' . print_r($threads,true));
+// if($page_mode === 'preview')
+// logger('preview: ' . print_r($threads,true));
// Do not un-comment if smarty3 is in use
// logger('page_template: ' . $page_template);
@@ -1551,16 +1551,18 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
);
}
- require_once('include/chat.php');
- $has_chats = chatroom_list_count($uid);
- if ($has_chats) {
- $tabs[] = array(
- 'label' => t('Chatrooms'),
- 'url' => $a->get_baseurl() . '/chat/' . $nickname,
- 'sel' => ((argv(0) == 'chat') ? 'active' : '' ),
- 'title' => t('Chatrooms'),
- 'id' => 'chat-tab',
- );
+ if($p['chat']) {
+ require_once('include/chat.php');
+ $has_chats = chatroom_list_count($uid);
+ if ($has_chats) {
+ $tabs[] = array(
+ 'label' => t('Chatrooms'),
+ 'url' => $a->get_baseurl() . '/chat/' . $nickname,
+ 'sel' => ((argv(0) == 'chat') ? 'active' : '' ),
+ 'title' => t('Chatrooms'),
+ 'id' => 'chat-tab',
+ );
+ }
}
require_once('include/menu.php');
diff --git a/include/deliver.php b/include/deliver.php
index f4fae6061..729018448 100644
--- a/include/deliver.php
+++ b/include/deliver.php
@@ -38,15 +38,33 @@ function deliver_run($argv, $argc) {
continue;
}
- if($r[0]['outq_posturl'] === z_root() . '/post') {
+ $notify = json_decode($r[0]['outq_notify'],true);
+
+ // Check if this is a conversation request packet. It won't have outq_msg
+ // but will be an encrypted packet - so will need to be handed off to
+ // web delivery rather than processed inline.
+
+ $sendtoweb = false;
+ if(array_key_exists('iv',$notify) && (! $r[0]['outq_msg']))
+ $sendtoweb = true;
+
+ if(($r[0]['outq_posturl'] === z_root() . '/post') && (! $sendtoweb)) {
logger('deliver: local delivery', LOGGER_DEBUG);
// local delivery
// we should probably batch these and save a few delivery processes
- // If there is no outq_msg, this is a refresh_all message which does not require local handling
- if($r[0]['outq_msg']) {
- $msg = array('body' => json_encode(array('pickup' => array(array('notify' => json_decode($r[0]['outq_notify'],true),'message' => json_decode($r[0]['outq_msg'],true))))));
- zot_import($msg,z_root());
+ if($r[0]['outq_msg']) {
+ $m = json_decode($r[0]['outq_msg'],true);
+ if(array_key_exists('message_list',$m)) {
+ foreach($m['message_list'] as $mm) {
+ $msg = array('body' => json_encode(array('pickup' => array(array('notify' => $notify,'message' => $mm)))));
+ zot_import($msg,z_root());
+ }
+ }
+ else {
+ $msg = array('body' => json_encode(array('pickup' => array(array('notify' => $notify,'message' => $m)))));
+ zot_import($msg,z_root());
+ }
$r = q("delete from outq where outq_hash = '%s' limit 1",
dbesc($argv[$x])
);
diff --git a/include/diaspora.php b/include/diaspora.php
index c6d4b7423..7858fa203 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_DATA);
+// logger('diaspora_dispatch: ' . print_r($xmlbase,true), LOGGER_DATA);
if($xmlbase->request) {
@@ -673,16 +673,15 @@ function diaspora_request($importer,$xml) {
return;
}
- $default_perms = 0;
- // look for default permissions to apply in return - e.g. auto-friend
- $z = q("select * from abook where abook_channel = %d and (abook_flags & %d) limit 1",
- intval($importer['channel_id']),
- intval(ABOOK_FLAG_SELF)
- );
-
- if($z)
- $default_perms = intval($z[0]['abook_my_perms']);
-
+ $role = get_pconfig($channel['channel_id'],'system','permissions_role');
+ if($role) {
+ $x = get_role_perms($role);
+ if($x['perms_auto'])
+ $default_perms = $x['perms_accept'];
+ }
+ if(! $default_perms)
+ $default_perms = intval(get_pconfig($channel['channel_id'],'system','autoperms'));
+
$their_perms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK|PERMS_W_STREAM|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT|PERMS_R_STORAGE|PERMS_R_PAGES;
$r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_my_perms, abook_their_perms, abook_closeness, abook_rating, abook_created, abook_updated, abook_connected, abook_dob, abook_flags) values ( %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', %d )",
diff --git a/include/event.php b/include/event.php
index 1fe6e6f7f..03ecaa0a7 100644
--- a/include/event.php
+++ b/include/event.php
@@ -400,8 +400,7 @@ function event_store_item($arr,$event) {
}
else {
- $z = q("select * from channel where channel_hash = '%s' and channel_id = %d limit 1",
- dbesc($event['event_xchan']),
+ $z = q("select * from channel where channel_id = %d limit 1",
intval($arr['uid'])
);
@@ -413,7 +412,7 @@ function event_store_item($arr,$event) {
$item_arr['id'] = $item['id'];
}
else {
- $wall = (($z) ? true : false);
+ $wall = (($z[0]['channel_hash'] == $event['event_xchan']) ? true : false);
$item_flags = ITEM_THREAD_TOP;
if($wall) {
@@ -455,7 +454,14 @@ function event_store_item($arr,$event) {
$item_arr['body'] = $prefix . format_event_bbcode($arr);
- $item_arr['plink'] = z_root() . '/channel/' . $z[0]['channel_address'] . '/?f=&mid=' . $item_arr['mid'];
+ // if it's local send the permalink to the channel page.
+ // otherwise we'll fallback to /display/$message_id
+
+ if($wall)
+ $item_arr['plink'] = z_root() . '/channel/' . $z[0]['channel_address'] . '/?f=&mid=' . $item_arr['mid'];
+ else
+ $item_arr['plink'] = z_root() . '/display/' . $item_arr['mid'];
+
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($arr['event_xchan'])
diff --git a/include/follow.php b/include/follow.php
index c8bd3c500..421bdd083 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -13,6 +13,8 @@ require_once('include/zot.php');
function new_contact($uid,$url,$channel,$interactive = false, $confirm = false) {
+
+
$result = array('success' => false,'message' => '');
$a = get_app();
@@ -62,9 +64,9 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
$j = json_decode($ret['body'],true);
}
- if($is_red && $j) {
+ $my_perms = get_channel_default_perms($uid);
- $my_perms = PERMS_W_STREAM|PERMS_W_MAIL;
+ if($is_red && $j) {
$role = get_pconfig($uid,'system','permissions_role');
if($role) {
@@ -135,7 +137,6 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
}
}
- $my_perms = 0;
$their_perms = 0;
$xchan_hash = '';
@@ -162,7 +163,6 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
if($r) {
$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);
@@ -203,8 +203,9 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
return $result;
}
- $r = q("select count(*) as total from abook where abook_account = %d and ( abook_flags & ABOOK_FLAG_FEED )",
- intval($aid)
+ $r = q("select count(*) as total from abook where abook_account = %d and ( abook_flags & %d )",
+ intval($aid),
+ intval(ABOOK_FLAG_FEED)
);
if($r)
$total_feeds = $r[0]['total'];
diff --git a/include/html2bbcode.php b/include/html2bbcode.php
index 6d6e6333b..9ffc85a82 100644
--- a/include/html2bbcode.php
+++ b/include/html2bbcode.php
@@ -16,7 +16,7 @@ function node2bbcode(&$doc, $oldnode, $attributes, $startbb, $endbb)
function node2bbcodesub(&$doc, $oldnode, $attributes, $startbb, $endbb)
{
- $savestart = str_replace('$', '%', $startbb);
+ $savestart = str_replace('$', '\x01', $startbb);
$replace = false;
$xpath = new DomXPath($doc);
@@ -37,7 +37,7 @@ function node2bbcodesub(&$doc, $oldnode, $attributes, $startbb, $endbb)
foreach ($attributes as $attribute => $value) {
- $startbb = str_replace('%'.++$i, '$1', $startbb);
+ $startbb = str_replace('\x01'.++$i, '$1', $startbb);
if (strpos('*'.$startbb, '$1') > 0) {
diff --git a/include/hubloc.php b/include/hubloc.php
index 04c29315a..0a1b51331 100644
--- a/include/hubloc.php
+++ b/include/hubloc.php
@@ -170,4 +170,92 @@ function hubloc_change_primary($hubloc) {
return true;
}
- \ No newline at end of file
+
+
+function xchan_store($arr) {
+
+ if(! $arr['hash'])
+ $arr['hash'] = $arr['guid'];
+ if(! $arr['hash'])
+ return false;
+
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ dbesc($arr['hash'])
+ );
+ if($r)
+ return true;
+
+ if(! $arr['network'])
+ $arr['network'] = 'unknown';
+ if(! $arr['name'])
+ $arr['name'] = 'unknown';
+ if(! $arr['url'])
+ $arr['url'] = z_root();
+ if(! $arr['photo'])
+ $arr['photo'] = get_default_profile_photo();
+
+ $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_instance_url, xchan_flags, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s',%d,'%s') ",
+ dbesc($arr['hash']),
+ dbesc($arr['guid']),
+ dbesc($arr['guid_sig']),
+ dbesc($arr['pubkey']),
+ dbesc($arr['address']),
+ dbesc($arr['url']),
+ dbesc($arr['connurl']),
+ dbesc($arr['follow']),
+ dbesc($arr['connpage']),
+ dbesc($arr['name']),
+ dbesc($arr['network']),
+ dbesc($arr['instance_url']),
+ intval($arr['flags']),
+ dbesc(datetime_convert())
+ );
+ if(! $r)
+ return $r;
+
+ $photos = import_profile_photo($arr['photo'],$arr['hash']);
+ $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s' limit 1",
+ dbesc(datetime_convert()),
+ dbesc($photos[0]),
+ dbesc($photos[1]),
+ dbesc($photos[2]),
+ dbesc($photos[3]),
+ dbesc($arr['hash'])
+ );
+ return $r;
+
+}
+
+
+function xchan_fetch($arr) {
+
+ $key = '';
+ if($arr['hash']) {
+ $key = 'xchan_hash';
+ $v = $arr['hash'];
+ }
+ elseif($arr['guid']) {
+ $key = 'xchan_guid';
+ $v = $arr['guid'];
+ }
+ elseif($arr['address']) {
+ $key = 'xchan_addr';
+ $v = $arr['address'];
+ }
+
+ if(! $key)
+ return false;
+
+ $r = q("select * from xchan where $key = '$v'");
+ if(! $r)
+ return false;
+
+ $ret = array();
+ foreach($r as $k => $v) {
+ if($k === 'xchan_addr')
+ $ret['address'] = $v;
+ else
+ $ret[str_replace('xchan_','',$k)] = $v;
+ }
+ return $ret;
+} \ No newline at end of file
diff --git a/include/identity.php b/include/identity.php
index 07bfaebbd..b9ee00623 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -176,6 +176,7 @@ function create_identity($arr) {
// save this for auto_friending
$total_identities = $ret['total_identities'];
+
$nick = mb_strtolower(trim($arr['nickname']));
if(! $nick) {
$ret['message'] = t('Nickname is required.');
@@ -347,10 +348,13 @@ function create_identity($arr) {
dbesc($a->get_baseurl() . "/photo/profile/m/{$newuid}")
);
- $myperms = 0;
if($role_permissions) {
$myperms = ((array_key_exists('perms_auto',$role_permissions) && $role_permissions['perms_auto']) ? intval($role_permissions['perms_accept']) : 0);
}
+ else
+ $myperms = 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;
$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 ) ",
@@ -372,6 +376,8 @@ function create_identity($arr) {
set_pconfig($newuid,'system','permissions_role',$arr['permissions_role']);
if(array_key_exists('online',$role_permissions))
set_pconfig($newuid,'system','hide_presence',1-intval($role_permissions['online']));
+ if(array_key_exists('perms_auto',$role_permissions))
+ set_pconfig($newuid,'system','autoperms',(($role_permissions['perms_auto']) ? $role_permissions['perms_accept'] : 0));
}
// Create a group with yourself as a member. This allows somebody to use it
@@ -389,7 +395,8 @@ function create_identity($arr) {
dbesc( t('Friends') )
);
if($r) {
- q("update channel set channel_allow_gid = '%s' where channel_id = %d limit 1",
+ q("update channel set channel_default_group = '%s', channel_allow_gid = '%s' where channel_id = %d limit 1",
+ dbesc($r[0]['hash']),
dbesc('<' . $r[0]['hash'] . '>'),
intval($newuid)
);
@@ -403,6 +410,7 @@ function create_identity($arr) {
$accts = get_config('system','auto_follow');
if(($accts) && (! $total_identities)) {
+ require_once('include/follow.php');
if(! is_array($accts))
$accts = array($accts);
foreach($accts as $acct) {
@@ -1558,4 +1566,16 @@ function notifications_on($channel_id,$value) {
intval($channel_id)
);
return $x;
+}
+
+
+function get_channel_default_perms($uid) {
+
+ $r = q("select abook_my_perms from abook where abook_channel = %d and abook_flags & %d limit 1",
+ intval($uid),
+ intval(ABOOK_FLAG_SELF)
+ );
+ if($r)
+ return $r[0]['abook_my_perms'];
+ return 0;
} \ No newline at end of file
diff --git a/include/items.php b/include/items.php
index 40343d505..7e2bb4f18 100755
--- a/include/items.php
+++ b/include/items.php
@@ -98,6 +98,7 @@ function collect_recipients($item,&$private_envelope) {
}
}
+
// This is a somewhat expensive operation but important.
// Don't send this item to anybody who isn't allowed to see it
@@ -213,6 +214,7 @@ function can_comment_on_post($observer_xchan,$item) {
break;
case 'any connections':
case 'contacts':
+ case 'authenticated':
case '':
if(array_key_exists('owner',$item)) {
if(($item['owner']['abook_xchan']) && ($item['owner']['abook_their_perms'] & PERMS_W_COMMENT))
@@ -2516,7 +2518,7 @@ function item_store_update($arr,$allow_exec = false) {
return $ret;
}
-function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id) {
+function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, $walltowall = false) {
// We won't be able to sign Diaspora comments for authenticated visitors
// - we don't have their private key
@@ -2524,9 +2526,18 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id)
// since Diaspora doesn't handle edits we can only do this for the original text and not update it.
require_once('include/bb2diaspora.php');
- $signed_body = bb2diaspora_itembody($datarray);
+ $signed_body = bb2diaspora_itembody($datarray,$walltowall);
+
+ if($walltowall) {
+ logger('wall to wall comment',LOGGER_DEBUG);
+ // post will come across with the owner's identity. Throw a preamble onto the post to indicate the true author.
+ $signed_body = "\n\n"
+ . '![' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_photo_m'] . ')'
+ . '[' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_url'] . ')' . "\n\n"
+ . $signed_body;
+ }
- logger('mod_item: storing diaspora comment signature',LOGGER_DEBUG);
+ logger('storing diaspora comment signature',LOGGER_DEBUG);
$diaspora_handle = $channel['channel_address'] . '@' . get_app()->get_hostname();
@@ -2963,7 +2974,15 @@ function tgroup_check($uid,$item) {
// At this point we've determined that the person receiving this post was mentioned in it.
// Now let's check if this mention was inside a reshare so we don't spam a forum
- $body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
+
+ $body = $item['body'];
+
+ if(array_key_exists('item_flags',$item) && ($item['item_flags'] & ITEM_OBSCURED) && $body) {
+ $key = get_config('system','prvkey');
+ $body = crypto_unencapsulate(json_decode($body,true),$key);
+ }
+
+ $body = preg_replace('/\[share(.*?)\[\/share\]/','',$body);
$pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'] . '+','/') . '\[\/zrl\]/';
@@ -4117,10 +4136,13 @@ function first_post_date($uid,$wall = false) {
* current flat list of all representative dates.
*/
-function list_post_dates($uid,$wall) {
+function list_post_dates($uid,$wall,$mindate) {
$dnow = datetime_convert('',date_default_timezone_get(),'now','Y-m-d');
- $dthen = first_post_date($uid,$wall);
+ if($mindate)
+ $dthen = datetime_convert('',date_default_timezone_get(),$mindate);
+ else
+ $dthen = first_post_date($uid,$wall);
if(! $dthen)
return array();
@@ -4130,7 +4152,7 @@ function list_post_dates($uid,$wall) {
if(intval(substr($dnow,8)) > 28)
$dnow = substr($dnow,0,8) . '28';
if(intval(substr($dthen,8)) > 28)
- $dnow = substr($dthen,0,8) . '28';
+ $dthen = substr($dthen,0,8) . '28';
$ret = array();
// Starting with the current month, get the first and last days of every
@@ -4164,7 +4186,7 @@ function posted_dates($uid,$wall) {
if(intval(substr($dnow,8)) > 28)
$dnow = substr($dnow,0,8) . '28';
if(intval(substr($dthen,8)) > 28)
- $dnow = substr($dthen,0,8) . '28';
+ $dthen = substr($dthen,0,8) . '28';
$ret = array();
// Starting with the current month, get the first and last days of every
@@ -4238,14 +4260,24 @@ function fetch_post_tags($items,$link = false) {
-function zot_feed($uid,$observer_xchan,$mindate) {
+function zot_feed($uid,$observer_xchan,$arr) {
$result = array();
- $mindate = datetime_convert('UTC','UTC',$mindate);
+ $mindate = null;
+ $message_id = null;
+
+ if(array_key_exists('mindate',$arr)) {
+ $mindate = datetime_convert('UTC','UTC',$arr['mindate']);
+ }
+
+ if(array_key_exists('message_id',$arr)) {
+ $message_id = $arr['message_id'];
+ }
+
+
if(! $mindate)
$mindate = NULL_DATE;
-
$mindate = dbesc($mindate);
logger('zot_feed: ' . $uid);
@@ -4267,6 +4299,11 @@ function zot_feed($uid,$observer_xchan,$mindate) {
else
$limit = " limit 0, 50 ";
+ if($message_id) {
+ $sql_extra .= " and mid = '" . dbesc($message_id) . "' ";
+ $limit = '';
+ }
+
$items = array();
if(is_sys_channel($uid)) {
diff --git a/include/notifier.php b/include/notifier.php
index 79a6886ad..c193db116 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -58,6 +58,7 @@ require_once('include/html2plain.php');
* expire channel_id
* relay item_id (item was relayed to owner, we will deliver it as owner)
* location channel_id
+ * request channel_id xchan_hash message_id
*
*/
@@ -142,6 +143,7 @@ function notifier_run($argv, $argc){
$expire = false;
+ $request = false;
$mail = false;
$fsuggest = false;
$top_level = false;
@@ -175,6 +177,22 @@ function notifier_run($argv, $argc){
$channel = $s[0];
}
+ elseif($cmd === 'request') {
+ $channel_id = $item_id;
+ $xchan = $argv[3];
+ $request_message_id = $argv[4];
+
+ $s = q("select * from channel where channel_id = %d limit 1",
+ intval($channel_id)
+ );
+ if($s)
+ $channel = $s[0];
+
+ $private = true;
+ $recipients[] = $xchan;
+ $packet_type = 'request';
+ $normal_mode = false;
+ }
elseif($cmd === 'expire') {
// FIXME
@@ -550,6 +568,7 @@ function notifier_run($argv, $argc){
'mail' => $mail,
'location' => $location,
'fsuggest' => $fsuggest,
+ 'request' => $request,
'normal_mode' => $normal_mode,
'packet_type' => $packet_type,
'walltowall' => $walltowall
@@ -579,6 +598,21 @@ function notifier_run($argv, $argc){
dbesc('')
);
}
+ elseif($packet_type === 'request') {
+ $n = zot_build_packet($channel,'request',$env_recips,$hub['hubloc_sitekey'],$hash,array('message_id' => $request_message_id));
+ q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
+ dbesc($hash),
+ intval($channel['channel_account_id']),
+ intval($channel['channel_id']),
+ dbesc('zot'),
+ dbesc($hub['hubloc_callback']),
+ intval(1),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ dbesc($n),
+ dbesc('')
+ );
+ }
else {
$n = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash);
q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
diff --git a/include/onepoll.php b/include/onepoll.php
index 98d52db93..7a81282b3 100644
--- a/include/onepoll.php
+++ b/include/onepoll.php
@@ -15,12 +15,6 @@ function onepoll_run($argv, $argc){
logger('onepoll: start');
- $manual_id = 0;
- $generation = 0;
-
- $force = false;
- $restart = false;
-
if(($argc > 1) && (intval($argv[1])))
$contact_id = intval($argv[1]);
@@ -28,7 +22,7 @@ function onepoll_run($argv, $argc){
logger('onepoll: no contact');
return;
}
-
+
$d = datetime_convert();
$contacts = q("SELECT abook.*, xchan.*, account.*
@@ -90,7 +84,8 @@ function onepoll_run($argv, $argc){
$x = zot_refresh($contact,$importer);
$responded = false;
- $updated = datetime_convert();
+ $updated = datetime_convert();
+ $connected = datetime_convert();
if(! $x) {
// mark for death by not updating abook_connected, this is caught in include/poller.php
q("update abook set abook_updated = '%s' where abook_id = %d limit 1",
@@ -101,7 +96,7 @@ function onepoll_run($argv, $argc){
else {
q("update abook set abook_updated = '%s', abook_connected = '%s' where abook_id = %d limit 1",
dbesc($updated),
- dbesc($updated),
+ dbesc($connected),
intval($contact['abook_id'])
);
$responded = true;
@@ -120,7 +115,9 @@ function onepoll_run($argv, $argc){
if($fetch_feed) {
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
- $x = z_fetch_url($feedurl . '?f=&mindate=' . urlencode($last_update));
+ $feedurl .= '?f=&mindate=' . urlencode($last_update);
+
+ $x = z_fetch_url($feedurl);
logger('feed_update: ' . print_r($x,true), LOGGER_DATA);
@@ -143,8 +140,8 @@ function onepoll_run($argv, $argc){
}
}
- // fetch some items
- // set last updated timestamp
+
+ // update the poco details for this connection
if($contact['xchan_connurl']) {
$r = q("SELECT xlink_id from xlink
diff --git a/include/permissions.php b/include/permissions.php
index 61ac8aea3..186ba32d8 100644
--- a/include/permissions.php
+++ b/include/permissions.php
@@ -460,6 +460,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = PERMS_CONTACTS;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
@@ -492,6 +493,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = PERMS_CONTACTS;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
@@ -524,6 +526,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
@@ -555,6 +558,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = PERMS_CONTACTS;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
@@ -586,6 +590,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = PERMS_CONTACTS;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
@@ -618,6 +623,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_CONTACTS;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_CONTACTS;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
@@ -649,6 +655,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = PERMS_CONTACTS;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_NETWORK;
@@ -681,6 +688,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = PERMS_CONTACTS;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
@@ -710,6 +718,7 @@ function get_role_perms($role) {
$ret['channel_w_chat'] = 0;
$ret['channel_a_delegate'] = 0;
$ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = 0;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
@@ -717,6 +726,40 @@ function get_role_perms($role) {
break;
+ case 'repository':
+ $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_W_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_W_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'] = PERMS_CONTACTS;
+ $ret['channel_w_chat'] = PERMS_CONTACTS;
+ $ret['channel_a_delegate'] = 0;
+ $ret['channel_r_storage'] = PERMS_PUBLIC;
+ $ret['channel_w_storage'] = PERMS_CONTACTS;
+ $ret['channel_r_pages'] = PERMS_PUBLIC;
+ $ret['channel_w_pages'] = PERMS_CONTACTS;
+ $ret['channel_a_republish'] = PERMS_SPECIFIC;
+ $ret['channel_w_like'] = PERMS_NETWORK;
+
+ break;
+
+
+
default:
break;
@@ -734,6 +777,10 @@ function get_role_perms($role) {
function role_selector($current) {
+
+ if(! $current)
+ $current = 'custom';
+
$roles = array(
'social' => array( t('Social Networking'),
array('social' => t('Mostly Public'), 'social_restricted' => t('Restricted'), 'social_private' => t('Private'))),
@@ -741,8 +788,8 @@ function role_selector($current) {
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'))),
+ 'special' => array( t('Special Purpose'),
+ array('soapbox' => t('Celebrity/Soapbox'), 'repository' => t('Group Repository'))),
'other' => array( t('Other'),
array('custom' => t('Custom/Expert Mode'))));
$o = '<select name="permissions_role" id="privacy-role-select">';
diff --git a/include/photos.php b/include/photos.php
index badbbd791..23c1ea826 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -178,7 +178,7 @@ function photo_upload($channel, $observer, $args) {
if($args['title'])
$p['title'] = $args['title'];
if($args['description'])
- $p['desciprion'] = $args['description'];
+ $p['description'] = $args['description'];
$r1 = $ph->save($p);
@@ -431,7 +431,7 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
// Create item container
$item_flags = ITEM_WALL|ITEM_ORIGIN|ITEM_THREAD_TOP;
- $item_restrict = (($visible) ? ITEM_HIDDEN : ITEM_VISIBLE);
+ $item_restrict = (($visible) ? ITEM_VISIBLE : ITEM_HIDDEN);
$title = '';
$mid = item_message_id();
diff --git a/include/poller.php b/include/poller.php
index 61298b0ab..026d84c62 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -25,6 +25,15 @@ function poller_run($argv, $argc){
if(! $interval)
$interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval')));
+ // Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
+ $lockfile = 'store/[data]/poller';
+ if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))) {
+ logger("poller: Already running");
+ return;
+ }
+
+ // Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
+ file_put_contents($lockfile, $x);
logger('poller: start');
@@ -114,8 +123,8 @@ function poller_run($argv, $argc){
if(($d2 != $d1) && ($h1 == $h2)) {
- require_once('include/dir_fns.php');
- check_upstream_directory();
+ require_once('include/dir_fns.php');
+ check_upstream_directory();
call_hooks('cron_daily',datetime_convert());
@@ -296,6 +305,7 @@ function poller_run($argv, $argc){
$update = true;
}
else {
+
// if we've never connected with them, start the mark for death countdown from now
if($c == NULL_DATE) {
@@ -342,7 +352,6 @@ function poller_run($argv, $argc){
$update = true;
}
-
}
if((! $update) && (! $force))
@@ -375,7 +384,10 @@ function poller_run($argv, $argc){
}
}
}
-
+
+ //All done - clear the lockfile
+ @unlink($lockfile);
+
return;
}
diff --git a/include/reddav.php b/include/reddav.php
index 86b3a00e4..c16e08e27 100644
--- a/include/reddav.php
+++ b/include/reddav.php
@@ -50,7 +50,7 @@ function RedChannelList(&$auth) {
if ($r) {
foreach ($r as $rr) {
if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage')) {
- logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DEBUG);
+ logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA);
// @todo can't we drop '/cloud'? It gets stripped off anyway in RedDirectory
$ret[] = new RedDAV\RedDirectory('/cloud/' . $rr['channel_address'], $auth);
}
@@ -188,7 +188,7 @@ function RedCollectionData($file, &$auth) {
* @throw \Sabre\DAV\Exception\Forbidden
*/
function RedFileData($file, &$auth, $test = false) {
- logger($file . (($test) ? ' (test mode) ' : ''), LOGGER_DEBUG);
+ logger($file . (($test) ? ' (test mode) ' : ''), LOGGER_DATA);
$x = strpos($file, '/cloud');
if ($x === 0) {
diff --git a/include/session.php b/include/session.php
index b531688e2..8500e2cd3 100644
--- a/include/session.php
+++ b/include/session.php
@@ -84,8 +84,9 @@ function ref_session_destroy ($id) {
function ref_session_gc($expire) {
q("DELETE FROM session WHERE expire < %d", dbesc(time()));
- q("OPTIMIZE TABLE session");
- return true;
+ if (! get_config('system','innodb'))
+ q("OPTIMIZE TABLE session");
+ return true;
}
$gc_probability = 50;
diff --git a/include/taxonomy.php b/include/taxonomy.php
index 35605da22..fab31c73d 100644
--- a/include/taxonomy.php
+++ b/include/taxonomy.php
@@ -209,13 +209,35 @@ function tagblock($link,$uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$
if($r) {
$o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
- $o .= '<a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
+ $o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
}
$o .= '</div></div>';
}
return $o;
}
+function catblock($uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = TERM_CATEGORY) {
+ $o = '';
+ $tab = 0;
+
+ $r = tagadelic($uid,$count,$authors,$flags,$restrict,$type);
+
+ if($r) {
+ $c = q("select channel_address from channel where channel_id = %d limit 1",
+ intval($uid)
+ );
+
+ $o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">';
+ foreach($r as $rr) {
+ $o .= '<a href="channel/' . $c[0]['channel_address']. '?f=&cat=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
+ }
+ $o .= '</div></div>';
+ }
+ return $o;
+}
+
+
+
function dir_tagblock($link,$r) {
$o = '';
$tab = 0;
diff --git a/include/widgets.php b/include/widgets.php
index 8905df59a..dcad3eff6 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -330,19 +330,32 @@ function widget_archive($arr) {
$wall = ((array_key_exists('wall', $arr)) ? intval($arr['wall']) : 0);
$style = ((array_key_exists('style', $arr)) ? $arr['style'] : 'select');
+ $showend = ((get_pconfig($uid,'system','archive_show_end_date')) ? true : false);
+ $mindate = get_pconfig($uid,'system','archive_mindate');
+ $visible_years = get_pconfig($uid,'system','archive_visible_years');
+ if(! $visible_years)
+ $visible_years = 5;
+
+
$url = z_root() . '/' . $a->cmd;
- $ret = list_post_dates($uid,$wall);
+ $ret = list_post_dates($uid,$wall,$mindate);
if(! count($ret))
return '';
+ $cutoff_year = intval(datetime_convert('',date_default_timezone_get(),'now','Y')) - $visible_years;
+ $cutoff = ((array_key_exists($cutoff_year,$ret))? true : false);
+
$o = replace_macros(get_markup_template('posted_date_widget.tpl'),array(
'$title' => t('Archives'),
- '$size' => ((count($ret) > 6) ? 6 : count($ret)),
+ '$size' => $visible_years,
+ '$cutoff_year' => $cutoff_year,
+ '$cutoff' => $cutoff,
'$url' => $url,
'$style' => $style,
+ '$showend' => $showend,
'$dates' => $ret
));
return $o;
@@ -387,6 +400,17 @@ function widget_tagcloud_wall($arr) {
return tagblock('search',$a->profile['profile_uid'],$limit,$a->profile['channel_hash'],ITEM_WALL);
return '';
}
+function widget_catcloud_wall($arr) {
+ $a = get_app();
+ if((! $a->profile['profile_uid']) || (! $a->profile['channel_hash']))
+ return '';
+ if(! perm_is_allowed($a->profile['profile_uid'],get_observer_hash(),'view_stream'))
+ return '';
+
+ $limit = ((array_key_exists('limit',$arr)) ? intval($arr['limit']) : 50);
+ return catblock($a->profile['profile_uid'],$limit,$a->profile['channel_hash'],ITEM_WALL);
+ return '';
+}
function widget_affinity($arr) {
@@ -430,6 +454,8 @@ function widget_settings_menu($arr) {
// Retrieve the 'self' address book entry for use in the auto-permissions link
+ $role = get_pconfig(local_user(),'system','permissions_role');
+
$abk = q("select abook_id from abook where abook_channel = %d and ( abook_flags & %d ) limit 1",
intval(local_user()),
intval(ABOOK_FLAG_SELF)
@@ -487,14 +513,15 @@ function widget_settings_menu($arr) {
'selected' => ''
),
- array(
- 'label' => t('Automatic Permissions (Advanced)'),
+ );
+
+ if($role === false || $role === 'custom') {
+ $tabs[] = array(
+ 'label' => t('Connection Default Permissions'),
'url' => $a->get_baseurl(true) . '/connedit/' . $abook_self_id,
'selected' => ''
- ),
-
-
- );
+ );
+ }
if(feature_enabled(local_user(),'premium_channel')) {
$tabs[] = array(
diff --git a/include/zot.php b/include/zot.php
index e96eae10d..bdc1f607f 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -5,7 +5,7 @@ require_once('include/items.php');
require_once('include/hubloc.php');
/**
- * Red implementation of zot protocol.
+ * Red implementation of zot protocol.
*
* https://github.com/friendica/red/wiki/zot
* https://github.com/friendica/red/wiki/Zot---A-High-Level-Overview
@@ -20,8 +20,8 @@ require_once('include/hubloc.php');
* Generates a unique string for use as a zot guid using our DNS-based url, the channel nickname and some entropy.
* The entropy ensures uniqueness against re-installs where the same URL and nickname are chosen.
* NOTE: zot doesn't require this to be unique. Internally we use a whirlpool hash of this guid and the signature
- * of this guid signed with the channel private key. This can be verified and should make the probability of
- * collision of the verified result negligible within the constraints of our immediate universe.
+ * of this guid signed with the channel private key. This can be verified and should make the probability of
+ * collision of the verified result negligible within the constraints of our immediate universe.
*
* @param string channel_nickname = unique nickname of controlling entity
*
@@ -51,7 +51,7 @@ function make_xchan_hash($guid,$guid_sig) {
/**
* @function zot_get_hublocs($hash)
- * Given a zot hash, return all distinct hubs.
+ * Given a zot hash, return all distinct hubs.
* This function is used in building the zot discovery packet
* and therefore should only be used by channels which are defined
* on this hub
@@ -71,7 +71,7 @@ function make_xchan_hash($guid,$guid_sig) {
* hubloc_connect char(255)
* hubloc_sitekey text
* hubloc_updated datetime
- * hubloc_connected datetime
+ * hubloc_connected datetime
*
*/
@@ -85,26 +85,26 @@ function zot_get_hublocs($hash) {
);
return $ret;
}
-
+
/**
*
* @function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null)
* builds a zot notification packet that you can either
- * store in the queue with a message array or call zot_zot to immediately
+ * store in the queue with a message array or call zot_zot to immediately
* zot it to the other side
*
* @param array $channel => sender channel structure
* @param string $type => packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'force_refresh', 'notify', 'auth_check'
* @param array $recipients => envelope information, array ( 'guid' => string, 'guid_sig' => string ); empty for public posts
* @param string $remote_key => optional public site key of target hub used to encrypt entire packet
- * NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others
+ * NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others
* @param string $secret => random string, required for packets which require verification/callback
- * e.g. 'pickup', 'purge', 'notify', 'auth_check'. Packet types 'ping', 'force_refresh', and 'refresh' do not require verification
+ * e.g. 'pickup', 'purge', 'notify', 'auth_check'. Packet types 'ping', 'force_refresh', and 'refresh' do not require verification
*
* @returns string json encoded zot packet
*/
-function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null) {
+function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null, $extra = null) {
$data = array(
'type' => $type,
@@ -129,6 +129,12 @@ function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_
$data['secret_sig'] = base64url_encode(rsa_sign($secret,$channel['channel_prvkey']));
}
+ if($extra) {
+ foreach($extra as $k => $v)
+ $data[$k] = $v;
+ }
+
+
logger('zot_build_packet: ' . print_r($data,true), LOGGER_DATA);
// Hush-hush ultra top-secret mode
@@ -433,15 +439,15 @@ function zot_refresh($them,$channel = null, $force = false) {
}
}
else {
- $default_perms = 0;
- // look for default permissions to apply in return - e.g. auto-friend
- $z = q("select * from abook where abook_channel = %d and (abook_flags & %d) limit 1",
- intval($channel['channel_id']),
- intval(ABOOK_FLAG_SELF)
- );
-
- if($z)
- $default_perms = intval($z[0]['abook_my_perms']);
+ $role = get_pconfig($channel['channel_id'],'system','permissions_role');
+ if($role) {
+ $xx = get_role_perms($role);
+ if($xx['perms_auto'])
+ $default_perms = $xx['perms_accept'];
+ }
+ if(! $default_perms)
+ $default_perms = intval(get_pconfig($channel['channel_id'],'system','autoperms'));
+
// Keep original perms to check if we need to notify them
$previous_perms = get_all_perms($channel['channel_id'],$x['hash']);
@@ -1065,7 +1071,7 @@ function zot_import($arr, $sender_url) {
if(array_key_exists('iv',$i['notify'])) {
$i['notify'] = json_decode(crypto_unencapsulate($i['notify'],get_config('system','prvkey')),true);
- }
+ }
logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA);
@@ -1075,6 +1081,9 @@ function zot_import($arr, $sender_url) {
continue;
}
+ $message_request = ((array_key_exists('message_id',$i['notify'])) ? true : false);
+ if($message_request)
+ logger('processing message request');
$i['notify']['sender']['hash'] = make_xchan_hash($i['notify']['sender']['guid'],$i['notify']['sender']['guid_sig']);
$deliveries = null;
@@ -1098,7 +1107,7 @@ function zot_import($arr, $sender_url) {
// It's a specifically targetted post. If we were sent a public_scope hint (likely),
// get rid of it so that it doesn't get stored and cause trouble.
- if(array_key_exists('message',$i) && array_key_exists('public_scope',$i['message']))
+ if(($i) && is_array($i) && array_key_exists('message',$i) && is_array($i['message']) && array_key_exists('public_scope',$i['message']))
unset($i['message']['public_scope']);
$deliveries = $r;
@@ -1176,7 +1185,7 @@ function zot_import($arr, $sender_url) {
logger('Activity recipients: ' . print_r($deliveries,true), LOGGER_DATA);
$relay = ((array_key_exists('flags',$i['message']) && in_array('relay',$i['message']['flags'])) ? true : false);
- $result = process_delivery($i['notify']['sender'],$arr,$deliveries,$relay);
+ $result = process_delivery($i['notify']['sender'],$arr,$deliveries,$relay,false,$message_request);
}
elseif($i['message']['type'] === 'mail') {
@@ -1373,7 +1382,7 @@ function allowed_public_recips($msg) {
}
-function process_delivery($sender,$arr,$deliveries,$relay,$public = false) {
+function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$request = false) {
$result = array();
@@ -1436,6 +1445,25 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false) {
);
if(! $r) {
$result[] = array($d['hash'],'comment parent not found',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
+
+ // We don't seem to have a copy of this conversation or at least the parent
+ // - so request a copy of the entire conversation to date.
+ // Don't do this if it's a relay post as we're the ones who are supposed to
+ // have the copy and we don't want the request to loop.
+ // Also don't do this if this comment came from a conversation request packet.
+ // It's possible that comments are allowed but posting isn't and that could
+ // cause a conversation fetch loop. We can detect these packets since they are
+ // delivered via a 'notify' packet type that has a message_id element in the
+ // initial zot packet (just like the corresponding 'request' packet type which
+ // makes the request).
+ // We'll also check the send_stream permission - because if it isn't allowed,
+ // the top level post is unlikely to be imported and
+ // this is just an exercise in futility.
+
+ if((! $relay) && (! $request) && (! $public)
+ && perm_is_allowed($channel['channel_id'],$sender['hash'],'send_stream')) {
+ proc_run('php', 'include/notifier.php', 'request', $channel['channel_id'], $sender['hash'], $arr['parent_mid']);
+ }
continue;
}
if($relay) {
@@ -2432,8 +2460,8 @@ 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');
+ $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']) {
@@ -2519,7 +2547,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
continue;
}
$j = json_decode($f['body'],true);
- if(! ($j['success'] && $j['guid'])) {
+ if(! ($j['success'] && $j['guid'])) {
logger('process_channel_sync_delivery: probe failed.');
continue;
}
@@ -2618,8 +2646,8 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
intval($channel['channel_id']),
intval($cl['visible']),
intval($cl['deleted']),
- dbesc($cl['name'])
- );
+ dbesc($cl['name'])
+ );
}
// now look for any collections locally which weren't in the list we just received.
@@ -2793,3 +2821,110 @@ function import_author_zot($x) {
return false;
}
+
+/**
+ * @function zot_process_message_request($data)
+ * If a site receives a comment to a post but finds they have no parent to attach it with, they
+ * may send a 'request' packet containing the message_id of the missing parent. This is the handler
+ * for that packet. We will create a message_list array of the entire conversation starting with
+ * the missing parent and invoke delivery to the sender of the packet.
+ *
+ * include/deliver.php (for local delivery) and mod/post.php (for web delivery) detect the existence of
+ * this 'message_list' at the destination and split it into individual messages which are
+ * processed/delivered in order.
+ *
+ * Called from mod/post.php
+ */
+
+
+function zot_process_message_request($data) {
+ $ret = array('success' => false);
+
+ if(! $data['message_id']) {
+ $ret['message'] = 'no message_id';
+ logger('no message_id');
+ return $ret;
+ }
+
+ $sender = $data['sender'];
+ $sender_hash = make_xchan_hash($sender['guid'],$sender['guid_sig']);
+
+ /*
+ * Find the local channel in charge of this post (the first and only recipient of the request packet)
+ */
+
+ $arr = $data['recipients'][0];
+ $recip_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']);
+ $c = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_hash = '%s' limit 1",
+ dbesc($recip_hash)
+ );
+ if(! $c) {
+ logger('recipient channel not found.');
+ $ret['message'] .= 'recipient not found.' . EOL;
+ return $ret;
+ }
+
+ /*
+ * fetch the requested conversation
+ */
+
+ $messages = zot_feed($c[0]['channel_id'],$sender_hash,array('message_id' => $data['message_id']));
+
+ if($messages) {
+ $env_recips = null;
+
+ $r = q("select hubloc_guid, hubloc_url, hubloc_sitekey, hubloc_network, hubloc_flags, hubloc_callback, hubloc_host
+ from hubloc where hubloc_hash = '%s' and not (hubloc_flags & %d)
+ and not (hubloc_status & %d) group by hubloc_sitekey",
+ dbesc($sender_hash),
+ intval(HUBLOC_FLAGS_DELETED),
+ intval(HUBLOC_OFFLINE)
+ );
+ if(! $r) {
+ logger('no hubs');
+ return $ret;
+ }
+ $hubs = $r;
+ $hublist = array();
+ $keys = array();
+
+ $private = ((array_key_exists('flags',$messages[0]) && in_array('private',$messages[0]['flags'])) ? true : false);
+ if($private)
+ $env_recips = array('guid' => $sender['guid'],'guid_sig' => $sender['guid_sig'],'hash' => $sender_hash);
+
+ $data_packet = json_encode(array('message_list' => $messages));
+
+ foreach($hubs as $hub) {
+ $hash = random_string();
+
+ /*
+ * create a notify packet and drop the actual message packet in the queue for pickup
+ */
+
+ $n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash,array('message_id' => $data['message_id']));
+ q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async,
+ outq_created, outq_updated, outq_notify, outq_msg )
+ values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
+ dbesc($hash),
+ intval($c[0]['channel_account_id']),
+ intval($c[0]['channel_id']),
+ dbesc('zot'),
+ dbesc($hub['hubloc_callback']),
+ intval(1),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ dbesc($n),
+ dbesc($data_packet)
+ );
+
+ /*
+ * invoke delivery to send out the notify packet
+ */
+
+ proc_run('php','include/deliver.php',$hash);
+ }
+
+ }
+ $ret['success'] = true;
+ return $ret;
+}