aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/account.php3
-rw-r--r--include/api.php39
-rw-r--r--include/bb2diaspora.php34
-rw-r--r--include/bbcode.php44
-rw-r--r--include/config.php157
-rwxr-xr-xinclude/dba/dba_mysqli.php18
-rw-r--r--include/help.php150
-rw-r--r--include/import.php30
-rwxr-xr-xinclude/importdoc.php2
-rwxr-xr-xinclude/items.php166
-rw-r--r--include/nav.php19
-rw-r--r--include/network.php5
-rw-r--r--include/notifier.php21
-rw-r--r--include/photos.php44
-rwxr-xr-xinclude/plugin.php57
-rw-r--r--include/text.php35
-rw-r--r--include/zot.php13
17 files changed, 562 insertions, 275 deletions
diff --git a/include/account.php b/include/account.php
index c64197b49..5998609d4 100644
--- a/include/account.php
+++ b/include/account.php
@@ -591,6 +591,7 @@ function service_class_allows($uid, $property, $usage = false) {
if($limit === false)
return true; // No service class set => everything is allowed
+ $limit = engr_units_to_bytes($limit);
if($usage === false) {
// We use negative values for not allowed properties in a subscriber plan
return ((x($limit)) ? (bool) $limit : true);
@@ -627,6 +628,8 @@ function account_service_class_allows($aid, $property, $usage = false) {
if($limit === false)
return true; // No service class is set => everything is allowed
+ $limit = engr_units_to_bytes($limit);
+
if($usage === false) {
// We use negative values for not allowed properties in a subscriber plan
return ((x($limit)) ? (bool) $limit : true);
diff --git a/include/api.php b/include/api.php
index fd644947c..e64c86695 100644
--- a/include/api.php
+++ b/include/api.php
@@ -772,13 +772,15 @@ require_once('include/api_auth.php');
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
$_FILES['userfile'] = $_FILES['media'];
- require_once('mod/wall_attach.php');
- $posted = wall_attach_post($a);
-
- //now that we have the img url in bbcode we can add it to the status and insert the wall item.
+
+ $mod = new Zotlabs\Module\Wall_attach();
+ $mod->post();
+
+
$_REQUEST['body']=$txt."\n\n".$posted;
- require_once('mod/item.php');
- item_post($a);
+
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
// this should output the last post (the one we just posted).
return api_status_show($a,$type);
@@ -871,9 +873,9 @@ require_once('include/api_auth.php');
// upload each image if we have any
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_attach.php');
+ $mod = new Zotlabs\Module\Wall_attach();
App::$data['api_info'] = $user_info;
- $media = wall_attach_post($a);
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n" . $media;
@@ -884,9 +886,9 @@ require_once('include/api_auth.php');
$_FILES['userfile'] = $_FILES['media'];
// upload each image if we have any
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_attach.php');
+ $mod = new Zotlabs\Module\Wall_attach();
App::$data['api_info'] = $user_info;
- $media = wall_attach_post($a);
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n" . $media;
@@ -896,8 +898,8 @@ require_once('include/api_auth.php');
// call out normal post function
- require_once('mod/item.php');
- item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
// this should output the last post (the one we just posted).
return api_status_show($a,$type);
@@ -926,14 +928,14 @@ require_once('include/api_auth.php');
$_FILES['userfile'] = $_FILES['media'];
// upload the image if we have one
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
- require_once('mod/wall_upload.php');
- $media = wall_upload_post($a);
+ $mod = new Zotlabs\Module\Wall_upload();
+ $media = $mod->post();
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n".$media;
}
- require_once('mod/item.php');
- $x = item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $x = $mod->post();
json_return_and_die($x);
}
@@ -1423,9 +1425,8 @@ require_once('include/api_auth.php');
$_REQUEST['profile_uid'] = api_user();
$_REQUEST['type'] = 'wall';
$_REQUEST['api_source'] = true;
-
- require_once('mod/item.php');
- item_post($a);
+ $mod = new Zotlabs\Module\Item();
+ $mod->post();
}
}
else
diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php
index 1ed57bfd4..9167cb5ad 100644
--- a/include/bb2diaspora.php
+++ b/include/bb2diaspora.php
@@ -270,7 +270,14 @@ function bb2dmention_callback($match) {
function bb2diaspora_itemwallwall(&$item) {
+ // We will provide wallwall (embedded author on the Diaspora side) if
+ // 1. It is a wall-to-wall post
+ // 2. A comment arrived which has no Diaspora signature info
+
+
+ $wallwall = false;
$author_exists = true;
+
if(! array_key_exists('author',$item)) {
$author_exists = false;
logger('bb2diaspora_itemwallwall: no author');
@@ -281,11 +288,21 @@ function bb2diaspora_itemwallwall(&$item) {
$item['author'] = $r[0];
}
- 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_DATA);
+ $has_meta = false;
+ if($item['diaspora_meta'] || get_iconfig($item,'diaspora','fields'))
+ $has_meta = true;
+
+ if($item['author_xchan'] != $item['owner_xchan']) {
+ if($item['mid'] == $item['parent_mid'])
+ $wallwall = true;
+ else {
+ if(! $has_meta) {
+ $wallwall = true;
+ }
+ }
}
- 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']) {
+ if(($wallwall) && (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"
@@ -301,7 +318,12 @@ function bb2diaspora_itemwallwall(&$item) {
}
-function bb2diaspora_itembody($item, $force_update = false) {
+function bb2diaspora_itembody($item, $force_update = false, $have_channel = false) {
+
+
+ if(! get_iconfig($item,'diaspora','fields')) {
+ $force_update = true;
+ }
$matches = array();
@@ -339,8 +361,8 @@ function bb2diaspora_itembody($item, $force_update = false) {
}
}
-
- bb2diaspora_itemwallwall($newitem);
+ if(! $have_channel)
+ bb2diaspora_itemwallwall($newitem);
$title = $newitem['title'];
$body = preg_replace('/\#\^http/i', 'http', $newitem['body']);
diff --git a/include/bbcode.php b/include/bbcode.php
index 78a2759c1..b8cd23f59 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -330,8 +330,19 @@ function bb_map_location($match) {
}
function bb_opentag($match) {
+ $openclose = (($match[2]) ? '<span class="bb-open" title="' . t('Click to open/close') . '">' . $match[1] . '</span>' : t('Click to open/close'));
+ $text = (($match[2]) ? $match[2] : $match[1]);
$rnd = mt_rand();
- return "<br /><div onclick=\"openClose('opendiv-" . $rnd . "');return false;\" class=\"fakelink\">" . $match[1] . "</div><div id=\"opendiv-" . $rnd . "\" style=\"display: none;\">" . $match[2] . "</div>";
+
+ return '<div onclick="openClose(\'opendiv-' . $rnd . '\'); return false;" class="fakelink">' . $openclose . '</div><div id="opendiv-' . $rnd . '" style="display: none;">' . $text . '</div>';
+}
+
+function bb_spoilertag($match) {
+ $openclose = (($match[2]) ? '<span class="bb-spoiler" title="' . t('Click to open/close') . '">' . $match[1] . ' ' . t('spoiler') . '</span>' : t('Click to open/close'));
+ $text = (($match[2]) ? $match[2] : $match[1]);
+ $rnd = mt_rand();
+
+ return '<div onclick="openClose(\'opendiv-' . $rnd . '\'); return false;" class="fakelink">' . $openclose . '</div><blockquote id="opendiv-' . $rnd . '" style="display: none;">' . $text . '</blockquote>';
}
/**
@@ -748,33 +759,34 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = preg_replace("/\[code\](.*?)\[\/code\]/ism", "$CodeLayout", $Text);
}
- // Declare the format for [spoiler] layout
- $SpoilerLayout = '<blockquote class="spoiler">$1</blockquote>';
-
// Check for [spoiler] text
- // handle nested quotes
$endlessloop = 0;
- while ((strpos($Text, "[/spoiler]") !== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20))
- $Text = preg_replace("/\[spoiler\](.*?)\[\/spoiler\]/ism", "$SpoilerLayout", $Text);
+ while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20)) {
+ $Text = preg_replace_callback("/\[spoiler\](.*?)\[\/spoiler\]/ism", 'bb_spoilertag', $Text);
+ }
// Check for [spoiler=Author] text
-
- $t_wrote = t('$1 spoiler');
-
- // handle nested quotes
$endlessloop = 0;
- while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler=") !== false) and (++$endlessloop < 20))
- $Text = preg_replace("/\[spoiler=[\"\']*(.*?)[\"\']*\](.*?)\[\/spoiler\]/ism",
- "<br /><strong class=".'"spoiler"'.">" . $t_wrote . "</strong><blockquote class=".'"spoiler"'.">$2</blockquote>",
- $Text);
+ while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler=") !== false) and (++$endlessloop < 20)) {
+ $Text = preg_replace_callback("/\[spoiler=(.*?)\](.*?)\[\/spoiler\]/ism", 'bb_spoilertag', $Text);
+ }
+ // Check for [open] text
+ $endlessloop = 0;
+ while ((strpos($Text, "[/open]")!== false) and (strpos($Text, "[open]") !== false) and (++$endlessloop < 20)) {
+ $Text = preg_replace_callback("/\[open\](.*?)\[\/open\]/ism", 'bb_opentag', $Text);
+ }
+ // Check for [open=Title] text
$endlessloop = 0;
while ((strpos($Text, "[/open]")!== false) and (strpos($Text, "[open=") !== false) and (++$endlessloop < 20)) {
$Text = preg_replace_callback("/\[open=(.*?)\](.*?)\[\/open\]/ism", 'bb_opentag', $Text);
}
+
+
+
// Declare the format for [quote] layout
$QuoteLayout = '<blockquote>$1</blockquote>';
@@ -792,7 +804,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$endlessloop = 0;
while ((strpos($Text, "[/quote]")!== false) and (strpos($Text, "[quote=") !== false) and (++$endlessloop < 20))
$Text = preg_replace("/\[quote=[\"\']*(.*?)[\"\']*\](.*?)\[\/quote\]/ism",
- "<br /><strong class=".'"author"'.">" . $t_wrote . "</strong><blockquote>$2</blockquote>",
+ "<span class=".'"bb-quote"'.">" . $t_wrote . "</span><blockquote>$2</blockquote>",
$Text);
// Images
diff --git a/include/config.php b/include/config.php
index 712b4ca11..12768f4da 100644
--- a/include/config.php
+++ b/include/config.php
@@ -625,3 +625,160 @@ function del_abconfig($chash,$xhash,$family,$key) {
return $r;
}
+
+
+
+
+
+
+function get_iconfig(&$item, $family, $key) {
+
+ $is_item = false;
+ if(is_array($item)) {
+ $is_item = true;
+ if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
+ $item['iconfig'] = array();
+
+ if(array_key_exists('item_id',$item))
+ $iid = $item['item_id'];
+ else
+ $iid = $item['id'];
+ }
+ elseif(intval($item))
+ $iid = $item;
+
+ if(! $iid)
+ return false;
+
+ if(is_array($item) && array_key_exists('iconfig',$item) && is_array($item['iconfig'])) {
+ foreach($item['iconfig'] as $c) {
+ if($c['iid'] == $iid && $c['cat'] == $family && $c['k'] == $key)
+ return $c['v'];
+ }
+ }
+
+ $r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
+ intval($iid),
+ dbesc($family),
+ dbesc($key)
+ );
+ if($r) {
+ $r[0]['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
+ if($is_item)
+ $item['iconfig'][] = $r[0];
+ return $r[0]['v'];
+ }
+ return false;
+
+}
+
+/**
+ * set_iconfig(&$item, $family, $key, $value, $sharing = false);
+ *
+ * $item - item array or item id. If passed an array the iconfig meta information is
+ * added to the item structure (which will need to be saved with item_store eventually).
+ * If passed an id, the DB is updated, but may not be federated and/or cloned.
+ * $family - namespace of meta variable
+ * $key - key of meta variable
+ * $value - value of meta variable
+ * $sharing - boolean (default false); if true the meta information is propagated with the item
+ * to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
+ * If the meta information is added after delivery and you wish it to be shared, it may be necessary to
+ * alter the item edited timestamp and invoke the delivery process on the updated item. The edited
+ * timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
+ */
+
+
+function set_iconfig(&$item, $family, $key, $value, $sharing = false) {
+
+ $dbvalue = ((is_array($value)) ? serialize($value) : $value);
+ $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
+
+ $is_item = false;
+ $idx = null;
+
+ if(is_array($item)) {
+ $is_item = true;
+ if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
+ $item['iconfig'] = array();
+ elseif($item['iconfig']) {
+ for($x = 0; $x < count($item['iconfig']); $x ++) {
+ if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
+ $idx = $x;
+ }
+ }
+ }
+ $entry = array('cat' => $family, 'k' => $key, 'v' => $value, 'sharing' => $sharing);
+
+ if(is_null($idx))
+ $item['iconfig'][] = $entry;
+ else
+ $item['iconfig'][$idx] = $entry;
+ return $value;
+ }
+
+ if(intval($item))
+ $iid = intval($item);
+
+ if(! $iid)
+ return false;
+
+ if(get_iconfig($item, $family, $key) === false) {
+ $r = q("insert into iconfig( iid, cat, k, v, sharing ) values ( %d, '%s', '%s', '%s', %d ) ",
+ intval($iid),
+ dbesc($family),
+ dbesc($key),
+ dbesc($dbvalue),
+ intval($sharing)
+ );
+ }
+ else {
+ $r = q("update iconfig set v = '%s', sharing = %d where iid = %d and cat = '%s' and k = '%s' ",
+ dbesc($dbvalue),
+ intval($sharing),
+ intval($iid),
+ dbesc($family),
+ dbesc($key)
+ );
+ }
+
+ if(! $r)
+ return false;
+
+ return $value;
+}
+
+
+
+function del_iconfig(&$item, $family, $key) {
+
+
+ $is_item = false;
+ $idx = null;
+
+ if(is_array($item)) {
+ $is_item = true;
+ if(is_array($item['iconfig'])) {
+ for($x = 0; $x < count($item['iconfig']); $x ++) {
+ if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
+ unset($item['iconfig'][$x]);
+ }
+ }
+ }
+ return true;
+ }
+
+ if(intval($item))
+ $iid = intval($item);
+
+ if(! $iid)
+ return false;
+
+ return q("delete from iconfig where iid = %d and cat = '%s' and k = '%s' ",
+ intval($iid),
+ dbesc($family),
+ dbesc($key)
+ );
+
+}
+
diff --git a/include/dba/dba_mysqli.php b/include/dba/dba_mysqli.php
index 6986d4586..57a7559a1 100755
--- a/include/dba/dba_mysqli.php
+++ b/include/dba/dba_mysqli.php
@@ -4,20 +4,26 @@ require_once('include/dba/dba_driver.php');
class dba_mysqli extends dba_driver {
- function connect($server, $port, $user,$pass,$db) {
+ function connect($server,$port,$user,$pass,$db) {
if($port)
$this->db = new mysqli($server,$user,$pass,$db, $port);
else
$this->db = new mysqli($server,$user,$pass,$db);
- if(! mysqli_connect_errno()) {
- $this->connected = true;
+ if($this->db->connect_error) {
+ $this->connected = false;
+ $this->error = $this->db->connect_error;
+
+ if(file_exists('dbfail.out')) {
+ file_put_contents('dbfail.out', datetime_convert() . "\nConnect: " . $this->error . "\n", FILE_APPEND);
+ }
+
+ return false;
}
- if($this->connected) {
+ else {
+ $this->connected = true;
return true;
}
- $this->error = $this->db->connect_error;
- return false;
}
function q($sql) {
diff --git a/include/help.php b/include/help.php
new file mode 100644
index 000000000..13473164d
--- /dev/null
+++ b/include/help.php
@@ -0,0 +1,150 @@
+<?php
+
+function load_doc_file($s) {
+ $lang = \App::$language;
+ if(! isset($lang))
+ $lang = 'en';
+ $b = basename($s);
+ $d = dirname($s);
+
+ $c = find_doc_file("$d/$lang/$b");
+ if($c)
+ return $c;
+ $c = find_doc_file($s);
+ if($c)
+ return $c;
+ return '';
+}
+
+function find_doc_file($s) {
+ if(file_exists($s))
+ return file_get_contents($s);
+ return '';
+}
+
+function search_doc_files($s) {
+
+ $a = get_app();
+
+ $itemspage = get_pconfig(local_channel(),'system','itemspage');
+ \App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
+ $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
+
+ $regexop = db_getfunc('REGEXP');
+
+ $r = q("select item_id.sid, item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and
+ body $regexop '%s' and item_type = %d $pager_sql",
+ dbesc($s),
+ intval(ITEM_TYPE_DOC)
+ );
+
+ $r = fetch_post_tags($r,true);
+
+ for($x = 0; $x < count($r); $x ++) {
+
+ $r[$x]['text'] = $r[$x]['body'];
+
+ $r[$x]['rank'] = 0;
+ if($r[$x]['term']) {
+ foreach($r[$x]['term'] as $t) {
+ if(stristr($t['term'],$s)) {
+ $r[$x]['rank'] ++;
+ }
+ }
+ }
+ if(stristr($r[$x]['sid'],$s))
+ $r[$x]['rank'] ++;
+ $r[$x]['rank'] += substr_count(strtolower($r[$x]['text']),strtolower($s));
+ // bias the results to the observer's native language
+ if($r[$x]['lang'] === \App::$language)
+ $r[$x]['rank'] = $r[$x]['rank'] + 10;
+
+ }
+ usort($r,'doc_rank_sort');
+ return $r;
+}
+
+
+function doc_rank_sort($s1,$s2) {
+ if($s1['rank'] == $s2['rank'])
+ return 0;
+ return (($s1['rank'] < $s2['rank']) ? 1 : (-1));
+}
+
+
+function load_context_help() {
+
+ $path = App::$cmd;
+ $args = App::$argv;
+ $lang = App::$language;
+
+ if(! isset($lang) || !is_dir('doc/context/' . $lang . '/')) {
+ $lang = 'en';
+ }
+ while($path) {
+ $context_help = load_doc_file('doc/context/' . $lang . '/' . $path . '/help.html');
+ if(!$context_help) {
+ // Fallback to English if the translation is absent
+ $context_help = load_doc_file('doc/context/en/' . $path . '/help.html');
+ }
+ if($context_help)
+ break;
+ array_pop($args);
+ $path = implode($args,'/');
+ }
+
+ return $context_help;
+}
+
+
+function store_doc_file($s) {
+
+ if(is_dir($s))
+ return;
+
+ $item = array();
+ $sys = get_sys_channel();
+
+ $item['aid'] = 0;
+ $item['uid'] = $sys['channel_id'];
+
+
+ if(strpos($s,'.md'))
+ $mimetype = 'text/markdown';
+ elseif(strpos($s,'.html'))
+ $mimetype = 'text/html';
+ else
+ $mimetype = 'text/bbcode';
+
+ require_once('include/html2plain.php');
+
+ $item['body'] = html2plain(prepare_text(file_get_contents($s),$mimetype, true));
+ $item['mimetype'] = 'text/plain';
+
+ $item['plink'] = z_root() . '/' . str_replace('doc','help',$s);
+ $item['owner_xchan'] = $item['author_xchan'] = $sys['channel_hash'];
+ $item['item_type'] = ITEM_TYPE_DOC;
+
+ $r = q("select item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and
+ sid = '%s' and item_type = %d limit 1",
+ dbesc($s),
+ intval(ITEM_TYPE_DOC)
+ );
+
+ if($r) {
+ $item['id'] = $r[0]['id'];
+ $item['mid'] = $item['parent_mid'] = $r[0]['mid'];
+ $x = item_store_update($item);
+ }
+ else {
+ $item['mid'] = $item['parent_mid'] = item_message_id();
+ $x = item_store($item);
+ }
+
+ if($x['success']) {
+ update_remote_id($sys,$x['item_id'],ITEM_TYPE_DOC,$s,'docfile',0,$item['mid']);
+ }
+
+
+}
+
diff --git a/include/import.php b/include/import.php
index 3b5c8508c..f6e62f9e0 100644
--- a/include/import.php
+++ b/include/import.php
@@ -482,7 +482,7 @@ function sync_chatrooms($channel,$chatrooms) {
-function import_items($channel,$items) {
+function import_items($channel,$items,$sync = false) {
if($channel && $items) {
$allow_code = false;
@@ -499,6 +499,7 @@ function import_items($channel,$items) {
$deliver = false; // Don't deliver any messages or notifications when importing
foreach($items as $i) {
+ $item_result = false;
$item = get_item_elements($i,$allow_code);
if(! $item)
continue;
@@ -511,7 +512,13 @@ function import_items($channel,$items) {
if($item['edited'] > $r[0]['edited']) {
$item['id'] = $r[0]['id'];
$item['uid'] = $channel['channel_id'];
- item_store_update($item,$allow_code,$deliver);
+ $item_result = item_store_update($item,$allow_code,$deliver);
+ if($sync && $item['item_wall']) {
+ // deliver singletons if we have any
+ if($item_result && $item_result['success']) {
+ proc_run('php','include/notifier.php','single_activity',$item_result['item_id']);
+ }
+ }
continue;
}
}
@@ -520,13 +527,19 @@ function import_items($channel,$items) {
$item['uid'] = $channel['channel_id'];
$item_result = item_store($item,$allow_code,$deliver);
}
+ if($sync && $item['item_wall']) {
+ // deliver singletons if we have any
+ if($item_result && $item_result['success']) {
+ proc_run('php','include/notifier.php','single_activity',$item_result['item_id']);
+ }
+ }
}
}
}
function sync_items($channel,$items) {
- import_items($channel,$items);
+ import_items($channel,$items,true);
}
@@ -839,7 +852,7 @@ function import_conv($channel,$convs) {
-function import_mail($channel,$mails) {
+function import_mail($channel,$mails,$sync = false) {
if($channel && $mails) {
foreach($mails as $mail) {
if(array_key_exists('flags',$mail) && in_array('deleted',$mail['flags'])) {
@@ -863,12 +876,17 @@ function import_mail($channel,$mails) {
$m['aid'] = $channel['channel_account_id'];
$m['uid'] = $channel['channel_id'];
- mail_store($m);
+ $mail_id = mail_store($m);
+ if($sync && $mail_id) {
+ proc_run('php','include/notifier.php','single_mail',$mail_id);
+ }
}
}
}
-
+function sync_mail($channel,$mails) {
+ import_mail($channel,$mails,true);
+}
function sync_files($channel,$files) {
diff --git a/include/importdoc.php b/include/importdoc.php
index 10f868697..90dfb2fc4 100755
--- a/include/importdoc.php
+++ b/include/importdoc.php
@@ -9,7 +9,7 @@ function importdoc_run($argv, $argc){
cli_startup();
- require_once('mod/help.php');
+ require_once('include/help.php');
update_docs_dir('doc/*');
diff --git a/include/items.php b/include/items.php
index 95822c0ba..2720dd841 100755
--- a/include/items.php
+++ b/include/items.php
@@ -555,8 +555,8 @@ function get_public_feed($channel, $params) {
// put a sane lower limit on feed requests if not specified
- if($params['begin'] === NULL_DATE)
- $params['begin'] = datetime_convert('UTC','UTC','now - 1 month');
+// if($params['begin'] === NULL_DATE)
+// $params['begin'] = datetime_convert('UTC','UTC','now - 1 month');
switch($params['type']) {
case 'json':
@@ -4235,10 +4235,10 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
$obj = ((is_array($item['obj'])) ? $item['object'] : json_decode($item['object'],true));
$o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n";
- $o .= '<summary>' . xmlify(bbcode($obj['title'])) . '</summary>' . "\r\n";
+ $o .= '<summary xmlns="urn:ietf:params:xml:ns:xcal">' . xmlify(bbcode($obj['title'])) . '</summary>' . "\r\n";
$o .= '<dtstart xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['start'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtstart>' . "\r\n";
$o .= '<dtend xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC','UTC', $obj['finish'],'Ymd\\THis' . (($obj['adjust']) ? '\\Z' : '')) . '</dtend>' . "\r\n";
- $o .= '<location>' . bbcode($obj['location']) . '</location>' . "\r\n";
+ $o .= '<location xmlns="urn:ietf:params:xml:ns:xcal">' . xmlify(bbcode($obj['location'])) . '</location>' . "\r\n";
$o .= '<content type="' . $type . '" >' . xmlify(bbcode($obj['description'])) . '</content>' . "\r\n";
}
else {
@@ -5617,157 +5617,17 @@ function send_profile_photo_activity($channel,$photo,$profile) {
}
+function sync_an_item($channel_id,$item_id) {
-
-
-function get_iconfig(&$item, $family, $key) {
-
- $is_item = false;
- if(is_array($item)) {
- $is_item = true;
- if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
- $item['iconfig'] = array();
-
- if(array_key_exists('item_id',$item))
- $iid = $item['item_id'];
- else
- $iid = $item['id'];
- }
- elseif(intval($item))
- $iid = $item;
-
- if(! $iid)
- return false;
-
- if(is_array($item) && array_key_exists('iconfig',$item) && is_array($item['iconfig'])) {
- foreach($item['iconfig'] as $c) {
- if($c['iid'] == $iid && $c['cat'] == $family && $c['k'] == $key)
- return $c['v'];
- }
- }
-
- $r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
- intval($iid),
- dbesc($family),
- dbesc($key)
+ $r = q("select * from item where id = %d",
+ intval($item_id)
);
if($r) {
- $r[0]['v'] = ((preg_match('|^a:[0-9]+:{.*}$|s',$r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
- if($is_item)
- $item['iconfig'][] = $r[0];
- return $r[0]['v'];
- }
- return false;
-
-}
-
-/**
- * set_iconfig(&$item, $family, $key, $value, $sharing = false);
- *
- * $item - item array or item id. If passed an array the iconfig meta information is
- * added to the item structure (which will need to be saved with item_store eventually).
- * If passed an id, the DB is updated, but may not be federated and/or cloned.
- * $family - namespace of meta variable
- * $key - key of meta variable
- * $value - value of meta variable
- * $sharing - boolean (default false); if true the meta information is propagated with the item
- * to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
- * If the meta information is added after delivery and you wish it to be shared, it may be necessary to
- * alter the item edited timestamp and invoke the delivery process on the updated item. The edited
- * timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
- */
-
-
-function set_iconfig(&$item, $family, $key, $value, $sharing = false) {
-
- $dbvalue = ((is_array($value)) ? serialize($value) : $value);
- $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
-
- $is_item = false;
- $idx = null;
-
- if(is_array($item)) {
- $is_item = true;
- if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
- $item['iconfig'] = array();
- elseif($item['iconfig']) {
- for($x = 0; $x < count($item['iconfig']); $x ++) {
- if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
- $idx = $x;
- }
- }
- }
- $entry = array('cat' => $family, 'k' => $key, 'v' => $value, 'sharing' => $sharing);
-
- if(is_null($idx))
- $item['iconfig'][] = $entry;
- else
- $item['iconfig'][$idx] = $entry;
- return $value;
- }
-
- if(intval($item))
- $iid = intval($item);
-
- if(! $iid)
- return false;
-
- if(get_iconfig($item, $family, $key) === false) {
- $r = q("insert into iconfig( iid, cat, k, v, sharing ) values ( %d, '%s', '%s', '%s', %d ) ",
- intval($iid),
- dbesc($family),
- dbesc($key),
- dbesc($dbvalue),
- intval($sharing)
- );
- }
- else {
- $r = q("update iconfig set v = '%s', sharing = %d where iid = %d and cat = '%s' and k = '%s' ",
- dbesc($dbvalue),
- intval($sharing),
- intval($iid),
- dbesc($family),
- dbesc($key)
+ xchan_query($r);
+ $sync_item = fetch_post_tags($r);
+ $rid = q("select * from item_id where iid = %d",
+ intval($item_id)
);
+ build_sync_packet($channel_d,array('item' => array(encode_item($sync_item[0],true)),'item_id' => $rid));
}
-
- if(! $r)
- return false;
-
- return $value;
-}
-
-
-
-function del_iconfig(&$item, $family, $key) {
-
-
- $is_item = false;
- $idx = null;
-
- if(is_array($item)) {
- $is_item = true;
- if(is_array($item['iconfig'])) {
- for($x = 0; $x < count($item['iconfig']); $x ++) {
- if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
- unset($item['iconfig'][$x]);
- }
- }
- }
- return true;
- }
-
- if(intval($item))
- $iid = intval($item);
-
- if(! $iid)
- return false;
-
- return q("delete from iconfig where iid = %d and cat = '%s' and k = '%s' ",
- intval($iid),
- dbesc($family),
- dbesc($key)
- );
-
-}
-
+} \ No newline at end of file
diff --git a/include/nav.php b/include/nav.php
index 541ab3aed..70faec598 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -143,16 +143,20 @@ EOT;
if((App::$module != 'home') && (! (local_channel())))
$nav['home'] = array($homelink, t('Home'), "", t('Home Page'),'home_nav_btn');
-
if((App::$config['system']['register_policy'] == REGISTER_OPEN) && (! local_channel()) && (! remote_channel()))
$nav['register'] = array('register',t('Register'), "", t('Create an account'),'register_nav_btn');
- $help_url = z_root() . '/help?f=&cmd=' . App::$cmd;
-
if(! get_config('system','hide_help')) {
- require_once('mod/help.php');
- $context_help = load_context_help();
- $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation'),'help_nav_btn',$context_help);
+ $help_url = z_root() . '/help?f=&cmd=' . App::$cmd;
+ $context_help = '';
+ $enable_context_help = ((intval(get_config('system','enable_context_help')) === 1 || get_config('system','enable_context_help') === false) ? true : false);
+ if($enable_context_help === true) {
+ require_once('include/help.php');
+ $context_help = load_context_help();
+ //point directly to /help if $context_help is empty - this can be removed once we have context help for all modules
+ $enable_context_help = (($context_help) ? true : false);
+ }
+ $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation'), 'help_nav_btn', $context_help, $enable_context_help);
}
if(! UNO)
@@ -160,7 +164,6 @@ EOT;
$nav['search'] = array('search', t('Search'), "", t('Search site @name, #tag, ?docs, content'));
-
$nav['directory'] = array('directory', t('Directory'), "", t('Channel Directory'),'directory_nav_btn');
@@ -237,7 +240,7 @@ $powered_by = '';
$tpl = get_markup_template('nav.tpl');
App::$page['nav'] .= replace_macros($tpl, array(
- '$baseurl' => z_root(),
+ '$baseurl' => z_root(),
'$sitelocation' => $sitelocation,
'$nav' => $x['nav'],
'$banner' => $banner,
diff --git a/include/network.php b/include/network.php
index ec255581d..395641b73 100644
--- a/include/network.php
+++ b/include/network.php
@@ -2114,8 +2114,9 @@ function check_channelallowed($hash) {
return $retvalue;
}
-function deliverable_singleton($xchan) {
- $r = q("select abook_instance from abook where abook_xchan = '%s' limit 1",
+function deliverable_singleton($channel_id,$xchan) {
+ $r = q("select abook_instance from abook where abook_channel = %d and abook_xchan = '%s' limit 1",
+ intval($channel_id),
dbesc($xchan['xchan_hash'])
);
if($r) {
diff --git a/include/notifier.php b/include/notifier.php
index 628847d54..f0c6d7275 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -118,7 +118,7 @@ function notifier_run($argv, $argc){
$normal_mode = true;
$packet_type = 'undefined';
- if($cmd === 'mail') {
+ if($cmd === 'mail' || $cmd === 'single_mail') {
$normal_mode = false;
$mail = true;
$private = true;
@@ -280,7 +280,7 @@ function notifier_run($argv, $argc){
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
return;
}
- if(intval($target_item['item_unpublished']) || intval($target_item['item_delayed'])) {
+ if(intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) || intval($target_item['item_hidden'])) {
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
return;
}
@@ -450,11 +450,11 @@ function notifier_run($argv, $argc){
'target_item' => $target_item,
'top_level_post' => $top_level_post,
'private' => $private,
- 'followup' => $followup,
'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink,
'cmd' => $cmd,
'mail' => $mail,
+ 'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
'location' => $location,
'request' => $request,
'normal_mode' => $normal_mode,
@@ -547,11 +547,11 @@ function notifier_run($argv, $argc){
'hub' => $hub,
'top_level_post' => $top_level_post,
'private' => $private,
- 'followup' => $followup,
'relay_to_owner' => $relay_to_owner,
'uplink' => $uplink,
'cmd' => $cmd,
'mail' => $mail,
+ 'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false),
'location' => $location,
'request' => $request,
'normal_mode' => $normal_mode,
@@ -570,6 +570,19 @@ function notifier_run($argv, $argc){
}
+ // singleton deliveries by definition 'not got zot'.
+ // Single deliveries are other federated networks (plugins) and we're essentially
+ // delivering only to those that have this site url in their abook_instance
+ // and only from within a sync operation. This means if you post from a clone,
+ // and a connection is connected to one of your other clones; assuming that hub
+ // is running it will receive a sync packet. On receipt of this sync packet it
+ // will invoke a delivery to those connections which are connected to just that
+ // hub instance.
+
+ if($cmd === 'single_mail' || $cmd === 'single_activity') {
+ continue;
+ }
+
// default: zot protocol
$hash = random_string();
diff --git a/include/photos.php b/include/photos.php
index 943d7d503..73a29d8eb 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -131,7 +131,7 @@ function photo_upload($channel, $observer, $args) {
intval($account_id)
);
- $limit = service_class_fetch($channel_id,'photo_upload_limit');
+ $limit = engr_units_to_bytes(service_class_fetch($channel_id,'photo_upload_limit'));
if (($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) {
$ret['message'] = upgrade_message();
@@ -296,7 +296,7 @@ function photo_upload($channel, $observer, $args) {
$photo_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' . t('a new photo') . '[/zrl]';
- $album_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album) . ']' . $album . '[/zrl]';
+ $album_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album) . ']' . ((strlen($album)) ? $album : '/') . '[/zrl]';
$activity_format = sprintf(t('%1$s posted %2$s to %3$s','photo_upload'), $author_link, $photo_link, $album_link);
@@ -706,3 +706,43 @@ function gps2Num($coordPart) {
return floatval($parts[0]) / floatval($parts[1]);
}
+
+function profile_photo_set_profile_perms($profileid = '') {
+
+ $allowcid = '';
+ if (x($profileid)) {
+
+ $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.id = %d OR profile.profile_guid = '%s' LIMIT 1", intval($profileid), dbesc($profileid));
+
+ } else {
+
+ logger('Resetting permissions on default-profile-photo for user'.local_channel());
+ $r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.uid = %d AND is_default = 1 LIMIT 1", intval(local_channel()) ); //If no profile is given, we update the default profile
+ }
+
+ $profile = $r[0];
+ if(x($profile['id']) && x($profile['photo'])) {
+ preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
+ $resource_id = $resource_id[0];
+
+ if (intval($profile['is_default']) != 1) {
+ $r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1", intval(local_channel()) );
+ $r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ", intval($profile['id'])); //Should not be needed in future. Catches old int-profile-ids.
+ $r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'", dbesc($profile['profile_guid']));
+ $allowcid = "<" . $r0[0]['channel_hash'] . ">";
+ foreach ($r1 as $entry) {
+ $allowcid .= "<" . $entry['abook_xchan'] . ">";
+ }
+ foreach ($r2 as $entry) {
+ $allowcid .= "<" . $entry['abook_xchan'] . ">";
+ }
+
+ q("UPDATE `photo` SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",dbesc($allowcid),dbesc($resource_id),intval($profile['uid']));
+
+ } else {
+ q("UPDATE `photo` SET allow_cid = '' WHERE profile = 1 AND uid = %d",intval($profile['uid'])); //Reset permissions on default profile picture to public
+ }
+ }
+
+ return;
+ }
diff --git a/include/plugin.php b/include/plugin.php
index 8dceb8fb1..8dd67bb0c 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -185,7 +185,7 @@ function register_hook($hook, $file, $function, $priority = 0) {
dbesc($file),
dbesc($function)
);
- if(count($r))
+ if($r)
return true;
$r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`) VALUES ( '%s', '%s', '%s', '%s' )",
@@ -226,9 +226,8 @@ function unregister_hook($hook, $file, $function) {
function load_hooks() {
- $a = get_app();
-// if(! is_array(App::$hooks))
- App::$hooks = array();
+
+ App::$hooks = array();
$r = q("SELECT * FROM hook WHERE true ORDER BY priority DESC");
if($r) {
@@ -236,10 +235,10 @@ function load_hooks() {
if(! array_key_exists($rr['hook'],App::$hooks))
App::$hooks[$rr['hook']] = array();
- App::$hooks[$rr['hook']][] = array($rr['file'],$rr['function']);
+ App::$hooks[$rr['hook']][] = array($rr['file'],$rr['function'],$rr['priority'],$rr['hook_version']);
}
}
-//logger('hooks: ' . print_r(App::$hooks,true));
+ //logger('hooks: ' . print_r(App::$hooks,true));
}
/**
@@ -259,15 +258,15 @@ function load_hooks() {
* @param string $fn
* function name of callback handler
*/
-function insert_hook($hook, $fn) {
- $a = get_app();
+function insert_hook($hook, $fn, $version = 0, $priority = 0) {
+
if(! is_array(App::$hooks))
App::$hooks = array();
if(! array_key_exists($hook, App::$hooks))
App::$hooks[$hook] = array();
- App::$hooks[$hook][] = array('', $fn);
+ App::$hooks[$hook][] = array('', $fn, $priority, $version);
}
/**
@@ -280,22 +279,34 @@ function insert_hook($hook, $fn) {
* @param string|array &$data to transmit to the callback handler
*/
function call_hooks($name, &$data = null) {
- $a = get_app();
-
+ $a = 0;
if((is_array(App::$hooks)) && (array_key_exists($name, App::$hooks))) {
foreach(App::$hooks[$name] as $hook) {
+ $origfn = $hook[1];
if($hook[0])
@include_once($hook[0]);
+ if(preg_match('|^a:[0-9]+:{.*}$|s', $hook[1])) {
+ $hook[1] = unserialize($hook[1]);
+ }
+ elseif(strpos($hook[1],'::')) {
+ // We shouldn't need to do this, but it appears that PHP
+ // isn't able to directly execute a string variable with a class
+ // method in the manner we are attempting it, so we'll
+ // turn it into an array.
+ $hook[1] = explode('::',$hook[1]);
+ }
- if(function_exists($hook[1])) {
+ if(is_callable($hook[1])) {
$func = $hook[1];
- $func($a, $data);
+ if($hook[3])
+ $func($data);
+ else
+ $func($a, $data);
} else {
-
q("DELETE FROM hook WHERE hook = '%s' AND file = '%s' AND function = '%s'",
dbesc($name),
dbesc($hook[0]),
- dbesc($hook[1])
+ dbesc($origfn)
);
}
}
@@ -535,8 +546,11 @@ function format_css_if_exists($source) {
else
$path = theme_include($source[0]);
- if($path)
- return '<link rel="stylesheet" href="' . script_path() . '/' . $path . '" type="text/css" media="' . $source[1] . '">' . "\r\n";
+ if($path) {
+ $path = script_path() . '/' . $path;
+ $qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
+ return '<link rel="stylesheet" href="' . $path . $qstring . '" type="text/css" media="' . $source[1] . '">' . "\r\n";
+ }
}
/*
@@ -612,8 +626,11 @@ function format_js_if_exists($source) {
$path = $source;
else
$path = theme_include($source);
- if($path)
- return '<script src="' . script_path() . '/' . $path . '" ></script>' . "\r\n" ;
+ if($path) {
+ $path = script_path() . '/' . $path;
+ $qstring = ((parse_url($path, PHP_URL_QUERY)) ? '&' : '?') . 'v=' . STD_VERSION;
+ return '<script src="' . $path . $qstring . '" ></script>' . "\r\n" ;
+ }
}
@@ -678,4 +695,4 @@ function folder_exists($folder)
// If it exist, check if it's a directory
return (($path !== false) && is_dir($path)) ? $path : false;
-} \ No newline at end of file
+}
diff --git a/include/text.php b/include/text.php
index 0a7f84b01..f8bc4b6b0 100644
--- a/include/text.php
+++ b/include/text.php
@@ -1532,35 +1532,6 @@ function prepare_body(&$item,$attach = false) {
$s = sslify($s);
- // Look for spoiler
- $spoilersearch = '<blockquote class="spoiler">';
-
- // Remove line breaks before the spoiler
- while ((strpos($s, "\n".$spoilersearch) !== false))
- $s = str_replace("\n".$spoilersearch, $spoilersearch, $s);
- while ((strpos($s, "<br />".$spoilersearch) !== false))
- $s = str_replace("<br />".$spoilersearch, $spoilersearch, $s);
-
- while ((strpos($s, $spoilersearch) !== false)) {
-
- $pos = strpos($s, $spoilersearch);
- $rnd = random_string(8);
- $spoilerreplace = '<br /> <span id="spoiler-wrap-'.$rnd.'" style="white-space:nowrap;" class="fakelink" onclick="openClose(\'spoiler-'.$rnd.'\');">'.sprintf(t('Click to open/close')).'</span>'.
- '<blockquote class="spoiler" id="spoiler-'.$rnd.'" style="display: none;">';
- $s = substr($s, 0, $pos).$spoilerreplace.substr($s, $pos+strlen($spoilersearch));
- }
-
- // Look for quote with author
- $authorsearch = '<blockquote class="author">';
-
- while ((strpos($s, $authorsearch) !== false)) {
- $pos = strpos($s, $authorsearch);
- $rnd = random_string(8);
- $authorreplace = '<br /> <span id="author-wrap-'.$rnd.'" style="white-space:nowrap;" class="fakelink" onclick="openClose(\'author-'.$rnd.'\');">'.sprintf(t('Click to open/close')).'</span>'.
- '<blockquote class="author" id="author-'.$rnd.'" style="display: block;">';
- $s = substr($s, 0, $pos).$authorreplace.substr($s, $pos+strlen($authorsearch));
- }
-
$prep_arr = array(
'item' => $item,
'photo' => $photo,
@@ -1854,8 +1825,10 @@ function lang_selector() {
}
-function return_bytes ($size_str) {
- switch (substr ($size_str, -1)) {
+function engr_units_to_bytes ($size_str) {
+ if(! $size_str)
+ return $size_str;
+ switch (substr(trim($size_str), -1)) {
case 'M': case 'm': return (int)$size_str * 1048576;
case 'K': case 'k': return (int)$size_str * 1024;
case 'G': case 'g': return (int)$size_str * 1073741824;
diff --git a/include/zot.php b/include/zot.php
index 0cdf7fc87..1ca1b862b 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -3121,7 +3121,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
import_conv($channel,$arr['conv']);
if(array_key_exists('mail',$arr) && $arr['mail'])
- import_mail($channel,$arr['mail']);
+ sync_mail($channel,$arr['mail']);
if(array_key_exists('event',$arr) && $arr['event'])
sync_events($channel,$arr['event']);
@@ -4048,6 +4048,17 @@ function delivery_report_is_storable($dr) {
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient_not_found'))
return false;
+ // If you have a private post with a recipient list, every single site is going to report
+ // back a failed delivery for anybody on that list that isn't local to them. We're only
+ // concerned about this if we have a local hubloc record which says we expected them to
+ // have a channel on that site.
+
+ $r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
+ dbesc($rxchan),
+ dbesc($dr['location'])
+ );
+ if((! $r) && ($dr['status'] === 'recipient_not_found'))
+ return false;
$r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($rxchan),