]> git.mxchange.org Git - friendica.git/commitdiff
The last of the big workers moved ... delivery and notifier
authorMichael <heluecht@pirati.ca>
Sun, 19 Nov 2017 18:59:55 +0000 (18:59 +0000)
committerMichael <heluecht@pirati.ca>
Sun, 19 Nov 2017 18:59:55 +0000 (18:59 +0000)
24 files changed:
include/Contact.php
include/delivery.php [deleted file]
include/items.php
include/like.php
include/message.php
include/notifier.php [deleted file]
include/uimport.php
mod/admin.php
mod/dfrn_confirm.php
mod/events.php
mod/fsuggest.php
mod/item.php
mod/mood.php
mod/photos.php
mod/poke.php
mod/profiles.php
mod/settings.php
mod/tagger.php
mod/videos.php
src/Core/Worker.php
src/Protocol/DFRN.php
src/Protocol/Diaspora.php
src/Worker/Delivery.php [new file with mode: 0644]
src/Worker/Notifier.php [new file with mode: 0644]

index 636bbc4a7a30346799b507d371e02c3cdccb1ba2..cd1696af566dac9d14c670a9e4fc8cb88c47a9fa 100644 (file)
@@ -34,7 +34,7 @@ function user_remove($uid) {
 
        // The user and related data will be deleted in "cron_expire_and_remove_users" (cronjobs.php)
        q("UPDATE `user` SET `account_removed` = 1, `account_expires_on` = UTC_TIMESTAMP() WHERE `uid` = %d", intval($uid));
-       Worker::add(PRIORITY_HIGH, "notifier", "removeme", $uid);
+       Worker::add(PRIORITY_HIGH, "Notifier", "removeme", $uid);
 
        // Send an update to the directory
        Worker::add(PRIORITY_LOW, "Directory", $r['url']);
diff --git a/include/delivery.php b/include/delivery.php
deleted file mode 100644 (file)
index 15b9756..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-<?php
-/**
- * @file include/delivery.php
- */
-use Friendica\App;
-use Friendica\Core\System;
-use Friendica\Core\Config;
-use Friendica\Database\DBM;
-use Friendica\Protocol\Diaspora;
-use Friendica\Protocol\DFRN;
-
-require_once 'include/queue_fn.php';
-require_once 'include/html2plain.php';
-
-function delivery_run(&$argv, &$argc){
-       global $a;
-
-       require_once 'include/datetime.php';
-       require_once 'include/items.php';
-       require_once 'include/bbcode.php';
-       require_once 'include/email.php';
-
-       if ($argc < 3) {
-               return;
-       }
-
-       logger('delivery: invoked: '. print_r($argv,true), LOGGER_DEBUG);
-
-       $cmd        = $argv[1];
-       $item_id    = intval($argv[2]);
-
-       for ($x = 3; $x < $argc; $x ++) {
-
-               $contact_id = intval($argv[$x]);
-
-               if (!$item_id || !$contact_id) {
-                       continue;
-               }
-
-               $expire = false;
-               $mail = false;
-               $fsuggest = false;
-               $relocate = false;
-               $top_level = false;
-               $recipients = array();
-               $url_recipients = array();
-               $followup = false;
-
-               $normal_mode = true;
-
-               $recipients[] = $contact_id;
-
-               if ($cmd === 'mail') {
-                       $normal_mode = false;
-                       $mail = true;
-                       $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
-                                       intval($item_id)
-                       );
-                       if (!count($message)) {
-                               return;
-                       }
-                       $uid = $message[0]['uid'];
-                       $recipients[] = $message[0]['contact-id'];
-                       $item = $message[0];
-               } elseif ($cmd === 'expire') {
-                       $normal_mode = false;
-                       $expire = true;
-                       $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
-                               AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 30 MINUTE",
-                               intval($item_id)
-                       );
-                       $uid = $item_id;
-                       $item_id = 0;
-                       if (!count($items)) {
-                               continue;
-                       }
-               } elseif ($cmd === 'suggest') {
-                       $normal_mode = false;
-                       $fsuggest = true;
-
-                       $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
-                               intval($item_id)
-                       );
-                       if (!count($suggest)) {
-                               return;
-                       }
-                       $uid = $suggest[0]['uid'];
-                       $recipients[] = $suggest[0]['cid'];
-                       $item = $suggest[0];
-               } elseif ($cmd === 'relocate') {
-                       $normal_mode = false;
-                       $relocate = true;
-                       $uid = $item_id;
-               } else {
-                       // find ancestors
-                       $r = q("SELECT * FROM `item` WHERE `id` = %d AND visible = 1 AND moderated = 0 LIMIT 1",
-                               intval($item_id)
-                       );
-
-                       if ((!DBM::is_result($r)) || (!intval($r[0]['parent']))) {
-                               continue;
-                       }
-
-                       $target_item = $r[0];
-                       $parent_id = intval($r[0]['parent']);
-                       $uid = $r[0]['uid'];
-                       $updated = $r[0]['edited'];
-
-                       $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer`
-                               FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d AND visible = 1 AND moderated = 0 ORDER BY `id` ASC",
-                               intval($parent_id)
-                       );
-
-                       if (!count($items)) {
-                               continue;
-                       }
-
-                       $icontacts = null;
-                       $contacts_arr = array();
-                       foreach ($items as $item) {
-                               if (!in_array($item['contact-id'],$contacts_arr)) {
-                                       $contacts_arr[] = intval($item['contact-id']);
-                               }
-                       }
-                       if (count($contacts_arr)) {
-                               $str_contacts = implode(',',$contacts_arr);
-                               $icontacts = q("SELECT * FROM `contact`
-                                       WHERE `id` IN ( $str_contacts ) "
-                               );
-                       }
-                       if ( !($icontacts && count($icontacts))) {
-                               continue;
-                       }
-
-                       // avoid race condition with deleting entries
-
-                       if ($items[0]['deleted']) {
-                               foreach ($items as $item) {
-                                       $item['deleted'] = 1;
-                               }
-                       }
-
-                       // When commenting too fast after delivery, a post wasn't recognized as top level post.
-                       // The count then showed more than one entry. The additional check should help.
-                       // The check for the "count" should be superfluous, but I'm not totally sure by now, so we keep it.
-                       if ((($items[0]['id'] == $item_id) || (count($items) == 1)) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
-                               logger('delivery: top level post');
-                               $top_level = true;
-                       }
-               }
-
-               $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
-                       `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
-                       `user`.`page-flags`, `user`.`account-type`, `user`.`prvnets`
-                       FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
-                       WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
-                       intval($uid)
-               );
-
-               if (!DBM::is_result($r)) {
-                       continue;
-               }
-
-               $owner = $r[0];
-
-               $walltowall = ((($top_level) && ($owner['id'] != $items[0]['contact-id'])) ? true : false);
-
-               $public_message = true;
-
-               if (!($mail || $fsuggest || $relocate)) {
-                       require_once 'include/group.php';
-
-                       $parent = $items[0];
-
-                       // This is IMPORTANT!!!!
-
-                       // We will only send a "notify owner to relay" or followup message if the referenced post
-                       // originated on our system by virtue of having our hostname somewhere
-                       // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere.
-                       // if $parent['wall'] == 1 we will already have the parent message in our array
-                       // and we will relay the whole lot.
-
-                       // expire sends an entire group of expire messages and cannot be forwarded.
-                       // However the conversation owner will be a part of the conversation and will
-                       // be notified during this run.
-                       // Other DFRN conversation members will be alerted during polled updates.
-
-                       // Diaspora members currently are not notified of expirations, and other networks have
-                       // either limited or no ability to process deletions. We should at least fix Diaspora
-                       // by stringing togther an array of retractions and sending them onward.
-
-
-                       $localhost = $a->get_hostname();
-                       if (strpos($localhost,':')) {
-                               $localhost = substr($localhost,0,strpos($localhost,':'));
-                       }
-                       /**
-                        *
-                        * Be VERY CAREFUL if you make any changes to the following line. Seemingly innocuous changes
-                        * have been known to cause runaway conditions which affected several servers, along with
-                        * permissions issues.
-                        *
-                        */
-
-                       $relay_to_owner = false;
-
-                       if (!$top_level && ($parent['wall'] == 0) && !$expire && stristr($target_item['uri'],$localhost)) {
-                               $relay_to_owner = true;
-                       }
-
-                       if ($relay_to_owner) {
-                               logger('followup '.$target_item["guid"], LOGGER_DEBUG);
-                               // local followup to remote post
-                               $followup = true;
-                       }
-
-                       if ((strlen($parent['allow_cid']))
-                               || (strlen($parent['allow_gid']))
-                               || (strlen($parent['deny_cid']))
-                               || (strlen($parent['deny_gid']))
-                               || $parent["private"]) {
-                               $public_message = false; // private recipients, not public
-                       }
-
-               }
-
-               $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `blocked` = 0 AND `pending` = 0",
-                       intval($contact_id)
-               );
-
-               if (DBM::is_result($r)) {
-                       $contact = $r[0];
-               }
-               if ($contact['self']) {
-                       continue;
-               }
-               $deliver_status = 0;
-
-               logger("main delivery by delivery: followup=$followup mail=$mail fsuggest=$fsuggest relocate=$relocate - network ".$contact['network']);
-
-               switch($contact['network']) {
-
-                       case NETWORK_DFRN:
-                               logger('notifier: '.$target_item["guid"].' dfrndelivery: '.$contact['name']);
-
-                               if ($mail) {
-                                       $item['body'] = fix_private_photos($item['body'],$owner['uid'],null,$message[0]['contact-id']);
-                                       $atom = DFRN::mail($item, $owner);
-                               } elseif ($fsuggest) {
-                                       $atom = DFRN::fsuggest($item, $owner);
-                                       q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id']));
-                               } elseif ($relocate) {
-                                       $atom = DFRN::relocate($owner, $uid);
-                               } elseif ($followup) {
-                                       $msgitems = array();
-                                       foreach ($items as $item) {  // there is only one item
-                                               if (!$item['parent']) {
-                                                       continue;
-                                               }
-                                               if ($item['id'] == $item_id) {
-                                                       logger('followup: item: '. print_r($item,true), LOGGER_DATA);
-                                                       $msgitems[] = $item;
-                                               }
-                                       }
-                                       $atom = DFRN::entries($msgitems,$owner);
-                               } else {
-                                       $msgitems = array();
-                                       foreach ($items as $item) {
-                                               if (!$item['parent']) {
-                                                       continue;
-                                               }
-
-                                               // private emails may be in included in public conversations. Filter them.
-                                               if ($public_message && $item['private']) {
-                                                       continue;
-                                               }
-
-                                               $item_contact = get_item_contact($item,$icontacts);
-                                               if (!$item_contact) {
-                                                       continue;
-                                               }
-
-                                               if ($normal_mode) {
-                                                       if ($item_id == $item['id'] || $item['id'] == $item['parent']) {
-                                                               $item["entry:comment-allow"] = true;
-                                                               $item["entry:cid"] = (($top_level) ? $contact['id'] : 0);
-                                                               $msgitems[] = $item;
-                                                       }
-                                               } else {
-                                                       $item["entry:comment-allow"] = true;
-                                                       $msgitems[] = $item;
-                                               }
-                                       }
-                                       $atom = DFRN::entries($msgitems,$owner);
-                               }
-
-                               logger('notifier entry: '.$contact["url"].' '.$target_item["guid"].' entry: '.$atom, LOGGER_DEBUG);
-
-                               logger('notifier: '.$atom, LOGGER_DATA);
-                               $basepath =  implode('/', array_slice(explode('/',$contact['url']),0,3));
-
-                               // perform local delivery if we are on the same site
-
-                               if (link_compare($basepath,System::baseUrl())) {
-
-                                       $nickname = basename($contact['url']);
-                                       if ($contact['issued-id']) {
-                                               $sql_extra = sprintf(" AND `dfrn-id` = '%s' ", dbesc($contact['issued-id']));
-                                       } else {
-                                               $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($contact['dfrn-id']));
-                                       }
-
-                                       $x = q("SELECT  `contact`.*, `contact`.`uid` AS `importer_uid`,
-                                               `contact`.`pubkey` AS `cpubkey`,
-                                               `contact`.`prvkey` AS `cprvkey`,
-                                               `contact`.`thumb` AS `thumb`,
-                                               `contact`.`url` as `url`,
-                                               `contact`.`name` as `senderName`,
-                                               `user`.*
-                                               FROM `contact`
-                                               INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`
-                                               WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0
-                                               AND `contact`.`network` = '%s' AND `user`.`nickname` = '%s'
-                                               $sql_extra
-                                               AND `user`.`account_expired` = 0 AND `user`.`account_removed` = 0 LIMIT 1",
-                                               dbesc(NETWORK_DFRN),
-                                               dbesc($nickname)
-                                       );
-
-                                       if ($x && count($x)) {
-                                               $write_flag = ((($x[0]['rel']) && ($x[0]['rel'] != CONTACT_IS_SHARING)) ? true : false);
-                                               if ((($owner['page-flags'] == PAGE_COMMUNITY) || $write_flag) && !$x[0]['writable']) {
-                                                       q("UPDATE `contact` SET `writable` = 1 WHERE `id` = %d",
-                                                               intval($x[0]['id'])
-                                                       );
-                                                       $x[0]['writable'] = 1;
-                                               }
-
-                                               $ssl_policy = Config::get('system','ssl_policy');
-                                               fix_contact_ssl_policy($x[0],$ssl_policy);
-
-                                               // If we are setup as a soapbox we aren't accepting top level posts from this person
-
-                                               if (($x[0]['page-flags'] == PAGE_SOAPBOX) && $top_level) {
-                                                       break;
-                                               }
-                                               logger('mod-delivery: local delivery');
-                                               DFRN::import($atom, $x[0]);
-                                               break;
-                                       }
-                               }
-
-                               if (!was_recently_delayed($contact['id'])) {
-                                       $deliver_status = DFRN::deliver($owner,$contact,$atom);
-                               } else {
-                                       $deliver_status = (-1);
-                               }
-
-                               logger('notifier: dfrn_delivery to '.$contact["url"].' with guid '.$target_item["guid"].' returns '.$deliver_status);
-
-                               if ($deliver_status < 0) {
-                                       logger('notifier: delivery failed: queuing message');
-                                       add_to_queue($contact['id'],NETWORK_DFRN,$atom);
-
-                                       // The message could not be delivered. We mark the contact as "dead"
-                                       mark_for_death($contact);
-                               } else {
-                                       // We successfully delivered a message, the contact is alive
-                                       unmark_for_death($contact);
-                               }
-
-                               break;
-
-                       case NETWORK_OSTATUS:
-                               // Do not send to otatus if we are not configured to send to public networks
-                               if ($owner['prvnets']) {
-                                       break;
-                               }
-                               if (Config::get('system','ostatus_disabled') || Config::get('system','dfrn_only')) {
-                                       break;
-                               }
-
-                               // There is currently no code here to distribute anything to OStatus.
-                               // This is done in "notifier.php" (See "url_recipients" and "push_notify")
-                               break;
-
-                       case NETWORK_MAIL:
-                       case NETWORK_MAIL2:
-
-                               if (Config::get('system','dfrn_only')) {
-                                       break;
-                               }
-                               // WARNING: does not currently convert to RFC2047 header encodings, etc.
-
-                               $addr = $contact['addr'];
-                               if (!strlen($addr)) {
-                                       break;
-                               }
-
-                               if ($cmd === 'wall-new' || $cmd === 'comment-new') {
-
-                                       $it = null;
-                                       if ($cmd === 'wall-new') {
-                                               $it = $items[0];
-                                       } else {
-                                               $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
-                                                       intval($argv[2]),
-                                                       intval($uid)
-                                               );
-                                               if (DBM::is_result($r))
-                                                       $it = $r[0];
-                                       }
-                                       if (!$it)
-                                               break;
-
-
-                                       $local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
-                                               intval($uid)
-                                       );
-                                       if (!count($local_user))
-                                               break;
-
-                                       $reply_to = '';
-                                       $r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
-                                               intval($uid)
-                                       );
-                                       if ($r1 && $r1[0]['reply_to'])
-                                               $reply_to = $r1[0]['reply_to'];
-
-                                       $subject  = (($it['title']) ? email_header_encode($it['title'],'UTF-8') : t("\x28no subject\x29")) ;
-
-                                       // only expose our real email address to true friends
-
-                                       if (($contact['rel'] == CONTACT_IS_FRIEND) && !$contact['blocked']) {
-                                               if ($reply_to) {
-                                                       $headers  = 'From: '.email_header_encode($local_user[0]['username'],'UTF-8').' <'.$reply_to.'>'."\n";
-                                                       $headers .= 'Sender: '.$local_user[0]['email']."\n";
-                                               } else {
-                                                       $headers  = 'From: '.email_header_encode($local_user[0]['username'],'UTF-8').' <'.$local_user[0]['email'].'>'."\n";
-                                               }
-                                       } else {
-                                               $headers  = 'From: '. email_header_encode($local_user[0]['username'],'UTF-8') .' <'. t('noreply') .'@'.$a->get_hostname() .'>'. "\n";
-                                       }
-
-                                       //if ($reply_to)
-                                       //      $headers .= 'Reply-to: '.$reply_to . "\n";
-
-                                       $headers .= 'Message-Id: <'. iri2msgid($it['uri']).'>'. "\n";
-
-                                       //logger("Mail: uri: ".$it['uri']." parent-uri ".$it['parent-uri'], LOGGER_DEBUG);
-                                       //logger("Mail: Data: ".print_r($it, true), LOGGER_DEBUG);
-                                       //logger("Mail: Data: ".print_r($it, true), LOGGER_DATA);
-
-                                       if ($it['uri'] !== $it['parent-uri']) {
-                                               $headers .= "References: <".iri2msgid($it["parent-uri"]).">";
-
-                                               // If Threading is enabled, write down the correct parent
-                                               if (($it["thr-parent"] != "") && ($it["thr-parent"] != $it["parent-uri"]))
-                                                       $headers .= " <".iri2msgid($it["thr-parent"]).">";
-                                               $headers .= "\n";
-
-                                               if (!$it['title']) {
-                                                       $r = q("SELECT `title` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-                                                               dbesc($it['parent-uri']),
-                                                               intval($uid));
-
-                                                       if (DBM::is_result($r) && ($r[0]['title'] != '')) {
-                                                               $subject = $r[0]['title'];
-                                                       } else {
-                                                               $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d LIMIT 1",
-                                                                       dbesc($it['parent-uri']),
-                                                                       intval($uid));
-
-                                                               if (DBM::is_result($r) && ($r[0]['title'] != ''))
-                                                                       $subject = $r[0]['title'];
-                                                       }
-                                               }
-                                               if (strncasecmp($subject,'RE:',3))
-                                                       $subject = 'Re: '.$subject;
-                                       }
-                                       email_send($addr, $subject, $headers, $it);
-                               }
-                               break;
-
-                       case NETWORK_DIASPORA:
-                               if ($public_message)
-                                       $loc = 'public batch '.$contact['batch'];
-                               else
-                                       $loc = $contact['name'];
-
-                               logger('delivery: diaspora batch deliver: '.$loc);
-
-                               if (Config::get('system','dfrn_only') || (!Config::get('system','diaspora_enabled')))
-                                       break;
-
-                               if ($mail) {
-                                       Diaspora::send_mail($item,$owner,$contact);
-                                       break;
-                               }
-
-                               if (!$normal_mode)
-                                       break;
-
-                               if (!$contact['pubkey'] && !$public_message)
-                                       break;
-
-                               if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
-                                       // top-level retraction
-                                       logger('diaspora retract: '.$loc);
-                                       Diaspora::send_retraction($target_item,$owner,$contact,$public_message);
-                                       break;
-                               } elseif ($relocate) {
-                                       Diaspora::sendAccountMigration($owner, $contact, $uid);
-                                       break;
-                               } elseif ($followup) {
-                                       // send comments and likes to owner to relay
-                                       logger('diaspora followup: '.$loc);
-                                       Diaspora::send_followup($target_item,$owner,$contact,$public_message);
-                                       break;
-                               } elseif ($target_item['uri'] !== $target_item['parent-uri']) {
-                                       // we are the relay - send comments, likes and relayable_retractions to our conversants
-                                       logger('diaspora relay: '.$loc);
-                                       Diaspora::send_relay($target_item,$owner,$contact,$public_message);
-                                       break;
-                               } elseif ($top_level && !$walltowall) {
-                                       // currently no workable solution for sending walltowall
-                                       logger('diaspora status: '.$loc);
-                                       Diaspora::send_status($target_item,$owner,$contact,$public_message);
-                                       break;
-                               }
-
-                               logger('delivery: diaspora unknown mode: '.$contact['name']);
-
-                               break;
-
-                       default:
-                               break;
-               }
-       }
-
-       return;
-}
index 64ee3ffbf1f47245c0bf9f5d9e3dec7d545fe3a4..ed2204f608db4a79197f6a0c783ebf966f742e58 100644 (file)
@@ -1138,7 +1138,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f
        check_item_notification($current_post, $uid);
 
        if ($notify) {
-               Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "notifier", $notify_type, $current_post);
+               Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "Notifier", $notify_type, $current_post);
        }
 
        return $current_post;
@@ -1421,7 +1421,7 @@ function tag_deliver($uid, $item_id) {
        );
        update_thread($item_id);
 
-       Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'notifier', 'tgroup', $item_id);
+       Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'Notifier', 'tgroup', $item_id);
 
 }
 
@@ -2055,7 +2055,7 @@ function item_expire($uid, $days, $network = "", $force = false) {
                drop_item($item['id'], false);
        }
 
-       Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "notifier", "expire", $uid);
+       Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "Notifier", "expire", $uid);
 }
 
 /// @TODO type-hint is array
@@ -2077,7 +2077,7 @@ function drop_items($items) {
        // multiple threads may have been deleted, send an expire notification
 
        if ($uid) {
-               Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "notifier", "expire", $uid);
+               Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "Notifier", "expire", $uid);
        }
 }
 
@@ -2269,7 +2269,7 @@ function drop_item($id, $interactive = true) {
                $drop_id = intval($item['id']);
                $priority = ($interactive ? PRIORITY_HIGH : PRIORITY_LOW);
 
-               Worker::add(array('priority' => $priority, 'dont_fork' => true), "notifier", "drop", $drop_id);
+               Worker::add(array('priority' => $priority, 'dont_fork' => true), "Notifier", "drop", $drop_id);
 
                if (! $interactive) {
                        return $owner;
index eee89168a91ef33bfdf334786af621839239faf3..5e05121f6986f31e88f1cac5308be765fc993804 100644 (file)
@@ -167,7 +167,7 @@ function do_like($item_id, $verb) {
                );
 
                $like_item_id = $like_item['id'];
-               Worker::add(PRIORITY_HIGH, "notifier", "like", $like_item_id);
+               Worker::add(PRIORITY_HIGH, "Notifier", "like", $like_item_id);
 
                if (!$event_verb_flag || $like_item['verb'] == $activity) {
                        return true;
@@ -254,7 +254,7 @@ EOT;
 
        call_hooks('post_local_end', $new_item);
 
-       Worker::add(PRIORITY_HIGH, "notifier", "like", $new_item_id);
+       Worker::add(PRIORITY_HIGH, "Notifier", "like", $new_item_id);
 
        return true;
 }
index dcc1fbc12eba1e86a0ada8da833d0a4a4df4bc8f..e49647b6ef7c9868fe162a28a31298a6e180711c 100644 (file)
@@ -145,7 +145,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
        }
 
        if ($post_id) {
-               Worker::add(PRIORITY_HIGH, "notifier", "mail", $post_id);
+               Worker::add(PRIORITY_HIGH, "Notifier", "mail", $post_id);
                return intval($post_id);
        } else {
                return -3;
diff --git a/include/notifier.php b/include/notifier.php
deleted file mode 100644 (file)
index 58926b9..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-<?php
-
-use Friendica\App;
-use Friendica\Core\Config;
-use Friendica\Core\Worker;
-use Friendica\Database\DBM;
-use Friendica\Network\Probe;
-use Friendica\Protocol\Diaspora;
-use Friendica\Protocol\OStatus;
-
-require_once 'include/queue_fn.php';
-require_once 'include/html2plain.php';
-require_once 'include/salmon.php';
-
-/*
- * This file was at one time responsible for doing all deliveries, but this caused
- * big problems when the process was killed or stalled during the delivery process.
- * It now invokes separate queues that are delivering via delivery.php and pubsubpublish.php.
- */
-
-/*
- * The notifier is typically called with:
- *
- *             Worker::add(PRIORITY_HIGH, "notifier", COMMAND, ITEM_ID);
- *
- * where COMMAND is one of the following:
- *
- *             activity                                (in diaspora.php, dfrn_confirm.php, profiles.php)
- *             comment-import                  (in diaspora.php, items.php)
- *             comment-new                             (in item.php)
- *             drop                                    (in diaspora.php, items.php, photos.php)
- *             edit_post                               (in item.php)
- *             event                                   (in events.php)
- *             expire                                  (in items.php)
- *             like                                    (in like.php, poke.php)
- *             mail                                    (in message.php)
- *             suggest                                 (in fsuggest.php)
- *             tag                                             (in photos.php, poke.php, tagger.php)
- *             tgroup                                  (in items.php)
- *             wall-new                                (in photos.php, item.php)
- *             removeme                                (in Contact.php)
- *             relocate                                (in uimport.php)
- *
- * and ITEM_ID is the id of the item in the database that needs to be sent to others.
- */
-
-
-function notifier_run(&$argv, &$argc){
-       global $a;
-
-       require_once 'include/datetime.php';
-       require_once 'include/items.php';
-       require_once 'include/bbcode.php';
-       require_once 'include/email.php';
-
-       if ($argc < 3) {
-               return;
-       }
-
-       logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
-
-       $cmd = $argv[1];
-
-       switch($cmd) {
-               case 'mail':
-               default:
-                       $item_id = intval($argv[2]);
-                       if (! $item_id) {
-                               return;
-                       }
-                       break;
-       }
-
-       $expire = false;
-       $mail = false;
-       $fsuggest = false;
-       $relocate = false;
-       $top_level = false;
-       $recipients = array();
-       $url_recipients = array();
-
-       $normal_mode = true;
-
-       if ($cmd === 'mail') {
-               $normal_mode = false;
-               $mail = true;
-               $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
-                               intval($item_id)
-               );
-               if (! count($message)) {
-                       return;
-               }
-               $uid = $message[0]['uid'];
-               $recipients[] = $message[0]['contact-id'];
-               $item = $message[0];
-
-       } elseif ($cmd === 'expire') {
-               $normal_mode = false;
-               $expire = true;
-               $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
-                       AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 10 MINUTE",
-                       intval($item_id)
-               );
-               $uid = $item_id;
-               $item_id = 0;
-               if (! count($items)) {
-                       return;
-               }
-       } elseif ($cmd === 'suggest') {
-               $normal_mode = false;
-               $fsuggest = true;
-
-               $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
-                       intval($item_id)
-               );
-               if (! count($suggest)) {
-                       return;
-               }
-               $uid = $suggest[0]['uid'];
-               $recipients[] = $suggest[0]['cid'];
-               $item = $suggest[0];
-       } elseif ($cmd === 'removeme') {
-               $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
-                               `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
-                               `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`, `user`.`guid`
-                       FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
-                               WHERE `contact`.`uid` = %d AND `contact`.`self` LIMIT 1",
-                               intval($item_id));
-               if (!$r)
-                       return;
-
-               $user = $r[0];
-
-               $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($item_id));
-               if (!$r)
-                       return;
-
-               $self = $r[0];
-
-               $r = q("SELECT * FROM `contact` WHERE NOT `self` AND `uid` = %d", intval($item_id));
-               if (!$r) {
-                       return;
-               }
-               require_once 'include/Contact.php';
-               foreach ($r as $contact) {
-                       terminate_friendship($user, $self, $contact);
-               }
-               return;
-       } elseif ($cmd === 'relocate') {
-               $normal_mode = false;
-               $relocate = true;
-               $uid = $item_id;
-
-               $recipients_relocate = q("SELECT * FROM `contact` WHERE `uid` = %d AND NOT `self` AND `network` IN ('%s', '%s')",
-                                       intval($uid), NETWORK_DFRN, NETWORK_DIASPORA);
-       } else {
-               // find ancestors
-               $r = q("SELECT * FROM `item` WHERE `id` = %d AND visible = 1 AND moderated = 0 LIMIT 1",
-                       intval($item_id)
-               );
-
-               if ((! DBM::is_result($r)) || (! intval($r[0]['parent']))) {
-                       return;
-               }
-
-               $target_item = $r[0];
-               $parent_id = intval($r[0]['parent']);
-               $uid = $r[0]['uid'];
-               $updated = $r[0]['edited'];
-
-               $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer`
-                       FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d AND visible = 1 AND moderated = 0 ORDER BY `id` ASC",
-                       intval($parent_id)
-               );
-
-               if (! count($items)) {
-                       return;
-               }
-
-               // avoid race condition with deleting entries
-
-               if ($items[0]['deleted']) {
-                       foreach ($items as $item) {
-                               $item['deleted'] = 1;
-                       }
-               }
-
-               if ((count($items) == 1) && ($items[0]['id'] === $target_item['id']) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
-                       logger('notifier: top level post');
-                       $top_level = true;
-               }
-
-       }
-
-       $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
-               `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
-               `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`
-               FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
-               WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
-               intval($uid)
-       );
-
-       if (! DBM::is_result($r)) {
-               return;
-       }
-
-       $owner = $r[0];
-
-       $walltowall = ((($top_level) && ($owner['id'] != $items[0]['contact-id'])) ? true : false);
-
-       // Should the post be transmitted to Diaspora?
-       $diaspora_delivery = true;
-
-       // If this is a public conversation, notify the feed hub
-       $public_message = true;
-
-       // Do a PuSH
-       $push_notify = false;
-
-       // Deliver directly to a forum, don't PuSH
-       $direct_forum_delivery = false;
-
-       // fill this in with a single salmon slap if applicable
-       $slap = '';
-
-       if (! ($mail || $fsuggest || $relocate)) {
-
-               $slap = OStatus::salmon($target_item, $owner);
-
-               require_once 'include/group.php';
-
-               $parent = $items[0];
-
-               $thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
-                       dbesc($target_item["thr-parent"]), intval($target_item["uid"]));
-
-               logger('GUID: '.$target_item["guid"].': Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG);
-
-               // This is IMPORTANT!!!!
-
-               // We will only send a "notify owner to relay" or followup message if the referenced post
-               // originated on our system by virtue of having our hostname somewhere
-               // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere.
-
-               // if $parent['wall'] == 1 we will already have the parent message in our array
-               // and we will relay the whole lot.
-
-               // expire sends an entire group of expire messages and cannot be forwarded.
-               // However the conversation owner will be a part of the conversation and will
-               // be notified during this run.
-               // Other DFRN conversation members will be alerted during polled updates.
-
-
-
-               // Diaspora members currently are not notified of expirations, and other networks have
-               // either limited or no ability to process deletions. We should at least fix Diaspora
-               // by stringing togther an array of retractions and sending them onward.
-
-
-               $localhost = str_replace('www.','',$a->get_hostname());
-               if (strpos($localhost,':')) {
-                       $localhost = substr($localhost,0,strpos($localhost,':'));
-               }
-               /**
-                *
-                * Be VERY CAREFUL if you make any changes to the following several lines. Seemingly innocuous changes
-                * have been known to cause runaway conditions which affected several servers, along with
-                * permissions issues.
-                *
-                */
-
-               $relay_to_owner = false;
-
-               if (!$top_level && ($parent['wall'] == 0) && !$expire && (stristr($target_item['uri'],$localhost))) {
-                       $relay_to_owner = true;
-               }
-
-
-               if (($cmd === 'uplink') && (intval($parent['forum_mode']) == 1) && !$top_level) {
-                       $relay_to_owner = true;
-               }
-
-               // until the 'origin' flag has been in use for several months
-               // we will just use it as a fallback test
-               // later we will be able to use it as the primary test of whether or not to relay.
-
-               if (! $target_item['origin']) {
-                       $relay_to_owner = false;
-               }
-               if ($parent['origin']) {
-                       $relay_to_owner = false;
-               }
-
-               // Special treatment for forum posts
-               if (($target_item['author-link'] != $target_item['owner-link']) &&
-                       ($owner['id'] != $target_item['contact-id']) &&
-                       ($target_item['uri'] === $target_item['parent-uri'])) {
-
-                       $fields = array('forum', 'prv');
-                       $condition = array('id' => $target_item['contact-id']);
-                       $contact = dba::select('contact', $fields, $condition, array('limit' => 1));
-                       if (!DBM::is_result($contact)) {
-                               // Should never happen
-                               return false;
-                       }
-
-                       // Is the post from a forum?
-                       if ($contact['forum'] || $contact['prv']) {
-                               $relay_to_owner = true;
-                               $direct_forum_delivery = true;
-                       }
-               }
-               if ($relay_to_owner) {
-                       logger('notifier: followup '.$target_item["guid"], LOGGER_DEBUG);
-                       // local followup to remote post
-                       $followup = true;
-                       $public_message = false; // not public
-                       $conversant_str = dbesc($parent['contact-id']);
-                       $recipients = array($parent['contact-id']);
-                       $recipients_followup  = array($parent['contact-id']);
-
-                       //if (!$target_item['private'] && $target_item['wall'] &&
-                       if (!$target_item['private'] &&
-                               (strlen($target_item['allow_cid'].$target_item['allow_gid'].
-                                       $target_item['deny_cid'].$target_item['deny_gid']) == 0))
-                               $push_notify = true;
-
-                       if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) {
-
-                               $push_notify = true;
-
-                               if ($parent["network"] == NETWORK_OSTATUS) {
-                                       // Distribute the message to the DFRN contacts as if this wasn't a followup since OStatus can't relay comments
-                                       // Currently it is work at progress
-                                       $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s' AND NOT `blocked` AND NOT `pending` AND NOT `archive`",
-                                               intval($uid),
-                                               dbesc(NETWORK_DFRN)
-                                       );
-                                       if (DBM::is_result($r)) {
-                                               foreach ($r as $rr) {
-                                                       $recipients_followup[] = $rr['id'];
-                                               }
-                                       }
-                               }
-                       }
-
-                       if ($direct_forum_delivery) {
-                               $push_notify = false;
-                       }
-
-                       logger("Notify ".$target_item["guid"]." via PuSH: ".($push_notify?"Yes":"No"), LOGGER_DEBUG);
-               } else {
-                       $followup = false;
-
-                       logger('Distributing directly '.$target_item["guid"], LOGGER_DEBUG);
-
-                       // don't send deletions onward for other people's stuff
-
-                       if ($target_item['deleted'] && (! intval($target_item['wall']))) {
-                               logger('notifier: ignoring delete notification for non-wall item');
-                               return;
-                       }
-
-                       if ((strlen($parent['allow_cid']))
-                               || (strlen($parent['allow_gid']))
-                               || (strlen($parent['deny_cid']))
-                               || (strlen($parent['deny_gid']))) {
-                               $public_message = false; // private recipients, not public
-                       }
-
-                       $allow_people = expand_acl($parent['allow_cid']);
-                       $allow_groups = expand_groups(expand_acl($parent['allow_gid']),true);
-                       $deny_people  = expand_acl($parent['deny_cid']);
-                       $deny_groups  = expand_groups(expand_acl($parent['deny_gid']));
-
-                       // if our parent is a public forum (forum_mode == 1), uplink to the origional author causing
-                       // a delivery fork. private groups (forum_mode == 2) do not uplink
-
-                       if ((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) {
-                               Worker::add($a->queue['priority'], 'notifier', 'uplink', $item_id);
-                       }
-
-                       $conversants = array();
-
-                       foreach ($items as $item) {
-                               $recipients[] = $item['contact-id'];
-                               $conversants[] = $item['contact-id'];
-                               // pull out additional tagged people to notify (if public message)
-                               if ($public_message && strlen($item['inform'])) {
-                                       $people = explode(',',$item['inform']);
-                                       foreach ($people as $person) {
-                                               if (substr($person,0,4) === 'cid:') {
-                                                       $recipients[] = intval(substr($person,4));
-                                                       $conversants[] = intval(substr($person,4));
-                                               } else {
-                                                       $url_recipients[] = substr($person,4);
-                                               }
-                                       }
-                               }
-                       }
-
-                       if (count($url_recipients))
-                               logger('notifier: '.$target_item["guid"].' url_recipients ' . print_r($url_recipients,true));
-
-                       $conversants = array_unique($conversants);
-
-
-                       $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups));
-                       $deny = array_unique(array_merge($deny_people,$deny_groups));
-                       $recipients = array_diff($recipients,$deny);
-
-                       $conversant_str = dbesc(implode(', ',$conversants));
-               }
-
-               // If the thread parent is OStatus then do some magic to distribute the messages.
-               // We have not only to look at the parent, since it could be a Friendica thread.
-               if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) {
-
-                       $diaspora_delivery = false;
-
-                       logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent[0]['author-link']." - Owner: ".$thr_parent[0]['owner-link'], LOGGER_DEBUG);
-
-                       // Send a salmon to the parent author
-                       $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
-                               dbesc(normalise_link($thr_parent[0]['author-link'])),
-                               intval($uid));
-                       if (DBM::is_result($r)) {
-                               $probed_contact = $r[0];
-                       } else {
-                               $probed_contact = Probe::uri($thr_parent[0]['author-link']);
-                       }
-
-                       if ($probed_contact["notify"] != "") {
-                               logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]);
-                               $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
-                       }
-
-                       // Send a salmon to the parent owner
-                       $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
-                               dbesc(normalise_link($thr_parent[0]['owner-link'])),
-                               intval($uid));
-                       if (DBM::is_result($r)) {
-                               $probed_contact = $r[0];
-                       } else {
-                               $probed_contact = Probe::uri($thr_parent[0]['owner-link']);
-                       }
-
-                       if ($probed_contact["notify"] != "") {
-                               logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]);
-                               $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
-                       }
-
-                       // Send a salmon notification to every person we mentioned in the post
-                       $arr = explode(',',$target_item['tag']);
-                       foreach ($arr as $x) {
-                               //logger('Checking tag '.$x, LOGGER_DEBUG);
-                               $matches = null;
-                               if (preg_match('/@\[url=([^\]]*)\]/',$x,$matches)) {
-                                               $probed_contact = Probe::uri($matches[1]);
-                                       if ($probed_contact["notify"] != "") {
-                                               logger('Notify mentioned user '.$probed_contact["url"].': '.$probed_contact["notify"]);
-                                               $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
-                                       }
-                               }
-                       }
-
-                       // It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora
-                       $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."')";
-               } else {
-                       $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."', '".NETWORK_DIASPORA."', '".NETWORK_MAIL."', '".NETWORK_MAIL2."')";
-               }
-       } else {
-               $public_message = false;
-       }
-
-       // If this is a public message and pubmail is set on the parent, include all your email contacts
-
-       $mail_disabled = ((function_exists('imap_open') && (!Config::get('system','imap_disabled'))) ? 0 : 1);
-
-       if (! $mail_disabled) {
-               if ((! strlen($target_item['allow_cid'])) && (! strlen($target_item['allow_gid']))
-                       && (! strlen($target_item['deny_cid'])) && (! strlen($target_item['deny_gid']))
-                       && (intval($target_item['pubmail']))) {
-                       $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s'",
-                               intval($uid),
-                               dbesc(NETWORK_MAIL)
-                       );
-                       if (DBM::is_result($r)) {
-                               foreach ($r as $rr) {
-                                       $recipients[] = $rr['id'];
-                               }
-                       }
-               }
-       }
-
-       if ($followup) {
-               $recip_str = implode(', ', $recipients_followup);
-       } else {
-               $recip_str = implode(', ', $recipients);
-       }
-       if ($relocate) {
-               $r = $recipients_relocate;
-       } else {
-               $r = q("SELECT `id`, `url`, `network`, `self` FROM `contact`
-                       WHERE `id` IN (%s) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra,
-                       dbesc($recip_str)
-               );
-       }
-
-       // delivery loop
-
-       if (DBM::is_result($r)) {
-               foreach ($r as $contact) {
-                       if ($contact['self']) {
-                               continue;
-                       }
-                       logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG);
-
-                       Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true),
-                                       'delivery', $cmd, $item_id, (int)$contact['id']);
-               }
-       }
-
-       // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts
-       // They are especially used for notifications to OStatus users that don't follow us.
-
-       if ($slap && count($url_recipients) && ($public_message || $push_notify) && $normal_mode) {
-               if (!Config::get('system','dfrn_only')) {
-                       foreach ($url_recipients as $url) {
-                               if ($url) {
-                                       logger('notifier: urldelivery: ' . $url);
-                                       $deliver_status = slapper($owner,$url,$slap);
-                                       /// @TODO Redeliver/queue these items on failure, though there is no contact record
-                               }
-                       }
-               }
-       }
-
-
-       if ($public_message) {
-
-               $r0 = array();
-               $r1 = array();
-
-               if ($diaspora_delivery) {
-                       if (!$followup) {
-                               $r0 = Diaspora::relay_list();
-                       }
-
-                       $r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network`
-                               FROM `contact` WHERE `network` = '%s' AND `batch` != ''
-                               AND `uid` = %d AND `rel` != %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` GROUP BY `batch`",
-                               dbesc(NETWORK_DIASPORA),
-                               intval($owner['uid']),
-                               intval(CONTACT_IS_SHARING)
-                       );
-               }
-
-               $r2 = q("SELECT `id`, `name`,`network` FROM `contact`
-                       WHERE `network` in ('%s', '%s') AND `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `rel` != %d",
-                       dbesc(NETWORK_DFRN),
-                       dbesc(NETWORK_MAIL2),
-                       intval($owner['uid']),
-                       intval(CONTACT_IS_SHARING)
-               );
-
-               $r = array_merge($r2,$r1,$r0);
-
-               if (DBM::is_result($r)) {
-                       logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG);
-
-                       foreach ($r as $rr) {
-
-                               // except for Diaspora batch jobs
-                               // Don't deliver to folks who have already been delivered to
-
-                               if (($rr['network'] !== NETWORK_DIASPORA) && (in_array($rr['id'],$conversants))) {
-                                       logger('notifier: already delivered id=' . $rr['id']);
-                                       continue;
-                               }
-
-                               if ((! $mail) && (! $fsuggest) && (! $followup)) {
-                                       logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]);
-                                       Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true),
-                                                       'delivery', $cmd, $item_id, (int)$rr['id']);
-                               }
-                       }
-               }
-
-               $push_notify = true;
-
-       }
-
-       // Notify PuSH subscribers (Used for OStatus distribution of regular posts)
-       if ($push_notify) {
-               // Set push flag for PuSH subscribers to this topic,
-               // they will be notified in queue.php
-               q("UPDATE `push_subscriber` SET `push` = 1 ".
-                 "WHERE `nickname` = '%s' AND `push` = 0", dbesc($owner['nickname']));
-
-               logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG);
-
-               // Handling the pubsubhubbub requests
-               Worker::add(array('priority' => PRIORITY_HIGH, 'created' => $a->queue['created'], 'dont_fork' => true),
-                               'PubSubPublish');
-       }
-
-       logger('notifier: calling hooks', LOGGER_DEBUG);
-
-       if ($normal_mode) {
-               call_hooks('notifier_normal',$target_item);
-       }
-
-       call_hooks('notifier_end',$target_item);
-
-       return;
-}
index af4f434d4bb0d65da2477695e7764e740bd577e8..e0edb7091d773f61cd149388c2118633293dcea9 100644 (file)
@@ -286,7 +286,7 @@ function import_account(App $a, $file) {
        }
 
        // send relocate messages
-       Worker::add(PRIORITY_HIGH, 'notifier', 'relocate', $newuid);
+       Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $newuid);
 
        info(t("Done. You can now login with your username and password"));
        goaway(System::baseUrl() . "/login");
index cda6d1a3b0baa23cb3edaf19885b44f42ddf5fc6..ee456a23f0ea01eba03d60a9ac6f131ad297df8e 100644 (file)
@@ -778,7 +778,7 @@ function admin_page_site_post(App $a) {
                $users = q("SELECT `uid` FROM `user` WHERE `account_removed` = 0 AND `account_expired` = 0");
 
                foreach ($users as $user) {
-                       Worker::add(PRIORITY_HIGH, 'notifier', 'relocate', $user['uid']);
+                       Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $user['uid']);
                }
 
                info("Relocation started. Could take a while to complete.");
index 98bdfbe1503991e69b4a92fc529d76b692d55764..8484ace2cf6f376509ddb8c88f1befe4371e4de9 100644 (file)
@@ -498,7 +498,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) {
 
                                        $i = item_store($arr);
                                        if($i)
-                                               Worker::add(PRIORITY_HIGH, "notifier", "activity", $i);
+                                               Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i);
                                }
                        }
                }
@@ -800,7 +800,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) {
 
                                        $i = item_store($arr);
                                        if($i)
-                                               Worker::add(PRIORITY_HIGH, "notifier", "activity", $i);
+                                               Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i);
 
                                }
                        }
index b72c8f1884e32f1fe87fd5f211e626952ee19b7b..7a05274e233d8281f6ff673ddb66a28160fd374c 100644 (file)
@@ -180,7 +180,7 @@ function events_post(App $a) {
        $item_id = event_store($datarray);
 
        if (! $cid) {
-               Worker::add(PRIORITY_HIGH, "notifier", "event", $item_id);
+               Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id);
        }
 
        goaway($_SESSION['return_url']);
index c2d9455b0d8d7e0519e956d299de63fade8909da..dd698db58ed5c62972fa70b49aeac208a9daf182 100644 (file)
@@ -61,7 +61,7 @@ function fsuggest_post(App $a) {
                                        intval($fsuggest_id),
                                        intval(local_user())
                                );
-                               Worker::add(PRIORITY_HIGH, 'notifier', 'suggest', $fsuggest_id);
+                               Worker::add(PRIORITY_HIGH, 'Notifier', 'suggest', $fsuggest_id);
                        }
 
                        info( t('Friend suggestion sent.') . EOL);
index 5f5a96d5e9ab9d724c0728c0c4a8e7058fed34ad..0e2e657049cf74adfd872962beb65f9cf015066e 100644 (file)
@@ -834,7 +834,7 @@ function item_post(App $a) {
                // update filetags in pconfig
                file_tag_update_pconfig($uid,$categories_old,$categories_new,'category');
 
-               Worker::add(PRIORITY_HIGH, "notifier", 'edit_post', $post_id);
+               Worker::add(PRIORITY_HIGH, "Notifier", 'edit_post', $post_id);
                if ((x($_REQUEST, 'return')) && strlen($return_path)) {
                        logger('return: ' . $return_path);
                        goaway($return_path);
@@ -1067,7 +1067,7 @@ function item_post(App $a) {
        Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "CreateShadowentry", $post_id);
 
        // Call the background process that is delivering the item to the receivers
-       Worker::add(PRIORITY_HIGH, "notifier", $notify_type, $post_id);
+       Worker::add(PRIORITY_HIGH, "Notifier", $notify_type, $post_id);
 
        logger('post_complete');
 
index 084750ef80ce80b26afa5eafa30ef4b7c557ef1d..bffe37f3be7ced95cff2f60dbd5b3c8d71159b3e 100644 (file)
@@ -100,13 +100,13 @@ function mood_init(App $a) {
                        intval($uid),
                        intval($item_id)
                );
-               Worker::add(PRIORITY_HIGH, "notifier", "tag", $item_id);
+               Worker::add(PRIORITY_HIGH, "Notifier", "tag", $item_id);
        }
 
 
        call_hooks('post_local_end', $arr);
 
-       Worker::add(PRIORITY_HIGH, "notifier", "like", $post_id);
+       Worker::add(PRIORITY_HIGH, "Notifier", "like", $post_id);
 
        return;
 }
index f18ce38af56d79a8bdbd94851b8e5d783d15bca0..1546bd9a8734715da5758f0e37738cfe7bf38814 100644 (file)
@@ -306,7 +306,7 @@ function photos_post(App $a) {
                                        // send the notification upstream/downstream as the case may be
 
                                        if ($rr['visible']) {
-                                               Worker::add(PRIORITY_HIGH, "notifier", "drop", $drop_id);
+                                               Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id);
                                        }
                                }
                        }
@@ -383,7 +383,7 @@ function photos_post(App $a) {
                                photo_albums($page_owner_uid, true);
 
                                if ($i[0]['visible']) {
-                                       Worker::add(PRIORITY_HIGH, "notifier", "drop", $drop_id);
+                                       Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id);
                                }
                        }
                }
@@ -731,7 +731,7 @@ function photos_post(App $a) {
 
                                        $item_id = item_store($arr);
                                        if ($item_id) {
-                                               Worker::add(PRIORITY_HIGH, "notifier", "tag", $item_id);
+                                               Worker::add(PRIORITY_HIGH, "Notifier", "tag", $item_id);
                                        }
                                }
                        }
@@ -936,7 +936,7 @@ function photos_post(App $a) {
        photo_albums($page_owner_uid, true);
 
        if ($visible) {
-               Worker::add(PRIORITY_HIGH, "notifier", 'wall-new', $item_id);
+               Worker::add(PRIORITY_HIGH, "Notifier", 'wall-new', $item_id);
        }
 
        call_hooks('photo_post_end',intval($item_id));
index 848ed817d69d4b5ff0a846a8fe7b5b1f274ae4e2..2f989dd7d3b07bd415847fe376034911b3be3ea9 100644 (file)
@@ -139,13 +139,13 @@ function poke_init(App $a) {
                //      intval($uid),
                //      intval($item_id)
                //);
-               Worker::add(PRIORITY_HIGH, "notifier", "tag", $item_id);
+               Worker::add(PRIORITY_HIGH, "Notifier", "tag", $item_id);
        }
 
 
        call_hooks('post_local_end', $arr);
 
-       Worker::add(PRIORITY_HIGH, "notifier", "like", $post_id);
+       Worker::add(PRIORITY_HIGH, "Notifier", "like", $post_id);
 
        return;
 }
index 5a5a649bcf2269da5e22cdecf2b317c1bf3fc2a0..bbce17c33b682c1f19b6da559dff9e8087efa6f6 100644 (file)
@@ -600,7 +600,7 @@ function profile_activity($changed, $value) {
 
        $i = item_store($arr);
        if ($i) {
-               Worker::add(PRIORITY_HIGH, "notifier", "activity", $i);
+               Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i);
        }
 }
 
index a3ba2ecb915d031b05d3326b761cd9a6eee935f9..6a32b7ed0d32bcf78ce70fba05eb39df7d547fa9 100644 (file)
@@ -360,7 +360,7 @@ function settings_post(App $a) {
        check_form_security_token_redirectOnErr('/settings', 'settings');
 
        if (x($_POST,'resend_relocate')) {
-               Worker::add(PRIORITY_HIGH, 'notifier', 'relocate', local_user());
+               Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', local_user());
                info(t("Relocate message has been send to your contacts"));
                goaway('settings');
        }
index c91fb4abaa82a8d3703072f37941946a4032b9ea..c7e8a9469aed35207dfc48a6ca269514cd968c96 100644 (file)
@@ -216,7 +216,7 @@ EOT;
 
        call_hooks('post_local_end', $arr);
 
-       Worker::add(PRIORITY_HIGH, "notifier", "tag", $post_id);
+       Worker::add(PRIORITY_HIGH, "Notifier", "tag", $post_id);
 
        killme();
 
index bea315c590c76530621c46f31ef616df53b4bbec..a46f5de1ab7758ad99eda638ce43649992f26e12 100644 (file)
@@ -173,7 +173,7 @@ function videos_post(App $a) {
                                $drop_id = intval($i[0]['id']);
 
                                if ($i[0]['visible']) {
-                                       Worker::add(PRIORITY_HIGH, "notifier", "drop", $drop_id);
+                                       Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id);
                                }
                        }
                }
index 88b5bdea8968cbd17666835769c1abaee64d03c9..7d130c1e3a381a781db05cd312bcd54c36f2bf18 100644 (file)
@@ -922,7 +922,7 @@ class Worker {
         * @param (integer|array) priority or parameter array, strings are deprecated and are ignored
         *
         * next args are passed as $cmd command line
-        * or: Worker::add(PRIORITY_HIGH, "notifier", "drop", $drop_id);
+        * or: Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id);
         * or: Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "CreateShadowentry", $post_id);
         *
         * @note $cmd and string args are surrounded with ""
index a88d69d56346db5c940a12aecd8090a446a66bca..d4a5efe8d920ff25a6bfc0109d3f8ce638eba923 100644 (file)
@@ -2106,7 +2106,7 @@ class DFRN
                        $changed = true;
 
                        if ($entrytype == DFRN_REPLY_RC) {
-                               Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $current["id"]);
+                               Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $current["id"]);
                        }
                }
 
@@ -2752,7 +2752,7 @@ class DFRN
 
                                if ($posted_id && $parent && ($entrytype == DFRN_REPLY_RC)) {
                                        logger("Notifying followers about comment ".$posted_id, LOGGER_DEBUG);
-                                       Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $posted_id);
+                                       Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $posted_id);
                                }
 
                                return true;
@@ -2940,7 +2940,7 @@ class DFRN
 
                                if ($entrytype == DFRN_REPLY_RC) {
                                        logger("Notifying followers about deletion of post " . $item["id"], LOGGER_DEBUG);
-                                       Worker::add(PRIORITY_HIGH, "notifier", "drop", $item["id"]);
+                                       Worker::add(PRIORITY_HIGH, "Notifier", "drop", $item["id"]);
                                }
                        }
                }
index 0c0c3bb2fa1bb32e671065cbbc073d448ca688f1..bf58f23e9b32c356075fa7c8d2f0b6db15753f22 100644 (file)
@@ -1696,7 +1696,7 @@ class Diaspora
                        dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($data)));
 
                        // notify others
-                       Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $message_id);
+                       Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $message_id);
                }
 
                return true;
@@ -2024,7 +2024,7 @@ class Diaspora
                        dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($data)));
 
                        // notify others
-                       Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $message_id);
+                       Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $message_id);
                }
 
                return true;
@@ -2320,7 +2320,7 @@ class Diaspora
 
                                $i = item_store($arr);
                                if ($i) {
-                                       Worker::add(PRIORITY_HIGH, "notifier", "activity", $i);
+                                       Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i);
                                }
                        }
                }
@@ -2768,7 +2768,7 @@ class Diaspora
                        // Now check if the retraction needs to be relayed by us
                        if ($parent["origin"]) {
                                // notify others
-                               Worker::add(PRIORITY_HIGH, "notifier", "drop", $item["id"]);
+                               Worker::add(PRIORITY_HIGH, "Notifier", "drop", $item["id"]);
                        }
                }
 
diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php
new file mode 100644 (file)
index 0000000..e450dee
--- /dev/null
@@ -0,0 +1,532 @@
+<?php
+/**
+ * @file src/Worker/Delivery.php
+ */
+
+namespace Friendica\Worker;
+
+use Friendica\App;
+use Friendica\Core\System;
+use Friendica\Core\Config;
+use Friendica\Database\DBM;
+use Friendica\Protocol\Diaspora;
+use Friendica\Protocol\DFRN;
+
+require_once 'include/queue_fn.php';
+require_once 'include/html2plain.php';
+require_once 'include/datetime.php';
+require_once 'include/items.php';
+require_once 'include/bbcode.php';
+require_once 'include/email.php';
+
+/// @todo This is some ugly code that needs to be split into several methods
+
+class Delivery {
+       public static function execute($cmd, $item_id, $contact_id) {
+               global $a;
+
+               logger('delivery: invoked: '.$cmd.': '.$item_id.' to '.$contact_id, LOGGER_DEBUG);
+
+               $expire = false;
+               $mail = false;
+               $fsuggest = false;
+               $relocate = false;
+               $top_level = false;
+               $recipients = array();
+               $url_recipients = array();
+               $followup = false;
+
+               $normal_mode = true;
+
+               $recipients[] = $contact_id;
+
+               if ($cmd === 'mail') {
+                       $normal_mode = false;
+                       $mail = true;
+                       $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
+                                       intval($item_id)
+                       );
+                       if (!count($message)) {
+                               return;
+                       }
+                       $uid = $message[0]['uid'];
+                       $recipients[] = $message[0]['contact-id'];
+                       $item = $message[0];
+               } elseif ($cmd === 'expire') {
+                       $normal_mode = false;
+                       $expire = true;
+                       $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
+                               AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 30 MINUTE",
+                               intval($item_id)
+                       );
+                       $uid = $item_id;
+                       $item_id = 0;
+                       if (!count($items)) {
+                               return;
+                       }
+               } elseif ($cmd === 'suggest') {
+                       $normal_mode = false;
+                       $fsuggest = true;
+
+                       $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
+                               intval($item_id)
+                       );
+                       if (!count($suggest)) {
+                               return;
+                       }
+                       $uid = $suggest[0]['uid'];
+                       $recipients[] = $suggest[0]['cid'];
+                       $item = $suggest[0];
+               } elseif ($cmd === 'relocate') {
+                       $normal_mode = false;
+                       $relocate = true;
+                       $uid = $item_id;
+               } else {
+                       // find ancestors
+                       $r = q("SELECT * FROM `item` WHERE `id` = %d AND visible = 1 AND moderated = 0 LIMIT 1",
+                               intval($item_id)
+                       );
+
+                       if (!DBM::is_result($r) || !intval($r[0]['parent'])) {
+                               return;
+                       }
+
+                       $target_item = $r[0];
+                       $parent_id = intval($r[0]['parent']);
+                       $uid = $r[0]['uid'];
+                       $updated = $r[0]['edited'];
+
+                       $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer`
+                               FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d AND visible = 1 AND moderated = 0 ORDER BY `id` ASC",
+                               intval($parent_id)
+                       );
+
+                       if (!count($items)) {
+                               return;
+                       }
+
+                       $icontacts = null;
+                       $contacts_arr = array();
+                       foreach ($items as $item) {
+                               if (!in_array($item['contact-id'],$contacts_arr)) {
+                                       $contacts_arr[] = intval($item['contact-id']);
+                               }
+                       }
+                       if (count($contacts_arr)) {
+                               $str_contacts = implode(',',$contacts_arr);
+                               $icontacts = q("SELECT * FROM `contact`
+                                       WHERE `id` IN ( $str_contacts ) "
+                               );
+                       }
+                       if ( !($icontacts && count($icontacts))) {
+                               return;
+                       }
+
+                       // avoid race condition with deleting entries
+
+                       if ($items[0]['deleted']) {
+                               foreach ($items as $item) {
+                                       $item['deleted'] = 1;
+                               }
+                       }
+
+                       // When commenting too fast after delivery, a post wasn't recognized as top level post.
+                       // The count then showed more than one entry. The additional check should help.
+                       // The check for the "count" should be superfluous, but I'm not totally sure by now, so we keep it.
+                       if ((($items[0]['id'] == $item_id) || (count($items) == 1)) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
+                               logger('delivery: top level post');
+                               $top_level = true;
+                       }
+               }
+
+               $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
+                       `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
+                       `user`.`page-flags`, `user`.`account-type`, `user`.`prvnets`
+                       FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
+                       WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
+                       intval($uid)
+               );
+
+               if (!DBM::is_result($r)) {
+                       return;
+               }
+
+               $owner = $r[0];
+
+               $walltowall = (($top_level && ($owner['id'] != $items[0]['contact-id'])) ? true : false);
+
+               $public_message = true;
+
+               if (!($mail || $fsuggest || $relocate)) {
+                       require_once 'include/group.php';
+
+                       $parent = $items[0];
+
+                       // This is IMPORTANT!!!!
+
+                       // We will only send a "notify owner to relay" or followup message if the referenced post
+                       // originated on our system by virtue of having our hostname somewhere
+                       // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere.
+                       // if $parent['wall'] == 1 we will already have the parent message in our array
+                       // and we will relay the whole lot.
+
+                       // expire sends an entire group of expire messages and cannot be forwarded.
+                       // However the conversation owner will be a part of the conversation and will
+                       // be notified during this run.
+                       // Other DFRN conversation members will be alerted during polled updates.
+
+                       // Diaspora members currently are not notified of expirations, and other networks have
+                       // either limited or no ability to process deletions. We should at least fix Diaspora
+                       // by stringing togther an array of retractions and sending them onward.
+
+
+                       $localhost = $a->get_hostname();
+                       if (strpos($localhost,':')) {
+                               $localhost = substr($localhost,0,strpos($localhost,':'));
+                       }
+                       /**
+                        *
+                        * Be VERY CAREFUL if you make any changes to the following line. Seemingly innocuous changes
+                        * have been known to cause runaway conditions which affected several servers, along with
+                        * permissions issues.
+                        *
+                        */
+
+                       $relay_to_owner = false;
+
+                       if (!$top_level && ($parent['wall'] == 0) && !$expire && stristr($target_item['uri'],$localhost)) {
+                               $relay_to_owner = true;
+                       }
+
+                       if ($relay_to_owner) {
+                               logger('followup '.$target_item["guid"], LOGGER_DEBUG);
+                               // local followup to remote post
+                               $followup = true;
+                       }
+
+                       if ((strlen($parent['allow_cid']))
+                               || (strlen($parent['allow_gid']))
+                               || (strlen($parent['deny_cid']))
+                               || (strlen($parent['deny_gid']))
+                               || $parent["private"]) {
+                               $public_message = false; // private recipients, not public
+                       }
+
+               }
+
+               $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `blocked` = 0 AND `pending` = 0",
+                       intval($contact_id)
+               );
+
+               if (DBM::is_result($r)) {
+                       $contact = $r[0];
+               }
+               if ($contact['self']) {
+                       return;
+               }
+               $deliver_status = 0;
+
+               logger("main delivery by delivery: followup=$followup mail=$mail fsuggest=$fsuggest relocate=$relocate - network ".$contact['network']);
+
+               switch($contact['network']) {
+
+                       case NETWORK_DFRN:
+                               logger('notifier: '.$target_item["guid"].' dfrndelivery: '.$contact['name']);
+
+                               if ($mail) {
+                                       $item['body'] = fix_private_photos($item['body'],$owner['uid'],null,$message[0]['contact-id']);
+                                       $atom = DFRN::mail($item, $owner);
+                               } elseif ($fsuggest) {
+                                       $atom = DFRN::fsuggest($item, $owner);
+                                       q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id']));
+                               } elseif ($relocate) {
+                                       $atom = DFRN::relocate($owner, $uid);
+                               } elseif ($followup) {
+                                       $msgitems = array();
+                                       foreach ($items as $item) {  // there is only one item
+                                               if (!$item['parent']) {
+                                                       return;
+                                               }
+                                               if ($item['id'] == $item_id) {
+                                                       logger('followup: item: '. print_r($item,true), LOGGER_DATA);
+                                                       $msgitems[] = $item;
+                                               }
+                                       }
+                                       $atom = DFRN::entries($msgitems,$owner);
+                               } else {
+                                       $msgitems = array();
+                                       foreach ($items as $item) {
+                                               if (!$item['parent']) {
+                                                       return;
+                                               }
+
+                                               // private emails may be in included in public conversations. Filter them.
+                                               if ($public_message && $item['private']) {
+                                                       return;
+                                               }
+
+                                               $item_contact = get_item_contact($item,$icontacts);
+                                               if (!$item_contact) {
+                                                       return;
+                                               }
+
+                                               if ($normal_mode) {
+                                                       if ($item_id == $item['id'] || $item['id'] == $item['parent']) {
+                                                               $item["entry:comment-allow"] = true;
+                                                               $item["entry:cid"] = (($top_level) ? $contact['id'] : 0);
+                                                               $msgitems[] = $item;
+                                                       }
+                                               } else {
+                                                       $item["entry:comment-allow"] = true;
+                                                       $msgitems[] = $item;
+                                               }
+                                       }
+                                       $atom = DFRN::entries($msgitems,$owner);
+                               }
+
+                               logger('notifier entry: '.$contact["url"].' '.$target_item["guid"].' entry: '.$atom, LOGGER_DEBUG);
+
+                               logger('notifier: '.$atom, LOGGER_DATA);
+                               $basepath =  implode('/', array_slice(explode('/',$contact['url']),0,3));
+
+                               // perform local delivery if we are on the same site
+
+                               if (link_compare($basepath,System::baseUrl())) {
+
+                                       $nickname = basename($contact['url']);
+                                       if ($contact['issued-id']) {
+                                               $sql_extra = sprintf(" AND `dfrn-id` = '%s' ", dbesc($contact['issued-id']));
+                                       } else {
+                                               $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($contact['dfrn-id']));
+                                       }
+
+                                       $x = q("SELECT  `contact`.*, `contact`.`uid` AS `importer_uid`,
+                                               `contact`.`pubkey` AS `cpubkey`,
+                                               `contact`.`prvkey` AS `cprvkey`,
+                                               `contact`.`thumb` AS `thumb`,
+                                               `contact`.`url` as `url`,
+                                               `contact`.`name` as `senderName`,
+                                               `user`.*
+                                               FROM `contact`
+                                               INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`
+                                               WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0
+                                               AND `contact`.`network` = '%s' AND `user`.`nickname` = '%s'
+                                               $sql_extra
+                                               AND `user`.`account_expired` = 0 AND `user`.`account_removed` = 0 LIMIT 1",
+                                               dbesc(NETWORK_DFRN),
+                                               dbesc($nickname)
+                                       );
+
+                                       if ($x && count($x)) {
+                                               $write_flag = ((($x[0]['rel']) && ($x[0]['rel'] != CONTACT_IS_SHARING)) ? true : false);
+                                               if ((($owner['page-flags'] == PAGE_COMMUNITY) || $write_flag) && !$x[0]['writable']) {
+                                                       q("UPDATE `contact` SET `writable` = 1 WHERE `id` = %d",
+                                                               intval($x[0]['id'])
+                                                       );
+                                                       $x[0]['writable'] = 1;
+                                               }
+
+                                               $ssl_policy = Config::get('system','ssl_policy');
+                                               fix_contact_ssl_policy($x[0],$ssl_policy);
+
+                                               // If we are setup as a soapbox we aren't accepting top level posts from this person
+
+                                               if (($x[0]['page-flags'] == PAGE_SOAPBOX) && $top_level) {
+                                                       break;
+                                               }
+                                               logger('mod-delivery: local delivery');
+                                               DFRN::import($atom, $x[0]);
+                                               break;
+                                       }
+                               }
+
+                               if (!was_recently_delayed($contact['id'])) {
+                                       $deliver_status = DFRN::deliver($owner,$contact,$atom);
+                               } else {
+                                       $deliver_status = (-1);
+                               }
+
+                               logger('notifier: dfrn_delivery to '.$contact["url"].' with guid '.$target_item["guid"].' returns '.$deliver_status);
+
+                               if ($deliver_status < 0) {
+                                       logger('notifier: delivery failed: queuing message');
+                                       add_to_queue($contact['id'],NETWORK_DFRN,$atom);
+
+                                       // The message could not be delivered. We mark the contact as "dead"
+                                       mark_for_death($contact);
+                               } else {
+                                       // We successfully delivered a message, the contact is alive
+                                       unmark_for_death($contact);
+                               }
+
+                               break;
+
+                       case NETWORK_OSTATUS:
+                               // Do not send to otatus if we are not configured to send to public networks
+                               if ($owner['prvnets']) {
+                                       break;
+                               }
+                               if (Config::get('system','ostatus_disabled') || Config::get('system','dfrn_only')) {
+                                       break;
+                               }
+
+                               // There is currently no code here to distribute anything to OStatus.
+                               // This is done in "notifier.php" (See "url_recipients" and "push_notify")
+                               break;
+
+                       case NETWORK_MAIL:
+                       case NETWORK_MAIL2:
+
+                               if (Config::get('system','dfrn_only')) {
+                                       break;
+                               }
+                               // WARNING: does not currently convert to RFC2047 header encodings, etc.
+
+                               $addr = $contact['addr'];
+                               if (!strlen($addr)) {
+                                       break;
+                               }
+
+                               if ($cmd === 'wall-new' || $cmd === 'comment-new') {
+
+                                       $it = null;
+                                       if ($cmd === 'wall-new') {
+                                               $it = $items[0];
+                                       } else {
+                                               $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+                                                       intval($item_id),
+                                                       intval($uid)
+                                               );
+                                               if (DBM::is_result($r))
+                                                       $it = $r[0];
+                                       }
+                                       if (!$it)
+                                               break;
+
+
+                                       $local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
+                                               intval($uid)
+                                       );
+                                       if (!count($local_user))
+                                               break;
+
+                                       $reply_to = '';
+                                       $r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
+                                               intval($uid)
+                                       );
+                                       if ($r1 && $r1[0]['reply_to'])
+                                               $reply_to = $r1[0]['reply_to'];
+
+                                       $subject  = (($it['title']) ? email_header_encode($it['title'],'UTF-8') : t("\x28no subject\x29")) ;
+
+                                       // only expose our real email address to true friends
+
+                                       if (($contact['rel'] == CONTACT_IS_FRIEND) && !$contact['blocked']) {
+                                               if ($reply_to) {
+                                                       $headers  = 'From: '.email_header_encode($local_user[0]['username'],'UTF-8').' <'.$reply_to.'>'."\n";
+                                                       $headers .= 'Sender: '.$local_user[0]['email']."\n";
+                                               } else {
+                                                       $headers  = 'From: '.email_header_encode($local_user[0]['username'],'UTF-8').' <'.$local_user[0]['email'].'>'."\n";
+                                               }
+                                       } else {
+                                               $headers  = 'From: '. email_header_encode($local_user[0]['username'],'UTF-8') .' <'. t('noreply') .'@'.$a->get_hostname() .'>'. "\n";
+                                       }
+
+                                       //if ($reply_to)
+                                       //      $headers .= 'Reply-to: '.$reply_to . "\n";
+
+                                       $headers .= 'Message-Id: <'. iri2msgid($it['uri']).'>'. "\n";
+
+                                       //logger("Mail: uri: ".$it['uri']." parent-uri ".$it['parent-uri'], LOGGER_DEBUG);
+                                       //logger("Mail: Data: ".print_r($it, true), LOGGER_DEBUG);
+                                       //logger("Mail: Data: ".print_r($it, true), LOGGER_DATA);
+
+                                       if ($it['uri'] !== $it['parent-uri']) {
+                                               $headers .= "References: <".iri2msgid($it["parent-uri"]).">";
+
+                                               // If Threading is enabled, write down the correct parent
+                                               if (($it["thr-parent"] != "") && ($it["thr-parent"] != $it["parent-uri"]))
+                                                       $headers .= " <".iri2msgid($it["thr-parent"]).">";
+                                               $headers .= "\n";
+
+                                               if (!$it['title']) {
+                                                       $r = q("SELECT `title` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                                               dbesc($it['parent-uri']),
+                                                               intval($uid));
+
+                                                       if (DBM::is_result($r) && ($r[0]['title'] != '')) {
+                                                               $subject = $r[0]['title'];
+                                                       } else {
+                                                               $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d LIMIT 1",
+                                                                       dbesc($it['parent-uri']),
+                                                                       intval($uid));
+
+                                                               if (DBM::is_result($r) && ($r[0]['title'] != ''))
+                                                                       $subject = $r[0]['title'];
+                                                       }
+                                               }
+                                               if (strncasecmp($subject,'RE:',3))
+                                                       $subject = 'Re: '.$subject;
+                                       }
+                                       email_send($addr, $subject, $headers, $it);
+                               }
+                               break;
+
+                       case NETWORK_DIASPORA:
+                               if ($public_message)
+                                       $loc = 'public batch '.$contact['batch'];
+                               else
+                                       $loc = $contact['name'];
+
+                               logger('delivery: diaspora batch deliver: '.$loc);
+
+                               if (Config::get('system','dfrn_only') || !Config::get('system','diaspora_enabled'))
+                                       break;
+
+                               if ($mail) {
+                                       Diaspora::send_mail($item,$owner,$contact);
+                                       break;
+                               }
+
+                               if (!$normal_mode)
+                                       break;
+
+                               if (!$contact['pubkey'] && !$public_message)
+                                       break;
+
+                               if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
+                                       // top-level retraction
+                                       logger('diaspora retract: '.$loc);
+                                       Diaspora::send_retraction($target_item,$owner,$contact,$public_message);
+                                       break;
+                               } elseif ($relocate) {
+                                       Diaspora::sendAccountMigration($owner, $contact, $uid);
+                                       break;
+                               } elseif ($followup) {
+                                       // send comments and likes to owner to relay
+                                       logger('diaspora followup: '.$loc);
+                                       Diaspora::send_followup($target_item,$owner,$contact,$public_message);
+                                       break;
+                               } elseif ($target_item['uri'] !== $target_item['parent-uri']) {
+                                       // we are the relay - send comments, likes and relayable_retractions to our conversants
+                                       logger('diaspora relay: '.$loc);
+                                       Diaspora::send_relay($target_item,$owner,$contact,$public_message);
+                                       break;
+                               } elseif ($top_level && !$walltowall) {
+                                       // currently no workable solution for sending walltowall
+                                       logger('diaspora status: '.$loc);
+                                       Diaspora::send_status($target_item,$owner,$contact,$public_message);
+                                       break;
+                               }
+
+                               logger('delivery: diaspora unknown mode: '.$contact['name']);
+
+                               break;
+
+                       default:
+                               break;
+               }
+
+               return;
+       }
+}
diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php
new file mode 100644 (file)
index 0000000..40b2910
--- /dev/null
@@ -0,0 +1,606 @@
+<?php
+/**
+ * @file src/Worker/Notifier.php
+ */
+namespace Friendica\Worker;
+
+use Friendica\App;
+use Friendica\Core\Config;
+use Friendica\Core\Worker;
+use Friendica\Database\DBM;
+use Friendica\Network\Probe;
+use Friendica\Protocol\Diaspora;
+use Friendica\Protocol\OStatus;
+use dba;
+
+require_once 'include/queue_fn.php';
+require_once 'include/html2plain.php';
+require_once 'include/salmon.php';
+require_once 'include/datetime.php';
+require_once 'include/items.php';
+require_once 'include/bbcode.php';
+require_once 'include/email.php';
+
+/*
+ * This file was at one time responsible for doing all deliveries, but this caused
+ * big problems when the process was killed or stalled during the delivery process.
+ * It now invokes separate queues that are delivering via delivery.php and pubsubpublish.php.
+ */
+
+/*
+ * The notifier is typically called with:
+ *
+ *             Worker::add(PRIORITY_HIGH, "Notifier", COMMAND, ITEM_ID);
+ *
+ * where COMMAND is one of the following:
+ *
+ *             activity                                (in diaspora.php, dfrn_confirm.php, profiles.php)
+ *             comment-import                  (in diaspora.php, items.php)
+ *             comment-new                             (in item.php)
+ *             drop                                    (in diaspora.php, items.php, photos.php)
+ *             edit_post                               (in item.php)
+ *             event                                   (in events.php)
+ *             expire                                  (in items.php)
+ *             like                                    (in like.php, poke.php)
+ *             mail                                    (in message.php)
+ *             suggest                                 (in fsuggest.php)
+ *             tag                                             (in photos.php, poke.php, tagger.php)
+ *             tgroup                                  (in items.php)
+ *             wall-new                                (in photos.php, item.php)
+ *             removeme                                (in Contact.php)
+ *             relocate                                (in uimport.php)
+ *
+ * and ITEM_ID is the id of the item in the database that needs to be sent to others.
+ */
+
+class Notifier {
+       public static function execute($cmd, $item_id) {
+               global $a;
+
+               logger('notifier: invoked: '.$cmd.': '.$item_id, LOGGER_DEBUG);
+
+               $expire = false;
+               $mail = false;
+               $fsuggest = false;
+               $relocate = false;
+               $top_level = false;
+               $recipients = array();
+               $url_recipients = array();
+
+               $normal_mode = true;
+
+               if ($cmd === 'mail') {
+                       $normal_mode = false;
+                       $mail = true;
+                       $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
+                                       intval($item_id)
+                       );
+                       if (! count($message)) {
+                               return;
+                       }
+                       $uid = $message[0]['uid'];
+                       $recipients[] = $message[0]['contact-id'];
+                       $item = $message[0];
+
+               } elseif ($cmd === 'expire') {
+                       $normal_mode = false;
+                       $expire = true;
+                       $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
+                               AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 10 MINUTE",
+                               intval($item_id)
+                       );
+                       $uid = $item_id;
+                       $item_id = 0;
+                       if (! count($items)) {
+                               return;
+                       }
+               } elseif ($cmd === 'suggest') {
+                       $normal_mode = false;
+                       $fsuggest = true;
+
+                       $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
+                               intval($item_id)
+                       );
+                       if (! count($suggest)) {
+                               return;
+                       }
+                       $uid = $suggest[0]['uid'];
+                       $recipients[] = $suggest[0]['cid'];
+                       $item = $suggest[0];
+               } elseif ($cmd === 'removeme') {
+                       $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
+                                       `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
+                                       `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`, `user`.`guid`
+                               FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
+                                       WHERE `contact`.`uid` = %d AND `contact`.`self` LIMIT 1",
+                                       intval($item_id));
+                       if (!$r)
+                               return;
+
+                       $user = $r[0];
+
+                       $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($item_id));
+                       if (!$r)
+                               return;
+
+                       $self = $r[0];
+
+                       $r = q("SELECT * FROM `contact` WHERE NOT `self` AND `uid` = %d", intval($item_id));
+                       if (!$r) {
+                               return;
+                       }
+                       require_once 'include/Contact.php';
+                       foreach ($r as $contact) {
+                               terminate_friendship($user, $self, $contact);
+                       }
+                       return;
+               } elseif ($cmd === 'relocate') {
+                       $normal_mode = false;
+                       $relocate = true;
+                       $uid = $item_id;
+
+                       $recipients_relocate = q("SELECT * FROM `contact` WHERE `uid` = %d AND NOT `self` AND `network` IN ('%s', '%s')",
+                                               intval($uid), NETWORK_DFRN, NETWORK_DIASPORA);
+               } else {
+                       // find ancestors
+                       $r = q("SELECT * FROM `item` WHERE `id` = %d AND visible = 1 AND moderated = 0 LIMIT 1",
+                               intval($item_id)
+                       );
+
+                       if ((! DBM::is_result($r)) || (! intval($r[0]['parent']))) {
+                               return;
+                       }
+
+                       $target_item = $r[0];
+                       $parent_id = intval($r[0]['parent']);
+                       $uid = $r[0]['uid'];
+                       $updated = $r[0]['edited'];
+
+                       $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer`
+                               FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d AND visible = 1 AND moderated = 0 ORDER BY `id` ASC",
+                               intval($parent_id)
+                       );
+
+                       if (! count($items)) {
+                               return;
+                       }
+
+                       // avoid race condition with deleting entries
+
+                       if ($items[0]['deleted']) {
+                               foreach ($items as $item) {
+                                       $item['deleted'] = 1;
+                               }
+                       }
+
+                       if ((count($items) == 1) && ($items[0]['id'] === $target_item['id']) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
+                               logger('notifier: top level post');
+                               $top_level = true;
+                       }
+
+               }
+
+               $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
+                       `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
+                       `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`
+                       FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
+                       WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
+                       intval($uid)
+               );
+
+               if (! DBM::is_result($r)) {
+                       return;
+               }
+
+               $owner = $r[0];
+
+               $walltowall = ((($top_level) && ($owner['id'] != $items[0]['contact-id'])) ? true : false);
+
+               // Should the post be transmitted to Diaspora?
+               $diaspora_delivery = true;
+
+               // If this is a public conversation, notify the feed hub
+               $public_message = true;
+
+               // Do a PuSH
+               $push_notify = false;
+
+               // Deliver directly to a forum, don't PuSH
+               $direct_forum_delivery = false;
+
+               // fill this in with a single salmon slap if applicable
+               $slap = '';
+
+               if (! ($mail || $fsuggest || $relocate)) {
+
+                       $slap = OStatus::salmon($target_item, $owner);
+
+                       require_once 'include/group.php';
+
+                       $parent = $items[0];
+
+                       $thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
+                               dbesc($target_item["thr-parent"]), intval($target_item["uid"]));
+
+                       logger('GUID: '.$target_item["guid"].': Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG);
+
+                       // This is IMPORTANT!!!!
+
+                       // We will only send a "notify owner to relay" or followup message if the referenced post
+                       // originated on our system by virtue of having our hostname somewhere
+                       // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere.
+
+                       // if $parent['wall'] == 1 we will already have the parent message in our array
+                       // and we will relay the whole lot.
+
+                       // expire sends an entire group of expire messages and cannot be forwarded.
+                       // However the conversation owner will be a part of the conversation and will
+                       // be notified during this run.
+                       // Other DFRN conversation members will be alerted during polled updates.
+
+
+
+                       // Diaspora members currently are not notified of expirations, and other networks have
+                       // either limited or no ability to process deletions. We should at least fix Diaspora
+                       // by stringing togther an array of retractions and sending them onward.
+
+
+                       $localhost = str_replace('www.','',$a->get_hostname());
+                       if (strpos($localhost,':')) {
+                               $localhost = substr($localhost,0,strpos($localhost,':'));
+                       }
+                       /**
+                        *
+                        * Be VERY CAREFUL if you make any changes to the following several lines. Seemingly innocuous changes
+                        * have been known to cause runaway conditions which affected several servers, along with
+                        * permissions issues.
+                        *
+                        */
+
+                       $relay_to_owner = false;
+
+                       if (!$top_level && ($parent['wall'] == 0) && !$expire && (stristr($target_item['uri'],$localhost))) {
+                               $relay_to_owner = true;
+                       }
+
+
+                       if (($cmd === 'uplink') && (intval($parent['forum_mode']) == 1) && !$top_level) {
+                               $relay_to_owner = true;
+                       }
+
+                       // until the 'origin' flag has been in use for several months
+                       // we will just use it as a fallback test
+                       // later we will be able to use it as the primary test of whether or not to relay.
+
+                       if (! $target_item['origin']) {
+                               $relay_to_owner = false;
+                       }
+                       if ($parent['origin']) {
+                               $relay_to_owner = false;
+                       }
+
+                       // Special treatment for forum posts
+                       if (($target_item['author-link'] != $target_item['owner-link']) &&
+                               ($owner['id'] != $target_item['contact-id']) &&
+                               ($target_item['uri'] === $target_item['parent-uri'])) {
+
+                               $fields = array('forum', 'prv');
+                               $condition = array('id' => $target_item['contact-id']);
+                               $contact = dba::select('contact', $fields, $condition, array('limit' => 1));
+                               if (!DBM::is_result($contact)) {
+                                       // Should never happen
+                                       return false;
+                               }
+
+                               // Is the post from a forum?
+                               if ($contact['forum'] || $contact['prv']) {
+                                       $relay_to_owner = true;
+                                       $direct_forum_delivery = true;
+                               }
+                       }
+                       if ($relay_to_owner) {
+                               logger('notifier: followup '.$target_item["guid"], LOGGER_DEBUG);
+                               // local followup to remote post
+                               $followup = true;
+                               $public_message = false; // not public
+                               $conversant_str = dbesc($parent['contact-id']);
+                               $recipients = array($parent['contact-id']);
+                               $recipients_followup  = array($parent['contact-id']);
+
+                               //if (!$target_item['private'] && $target_item['wall'] &&
+                               if (!$target_item['private'] &&
+                                       (strlen($target_item['allow_cid'].$target_item['allow_gid'].
+                                               $target_item['deny_cid'].$target_item['deny_gid']) == 0))
+                                       $push_notify = true;
+
+                               if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) {
+
+                                       $push_notify = true;
+
+                                       if ($parent["network"] == NETWORK_OSTATUS) {
+                                               // Distribute the message to the DFRN contacts as if this wasn't a followup since OStatus can't relay comments
+                                               // Currently it is work at progress
+                                               $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s' AND NOT `blocked` AND NOT `pending` AND NOT `archive`",
+                                                       intval($uid),
+                                                       dbesc(NETWORK_DFRN)
+                                               );
+                                               if (DBM::is_result($r)) {
+                                                       foreach ($r as $rr) {
+                                                               $recipients_followup[] = $rr['id'];
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if ($direct_forum_delivery) {
+                                       $push_notify = false;
+                               }
+
+                               logger("Notify ".$target_item["guid"]." via PuSH: ".($push_notify?"Yes":"No"), LOGGER_DEBUG);
+                       } else {
+                               $followup = false;
+
+                               logger('Distributing directly '.$target_item["guid"], LOGGER_DEBUG);
+
+                               // don't send deletions onward for other people's stuff
+
+                               if ($target_item['deleted'] && (! intval($target_item['wall']))) {
+                                       logger('notifier: ignoring delete notification for non-wall item');
+                                       return;
+                               }
+
+                               if ((strlen($parent['allow_cid']))
+                                       || (strlen($parent['allow_gid']))
+                                       || (strlen($parent['deny_cid']))
+                                       || (strlen($parent['deny_gid']))) {
+                                       $public_message = false; // private recipients, not public
+                               }
+
+                               $allow_people = expand_acl($parent['allow_cid']);
+                               $allow_groups = expand_groups(expand_acl($parent['allow_gid']),true);
+                               $deny_people  = expand_acl($parent['deny_cid']);
+                               $deny_groups  = expand_groups(expand_acl($parent['deny_gid']));
+
+                               // if our parent is a public forum (forum_mode == 1), uplink to the origional author causing
+                               // a delivery fork. private groups (forum_mode == 2) do not uplink
+
+                               if ((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) {
+                                       Worker::add($a->queue['priority'], 'Notifier', 'uplink', $item_id);
+                               }
+
+                               $conversants = array();
+
+                               foreach ($items as $item) {
+                                       $recipients[] = $item['contact-id'];
+                                       $conversants[] = $item['contact-id'];
+                                       // pull out additional tagged people to notify (if public message)
+                                       if ($public_message && strlen($item['inform'])) {
+                                               $people = explode(',',$item['inform']);
+                                               foreach ($people as $person) {
+                                                       if (substr($person,0,4) === 'cid:') {
+                                                               $recipients[] = intval(substr($person,4));
+                                                               $conversants[] = intval(substr($person,4));
+                                                       } else {
+                                                               $url_recipients[] = substr($person,4);
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if (count($url_recipients))
+                                       logger('notifier: '.$target_item["guid"].' url_recipients ' . print_r($url_recipients,true));
+
+                               $conversants = array_unique($conversants);
+
+
+                               $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups));
+                               $deny = array_unique(array_merge($deny_people,$deny_groups));
+                               $recipients = array_diff($recipients,$deny);
+
+                               $conversant_str = dbesc(implode(', ',$conversants));
+                       }
+
+                       // If the thread parent is OStatus then do some magic to distribute the messages.
+                       // We have not only to look at the parent, since it could be a Friendica thread.
+                       if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) {
+
+                               $diaspora_delivery = false;
+
+                               logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent[0]['author-link']." - Owner: ".$thr_parent[0]['owner-link'], LOGGER_DEBUG);
+
+                               // Send a salmon to the parent author
+                               $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
+                                       dbesc(normalise_link($thr_parent[0]['author-link'])),
+                                       intval($uid));
+                               if (DBM::is_result($r)) {
+                                       $probed_contact = $r[0];
+                               } else {
+                                       $probed_contact = Probe::uri($thr_parent[0]['author-link']);
+                               }
+
+                               if ($probed_contact["notify"] != "") {
+                                       logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]);
+                                       $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
+                               }
+
+                               // Send a salmon to the parent owner
+                               $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
+                                       dbesc(normalise_link($thr_parent[0]['owner-link'])),
+                                       intval($uid));
+                               if (DBM::is_result($r)) {
+                                       $probed_contact = $r[0];
+                               } else {
+                                       $probed_contact = Probe::uri($thr_parent[0]['owner-link']);
+                               }
+
+                               if ($probed_contact["notify"] != "") {
+                                       logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]);
+                                       $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
+                               }
+
+                               // Send a salmon notification to every person we mentioned in the post
+                               $arr = explode(',',$target_item['tag']);
+                               foreach ($arr as $x) {
+                                       //logger('Checking tag '.$x, LOGGER_DEBUG);
+                                       $matches = null;
+                                       if (preg_match('/@\[url=([^\]]*)\]/',$x,$matches)) {
+                                                       $probed_contact = Probe::uri($matches[1]);
+                                               if ($probed_contact["notify"] != "") {
+                                                       logger('Notify mentioned user '.$probed_contact["url"].': '.$probed_contact["notify"]);
+                                                       $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
+                                               }
+                                       }
+                               }
+
+                               // It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora
+                               $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."')";
+                       } else {
+                               $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."', '".NETWORK_DIASPORA."', '".NETWORK_MAIL."', '".NETWORK_MAIL2."')";
+                       }
+               } else {
+                       $public_message = false;
+               }
+
+               // If this is a public message and pubmail is set on the parent, include all your email contacts
+
+               $mail_disabled = ((function_exists('imap_open') && (!Config::get('system','imap_disabled'))) ? 0 : 1);
+
+               if (! $mail_disabled) {
+                       if ((! strlen($target_item['allow_cid'])) && (! strlen($target_item['allow_gid']))
+                               && (! strlen($target_item['deny_cid'])) && (! strlen($target_item['deny_gid']))
+                               && (intval($target_item['pubmail']))) {
+                               $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s'",
+                                       intval($uid),
+                                       dbesc(NETWORK_MAIL)
+                               );
+                               if (DBM::is_result($r)) {
+                                       foreach ($r as $rr) {
+                                               $recipients[] = $rr['id'];
+                                       }
+                               }
+                       }
+               }
+
+               if ($followup) {
+                       $recip_str = implode(', ', $recipients_followup);
+               } else {
+                       $recip_str = implode(', ', $recipients);
+               }
+               if ($relocate) {
+                       $r = $recipients_relocate;
+               } else {
+                       $r = q("SELECT `id`, `url`, `network`, `self` FROM `contact`
+                               WHERE `id` IN (%s) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra,
+                               dbesc($recip_str)
+                       );
+               }
+
+               // delivery loop
+
+               if (DBM::is_result($r)) {
+                       foreach ($r as $contact) {
+                               if ($contact['self']) {
+                                       continue;
+                               }
+                               logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG);
+
+                               Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true),
+                                               'Delivery', $cmd, $item_id, (int)$contact['id']);
+                       }
+               }
+
+               // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts
+               // They are especially used for notifications to OStatus users that don't follow us.
+
+               if ($slap && count($url_recipients) && ($public_message || $push_notify) && $normal_mode) {
+                       if (!Config::get('system','dfrn_only')) {
+                               foreach ($url_recipients as $url) {
+                                       if ($url) {
+                                               logger('notifier: urldelivery: ' . $url);
+                                               $deliver_status = slapper($owner,$url,$slap);
+                                               /// @TODO Redeliver/queue these items on failure, though there is no contact record
+                                       }
+                               }
+                       }
+               }
+
+
+               if ($public_message) {
+
+                       $r0 = array();
+                       $r1 = array();
+
+                       if ($diaspora_delivery) {
+                               if (!$followup) {
+                                       $r0 = Diaspora::relay_list();
+                               }
+
+                               $r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network`
+                                       FROM `contact` WHERE `network` = '%s' AND `batch` != ''
+                                       AND `uid` = %d AND `rel` != %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` GROUP BY `batch`",
+                                       dbesc(NETWORK_DIASPORA),
+                                       intval($owner['uid']),
+                                       intval(CONTACT_IS_SHARING)
+                               );
+                       }
+
+                       $r2 = q("SELECT `id`, `name`,`network` FROM `contact`
+                               WHERE `network` in ('%s', '%s') AND `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `rel` != %d",
+                               dbesc(NETWORK_DFRN),
+                               dbesc(NETWORK_MAIL2),
+                               intval($owner['uid']),
+                               intval(CONTACT_IS_SHARING)
+                       );
+
+                       $r = array_merge($r2,$r1,$r0);
+
+                       if (DBM::is_result($r)) {
+                               logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG);
+
+                               foreach ($r as $rr) {
+
+                                       // except for Diaspora batch jobs
+                                       // Don't deliver to folks who have already been delivered to
+
+                                       if (($rr['network'] !== NETWORK_DIASPORA) && (in_array($rr['id'],$conversants))) {
+                                               logger('notifier: already delivered id=' . $rr['id']);
+                                               continue;
+                                       }
+
+                                       if ((! $mail) && (! $fsuggest) && (! $followup)) {
+                                               logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]);
+                                               Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true),
+                                                               'Delivery', $cmd, $item_id, (int)$rr['id']);
+                                       }
+                               }
+                       }
+
+                       $push_notify = true;
+
+               }
+
+               // Notify PuSH subscribers (Used for OStatus distribution of regular posts)
+               if ($push_notify) {
+                       // Set push flag for PuSH subscribers to this topic,
+                       // they will be notified in queue.php
+                       q("UPDATE `push_subscriber` SET `push` = 1 ".
+                         "WHERE `nickname` = '%s' AND `push` = 0", dbesc($owner['nickname']));
+
+                       logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG);
+
+                       // Handling the pubsubhubbub requests
+                       Worker::add(array('priority' => PRIORITY_HIGH, 'created' => $a->queue['created'], 'dont_fork' => true),
+                                       'PubSubPublish');
+               }
+
+               logger('notifier: calling hooks', LOGGER_DEBUG);
+
+               if ($normal_mode) {
+                       call_hooks('notifier_normal',$target_item);
+               }
+
+               call_hooks('notifier_end',$target_item);
+
+               return;
+       }
+}