Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

679 lines
21 KiB

10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
6 years ago
11 years ago
11 years ago
11 years ago
6 years ago
10 years ago
6 years ago
10 years ago
11 years ago
11 years ago
6 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
6 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
6 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. <?php
  2. require_once("boot.php");
  3. require_once('include/queue_fn.php');
  4. require_once('include/html2plain.php');
  5. require_once("include/Scrape.php");
  6. require_once('include/diaspora.php');
  7. require_once("include/ostatus.php");
  8. require_once('include/salmon.php');
  9. /*
  10. * This file was at one time responsible for doing all deliveries, but this caused
  11. * big problems when the process was killed or stalled during the delivery process.
  12. * It now invokes separate queues that are delivering via delivery.php and pubsubpublish.php.
  13. */
  14. /*
  15. * The notifier is typically called with:
  16. *
  17. * proc_run('php', "include/notifier.php", COMMAND, ITEM_ID);
  18. *
  19. * where COMMAND is one of the following:
  20. *
  21. * activity (in diaspora.php, dfrn_confirm.php, profiles.php)
  22. * comment-import (in diaspora.php, items.php)
  23. * comment-new (in item.php)
  24. * drop (in diaspora.php, items.php, photos.php)
  25. * edit_post (in item.php)
  26. * event (in events.php)
  27. * expire (in items.php)
  28. * like (in like.php, poke.php)
  29. * mail (in message.php)
  30. * suggest (in fsuggest.php)
  31. * tag (in photos.php, poke.php, tagger.php)
  32. * tgroup (in items.php)
  33. * wall-new (in photos.php, item.php)
  34. * removeme (in Contact.php)
  35. * relocate (in uimport.php)
  36. *
  37. * and ITEM_ID is the id of the item in the database that needs to be sent to others.
  38. */
  39. function notifier_run(&$argv, &$argc){
  40. global $a, $db;
  41. if(is_null($a)){
  42. $a = new App;
  43. }
  44. if(is_null($db)) {
  45. @include(".htconfig.php");
  46. require_once("include/dba.php");
  47. $db = new dba($db_host, $db_user, $db_pass, $db_data);
  48. unset($db_host, $db_user, $db_pass, $db_data);
  49. }
  50. require_once("include/session.php");
  51. require_once("include/datetime.php");
  52. require_once('include/items.php');
  53. require_once('include/bbcode.php');
  54. require_once('include/email.php');
  55. load_config('config');
  56. load_config('system');
  57. load_hooks();
  58. if($argc < 3)
  59. return;
  60. $a->set_baseurl(get_config('system','url'));
  61. logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
  62. $cmd = $argv[1];
  63. switch($cmd) {
  64. case 'mail':
  65. default:
  66. $item_id = intval($argv[2]);
  67. if(! $item_id){
  68. return;
  69. }
  70. break;
  71. }
  72. $expire = false;
  73. $mail = false;
  74. $fsuggest = false;
  75. $relocate = false;
  76. $top_level = false;
  77. $recipients = array();
  78. $url_recipients = array();
  79. $normal_mode = true;
  80. if($cmd === 'mail') {
  81. $normal_mode = false;
  82. $mail = true;
  83. $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
  84. intval($item_id)
  85. );
  86. if(! count($message)){
  87. return;
  88. }
  89. $uid = $message[0]['uid'];
  90. $recipients[] = $message[0]['contact-id'];
  91. $item = $message[0];
  92. }
  93. elseif($cmd === 'expire') {
  94. $normal_mode = false;
  95. $expire = true;
  96. $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
  97. AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 10 MINUTE",
  98. intval($item_id)
  99. );
  100. $uid = $item_id;
  101. $item_id = 0;
  102. if(! count($items))
  103. return;
  104. }
  105. elseif($cmd === 'suggest') {
  106. $normal_mode = false;
  107. $fsuggest = true;
  108. $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
  109. intval($item_id)
  110. );
  111. if(! count($suggest))
  112. return;
  113. $uid = $suggest[0]['uid'];
  114. $recipients[] = $suggest[0]['cid'];
  115. $item = $suggest[0];
  116. } elseif($cmd === 'removeme') {
  117. $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
  118. `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
  119. `user`.`page-flags`, `user`.`prvnets`, `user`.`guid`
  120. FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
  121. WHERE `contact`.`uid` = %d AND `contact`.`self` LIMIT 1",
  122. intval($item_id));
  123. if (!$r)
  124. return;
  125. $user = $r[0];
  126. $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($item_id));
  127. if (!$r)
  128. return;
  129. $self = $r[0];
  130. $r = q("SELECT * FROM `contact` WHERE NOT `self` AND `uid` = %d", intval($item_id));
  131. if(!$r)
  132. return;
  133. require_once('include/Contact.php');
  134. foreach($r as $contact) {
  135. terminate_friendship($user, $self, $contact);
  136. }
  137. return;
  138. } elseif($cmd === 'relocate') {
  139. $normal_mode = false;
  140. $relocate = true;
  141. $uid = $item_id;
  142. $recipients_relocate = q("SELECT * FROM contact WHERE uid = %d AND self = 0 AND network = '%s'" , intval($uid), NETWORK_DFRN);
  143. } else {
  144. // find ancestors
  145. $r = q("SELECT * FROM `item` WHERE `id` = %d and visible = 1 and moderated = 0 LIMIT 1",
  146. intval($item_id)
  147. );
  148. if((! count($r)) || (! intval($r[0]['parent']))) {
  149. return;
  150. }
  151. $target_item = $r[0];
  152. $parent_id = intval($r[0]['parent']);
  153. $uid = $r[0]['uid'];
  154. $updated = $r[0]['edited'];
  155. $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer`
  156. FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d and visible = 1 and moderated = 0 ORDER BY `id` ASC",
  157. intval($parent_id)
  158. );
  159. if(! count($items)) {
  160. return;
  161. }
  162. // avoid race condition with deleting entries
  163. if($items[0]['deleted']) {
  164. foreach($items as $item)
  165. $item['deleted'] = 1;
  166. }
  167. if((count($items) == 1) && ($items[0]['id'] === $target_item['id']) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
  168. logger('notifier: top level post');
  169. $top_level = true;
  170. }
  171. }
  172. $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
  173. `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
  174. `user`.`page-flags`, `user`.`prvnets`
  175. FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
  176. WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
  177. intval($uid)
  178. );
  179. if(! count($r))
  180. return;
  181. $owner = $r[0];
  182. $walltowall = ((($top_level) && ($owner['id'] != $items[0]['contact-id'])) ? true : false);
  183. $hub = get_config('system','huburl');
  184. // If this is a public conversation, notify the feed hub
  185. $public_message = true;
  186. // Do a PuSH
  187. $push_notify = false;
  188. // fill this in with a single salmon slap if applicable
  189. $slap = '';
  190. if(! ($mail || $fsuggest || $relocate)) {
  191. $slap = ostatus::salmon($target_item,$owner);
  192. require_once('include/group.php');
  193. $parent = $items[0];
  194. $thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
  195. dbesc($target_item["thr-parent"]), intval($target_item["uid"]));
  196. logger('Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG);
  197. // This is IMPORTANT!!!!
  198. // We will only send a "notify owner to relay" or followup message if the referenced post
  199. // originated on our system by virtue of having our hostname somewhere
  200. // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere.
  201. // if $parent['wall'] == 1 we will already have the parent message in our array
  202. // and we will relay the whole lot.
  203. // expire sends an entire group of expire messages and cannot be forwarded.
  204. // However the conversation owner will be a part of the conversation and will
  205. // be notified during this run.
  206. // Other DFRN conversation members will be alerted during polled updates.
  207. // Diaspora members currently are not notified of expirations, and other networks have
  208. // either limited or no ability to process deletions. We should at least fix Diaspora
  209. // by stringing togther an array of retractions and sending them onward.
  210. $localhost = str_replace('www.','',$a->get_hostname());
  211. if(strpos($localhost,':'))
  212. $localhost = substr($localhost,0,strpos($localhost,':'));
  213. /**
  214. *
  215. * Be VERY CAREFUL if you make any changes to the following several lines. Seemingly innocuous changes
  216. * have been known to cause runaway conditions which affected several servers, along with
  217. * permissions issues.
  218. *
  219. */
  220. $relay_to_owner = false;
  221. if(!$top_level && ($parent['wall'] == 0) && !$expire && (stristr($target_item['uri'],$localhost))) {
  222. $relay_to_owner = true;
  223. }
  224. if(($cmd === 'uplink') && (intval($parent['forum_mode']) == 1) && !$top_level) {
  225. $relay_to_owner = true;
  226. }
  227. // until the 'origin' flag has been in use for several months
  228. // we will just use it as a fallback test
  229. // later we will be able to use it as the primary test of whether or not to relay.
  230. if(! $target_item['origin'])
  231. $relay_to_owner = false;
  232. if($parent['origin'])
  233. $relay_to_owner = false;
  234. if($relay_to_owner) {
  235. logger('notifier: followup '.$target_item["guid"], LOGGER_DEBUG);
  236. // local followup to remote post
  237. $followup = true;
  238. $public_message = false; // not public
  239. $conversant_str = dbesc($parent['contact-id']);
  240. $recipients = array($parent['contact-id']);
  241. $recipients_followup = array($parent['contact-id']);
  242. //if (!$target_item['private'] AND $target_item['wall'] AND
  243. if (!$target_item['private'] AND
  244. (strlen($target_item['allow_cid'].$target_item['allow_gid'].
  245. $target_item['deny_cid'].$target_item['deny_gid']) == 0))
  246. $push_notify = true;
  247. if (($thr_parent AND ($thr_parent[0]['network'] == NETWORK_OSTATUS)) OR ($parent['network'] == NETWORK_OSTATUS)) {
  248. $push_notify = true;
  249. if ($parent["network"] == NETWORK_OSTATUS) {
  250. // Distribute the message to the DFRN contacts as if this wasn't a followup since OStatus can't relay comments
  251. // Currently it is work at progress
  252. $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s' AND NOT `blocked` AND NOT `pending` AND NOT `archive`",
  253. intval($uid),
  254. dbesc(NETWORK_DFRN)
  255. );
  256. if(count($r))
  257. foreach($r as $rr)
  258. $recipients_followup[] = $rr['id'];
  259. }
  260. }
  261. logger("Notify ".$target_item["guid"]." via PuSH: ".($push_notify?"Yes":"No"), LOGGER_DEBUG);
  262. } else {
  263. $followup = false;
  264. logger('Distributing directly '.$target_item["guid"], LOGGER_DEBUG);
  265. // don't send deletions onward for other people's stuff
  266. if($target_item['deleted'] && (! intval($target_item['wall']))) {
  267. logger('notifier: ignoring delete notification for non-wall item');
  268. return;
  269. }
  270. if((strlen($parent['allow_cid']))
  271. || (strlen($parent['allow_gid']))
  272. || (strlen($parent['deny_cid']))
  273. || (strlen($parent['deny_gid']))) {
  274. $public_message = false; // private recipients, not public
  275. }
  276. $allow_people = expand_acl($parent['allow_cid']);
  277. $allow_groups = expand_groups(expand_acl($parent['allow_gid']),true);
  278. $deny_people = expand_acl($parent['deny_cid']);
  279. $deny_groups = expand_groups(expand_acl($parent['deny_gid']));
  280. // if our parent is a public forum (forum_mode == 1), uplink to the origional author causing
  281. // a delivery fork. private groups (forum_mode == 2) do not uplink
  282. if((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) {
  283. proc_run('php','include/notifier.php','uplink',$item_id);
  284. }
  285. $conversants = array();
  286. foreach($items as $item) {
  287. $recipients[] = $item['contact-id'];
  288. $conversants[] = $item['contact-id'];
  289. // pull out additional tagged people to notify (if public message)
  290. if($public_message && strlen($item['inform'])) {
  291. $people = explode(',',$item['inform']);
  292. foreach($people as $person) {
  293. if(substr($person,0,4) === 'cid:') {
  294. $recipients[] = intval(substr($person,4));
  295. $conversants[] = intval(substr($person,4));
  296. }
  297. else {
  298. $url_recipients[] = substr($person,4);
  299. }
  300. }
  301. }
  302. }
  303. if (count($url_recipients))
  304. logger('notifier: '.$target_item["guid"].' url_recipients ' . print_r($url_recipients,true));
  305. $conversants = array_unique($conversants);
  306. $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups));
  307. $deny = array_unique(array_merge($deny_people,$deny_groups));
  308. $recipients = array_diff($recipients,$deny);
  309. $conversant_str = dbesc(implode(', ',$conversants));
  310. }
  311. // If the thread parent is OStatus then do some magic to distribute the messages.
  312. // We have not only to look at the parent, since it could be a Friendica thread.
  313. if (($thr_parent AND ($thr_parent[0]['network'] == NETWORK_OSTATUS)) OR ($parent['network'] == NETWORK_OSTATUS)) {
  314. logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent[0]['author-link']." - Owner: ".$thr_parent[0]['owner-link'], LOGGER_DEBUG);
  315. // Send a salmon to the parent author
  316. $r = q("SELECT `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
  317. dbesc(normalise_link($thr_parent[0]['author-link'])),
  318. intval($uid));
  319. if ($r)
  320. $probed_contact = $r[0];
  321. else
  322. $probed_contact = probe_url($thr_parent[0]['author-link']);
  323. if ($probed_contact["notify"] != "") {
  324. logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]);
  325. $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
  326. }
  327. // Send a salmon to the parent owner
  328. $r = q("SELECT `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
  329. dbesc(normalise_link($thr_parent[0]['owner-link'])),
  330. intval($uid));
  331. if ($r)
  332. $probed_contact = $r[0];
  333. else
  334. $probed_contact = probe_url($thr_parent[0]['owner-link']);
  335. if ($probed_contact["notify"] != "") {
  336. logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]);
  337. $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
  338. }
  339. // Send a salmon notification to every person we mentioned in the post
  340. $arr = explode(',',$target_item['tag']);
  341. foreach($arr as $x) {
  342. //logger('Checking tag '.$x, LOGGER_DEBUG);
  343. $matches = null;
  344. if(preg_match('/@\[url=([^\]]*)\]/',$x,$matches)) {
  345. $probed_contact = probe_url($matches[1]);
  346. if ($probed_contact["notify"] != "") {
  347. logger('Notify mentioned user '.$probed_contact["url"].': '.$probed_contact["notify"]);
  348. $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
  349. }
  350. }
  351. }
  352. // It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora
  353. $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."')";
  354. } else
  355. $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."', '".NETWORK_DIASPORA."', '".NETWORK_MAIL."', '".NETWORK_MAIL2."')";
  356. $r = q("SELECT * FROM `contact` WHERE `id` IN ($conversant_str) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra);
  357. if(count($r))
  358. $contacts = $r;
  359. } else
  360. $public_message = false;
  361. // If this is a public message and pubmail is set on the parent, include all your email contacts
  362. $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
  363. if(! $mail_disabled) {
  364. if((! strlen($target_item['allow_cid'])) && (! strlen($target_item['allow_gid']))
  365. && (! strlen($target_item['deny_cid'])) && (! strlen($target_item['deny_gid']))
  366. && (intval($target_item['pubmail']))) {
  367. $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s'",
  368. intval($uid),
  369. dbesc(NETWORK_MAIL)
  370. );
  371. if(count($r)) {
  372. foreach($r as $rr)
  373. $recipients[] = $rr['id'];
  374. }
  375. }
  376. }
  377. if($followup)
  378. $recip_str = implode(', ', $recipients_followup);
  379. else
  380. $recip_str = implode(', ', $recipients);
  381. if ($relocate)
  382. $r = $recipients_relocate;
  383. else
  384. $r = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND NOT `blocked` AND NOT `pending` AND NOT `archive`",
  385. dbesc($recip_str)
  386. );
  387. $interval = ((get_config('system','delivery_interval') === false) ? 2 : intval(get_config('system','delivery_interval')));
  388. // If we are using the worker we don't need a delivery interval
  389. if (get_config("system", "worker"))
  390. $interval = false;
  391. // delivery loop
  392. if(count($r)) {
  393. foreach($r as $contact) {
  394. if(!$contact['self']) {
  395. if(($contact['network'] === NETWORK_DIASPORA) && ($public_message))
  396. continue;
  397. q("INSERT INTO `deliverq` (`cmd`,`item`,`contact`) VALUES ('%s', %d, %d)",
  398. dbesc($cmd),
  399. intval($item_id),
  400. intval($contact['id'])
  401. );
  402. }
  403. }
  404. // This controls the number of deliveries to execute with each separate delivery process.
  405. // By default we'll perform one delivery per process. Assuming a hostile shared hosting
  406. // provider, this provides the greatest chance of deliveries if processes start getting
  407. // killed. We can also space them out with the delivery_interval to also help avoid them
  408. // getting whacked.
  409. // If $deliveries_per_process > 1, we will chain this number of multiple deliveries
  410. // together into a single process. This will reduce the overall number of processes
  411. // spawned for each delivery, but they will run longer.
  412. // When using the workerqueue, we don't need this functionality.
  413. $deliveries_per_process = intval(get_config('system','delivery_batch_count'));
  414. if (($deliveries_per_process <= 0) OR get_config("system", "worker"))
  415. $deliveries_per_process = 1;
  416. $this_batch = array();
  417. for($x = 0; $x < count($r); $x ++) {
  418. $contact = $r[$x];
  419. if($contact['self'])
  420. continue;
  421. logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG);
  422. // potentially more than one recipient. Start a new process and space them out a bit.
  423. // we will deliver single recipient types of message and email recipients here.
  424. $this_batch[] = $contact['id'];
  425. if(count($this_batch) >= $deliveries_per_process) {
  426. proc_run('php','include/delivery.php',$cmd,$item_id,$this_batch);
  427. $this_batch = array();
  428. if($interval)
  429. @time_sleep_until(microtime(true) + (float) $interval);
  430. }
  431. continue;
  432. }
  433. // be sure to pick up any stragglers
  434. if(count($this_batch))
  435. proc_run('php','include/delivery.php',$cmd,$item_id,$this_batch);
  436. }
  437. // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts
  438. // They are especially used for notifications to OStatus users that don't follow us.
  439. if($slap && count($url_recipients) && ($public_message || $push_notify) && $normal_mode) {
  440. if(!get_config('system','dfrn_only')) {
  441. foreach($url_recipients as $url) {
  442. if($url) {
  443. logger('notifier: urldelivery: ' . $url);
  444. $deliver_status = slapper($owner,$url,$slap);
  445. /// @TODO Redeliver/queue these items on failure, though there is no contact record
  446. }
  447. }
  448. }
  449. }
  450. if($public_message) {
  451. if (!$followup)
  452. $r0 = diaspora::relay_list();
  453. else
  454. $r0 = array();
  455. $r1 = q("SELECT DISTINCT(`batch`), `id`, `name`,`network` FROM `contact` WHERE `network` = '%s'
  456. AND `uid` = %d AND `rel` != %d group by `batch` ORDER BY rand() ",
  457. dbesc(NETWORK_DIASPORA),
  458. intval($owner['uid']),
  459. intval(CONTACT_IS_SHARING)
  460. );
  461. $r2 = q("SELECT `id`, `name`,`network` FROM `contact`
  462. WHERE `network` in ( '%s', '%s') AND `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `archive`
  463. AND `rel` != %d order by rand() ",
  464. dbesc(NETWORK_DFRN),
  465. dbesc(NETWORK_MAIL2),
  466. intval($owner['uid']),
  467. intval(CONTACT_IS_SHARING)
  468. );
  469. $r = array_merge($r2,$r1,$r0);
  470. if(count($r)) {
  471. logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG);
  472. // throw everything into the queue in case we get killed
  473. foreach($r as $rr) {
  474. if((! $mail) && (! $fsuggest) && (! $followup)) {
  475. q("insert into deliverq ( `cmd`,`item`,`contact` ) values ('%s', %d, %d )",
  476. dbesc($cmd),
  477. intval($item_id),
  478. intval($rr['id'])
  479. );
  480. }
  481. }
  482. foreach($r as $rr) {
  483. // except for Diaspora batch jobs
  484. // Don't deliver to folks who have already been delivered to
  485. if(($rr['network'] !== NETWORK_DIASPORA) && (in_array($rr['id'],$conversants))) {
  486. logger('notifier: already delivered id=' . $rr['id']);
  487. continue;
  488. }
  489. if((! $mail) && (! $fsuggest) && (! $followup)) {
  490. logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]);
  491. proc_run('php','include/delivery.php',$cmd,$item_id,$rr['id']);
  492. if($interval)
  493. @time_sleep_until(microtime(true) + (float) $interval);
  494. }
  495. }
  496. }
  497. $push_notify = true;
  498. }
  499. // Notify PuSH subscribers (Used for OStatus distribution of regular posts)
  500. if($push_notify AND strlen($hub)) {
  501. $hubs = explode(',', $hub);
  502. if(count($hubs)) {
  503. foreach($hubs as $h) {
  504. $h = trim($h);
  505. if(! strlen($h))
  506. continue;
  507. if ($h === '[internal]') {
  508. // Set push flag for PuSH subscribers to this topic,
  509. // they will be notified in queue.php
  510. q("UPDATE `push_subscriber` SET `push` = 1 " .
  511. "WHERE `nickname` = '%s'", dbesc($owner['nickname']));
  512. logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG);
  513. } else {
  514. $params = 'hub.mode=publish&hub.url=' . urlencode( $a->get_baseurl() . '/dfrn_poll/' . $owner['nickname'] );
  515. post_url($h,$params);
  516. logger('publish for item '.$item_id.' ' . $h . ' ' . $params . ' returned ' . $a->get_curl_code());
  517. }
  518. if(count($hubs) > 1)
  519. sleep(7); // try and avoid multiple hubs responding at precisely the same time
  520. }
  521. }
  522. // Handling the pubsubhubbub requests
  523. proc_run('php','include/pubsubpublish.php');
  524. }
  525. logger('notifier: calling hooks', LOGGER_DEBUG);
  526. if($normal_mode)
  527. call_hooks('notifier_normal',$target_item);
  528. call_hooks('notifier_end',$target_item);
  529. return;
  530. }
  531. if (array_search(__file__,get_included_files())===0){
  532. notifier_run($_SERVER["argv"],$_SERVER["argc"]);
  533. killme();
  534. }