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.

698 lines
20 KiB

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
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 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
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
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
  1. <?php
  2. require_once("boot.php");
  3. function notifier_run($argv, $argc){
  4. global $a, $db;
  5. if(is_null($a)){
  6. $a = new App;
  7. }
  8. if(is_null($db)) {
  9. @include(".htconfig.php");
  10. require_once("dba.php");
  11. $db = new dba($db_host, $db_user, $db_pass, $db_data);
  12. unset($db_host, $db_user, $db_pass, $db_data);
  13. }
  14. require_once("session.php");
  15. require_once("datetime.php");
  16. require_once('include/items.php');
  17. require_once('include/bbcode.php');
  18. load_config('config');
  19. load_config('system');
  20. load_hooks();
  21. if($argc < 3)
  22. return;
  23. $a->set_baseurl(get_config('system','url'));
  24. logger('notifier: invoked: ' . print_r($argv,true));
  25. $cmd = $argv[1];
  26. switch($cmd) {
  27. case 'mail':
  28. default:
  29. $item_id = intval($argv[2]);
  30. if(! $item_id){
  31. return;
  32. }
  33. break;
  34. }
  35. $expire = false;
  36. $mail = false;
  37. $fsuggest = false;
  38. $top_level = false;
  39. $recipients = array();
  40. $url_recipients = array();
  41. $normal_mode = true;
  42. if($cmd === 'mail') {
  43. $normal_mode = false;
  44. $mail = true;
  45. $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
  46. intval($item_id)
  47. );
  48. if(! count($message)){
  49. return;
  50. }
  51. $uid = $message[0]['uid'];
  52. $recipients[] = $message[0]['contact-id'];
  53. $item = $message[0];
  54. }
  55. elseif($cmd === 'expire') {
  56. $normal_mode = false;
  57. $expire = true;
  58. $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
  59. AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP - INTERVAL 10 MINUTE",
  60. intval($item_id)
  61. );
  62. $uid = $item_id;
  63. $item_id = 0;
  64. if(! count($items))
  65. return;
  66. }
  67. elseif($cmd === 'suggest') {
  68. $normal_mode = false;
  69. $fsuggest = true;
  70. $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
  71. intval($item_id)
  72. );
  73. if(! count($suggest))
  74. return;
  75. $uid = $suggest[0]['uid'];
  76. $recipients[] = $suggest[0]['cid'];
  77. $item = $suggest[0];
  78. }
  79. else {
  80. // find ancestors
  81. $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1",
  82. intval($item_id)
  83. );
  84. if((! count($r)) || (! intval($r[0]['parent']))) {
  85. return;
  86. }
  87. $target_item = $r[0];
  88. $parent_id = intval($r[0]['parent']);
  89. $uid = $r[0]['uid'];
  90. $updated = $r[0]['edited'];
  91. $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer`
  92. FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d ORDER BY `id` ASC",
  93. intval($parent_id)
  94. );
  95. if(! count($items)) {
  96. return;
  97. }
  98. // avoid race condition with deleting entries
  99. if($items[0]['deleted']) {
  100. foreach($items as $item)
  101. $item['deleted'] = 1;
  102. }
  103. if((count($items) == 1) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
  104. logger('notifier: top level post');
  105. $top_level = true;
  106. }
  107. }
  108. $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
  109. `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
  110. `user`.`page-flags`, `user`.`prvnets`
  111. FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
  112. WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
  113. intval($uid)
  114. );
  115. if(! count($r))
  116. return;
  117. $owner = $r[0];
  118. $walltowall = ((($top_level) && ($owner['id'] != $items[0]['contact-id'])) ? true : false);
  119. $hub = get_config('system','huburl');
  120. // If this is a public conversation, notify the feed hub
  121. $public_message = true;
  122. // fill this in with a single salmon slap if applicable
  123. $slap = '';
  124. if(! ($mail || $fsuggest)) {
  125. require_once('include/group.php');
  126. $parent = $items[0];
  127. // This is IMPORTANT!!!!
  128. // We will only send a "notify owner to relay" or followup message if the referenced post
  129. // originated on our system by virtue of having our hostname somewhere
  130. // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere.
  131. // if $parent['wall'] == 1 we will already have the parent message in our array
  132. // and we will relay the whole lot.
  133. // expire sends an entire group of expire messages and cannot be forwarded.
  134. // However the conversation owner will be a part of the conversation and will
  135. // be notified during this run.
  136. // Other DFRN conversation members will be alerted during polled updates.
  137. // Diaspora members currently are not notified of expirations, and other networks have
  138. // either limited or no ability to process deletions. We should at least fix Diaspora
  139. // by stringing togther an array of retractions and sending them onward.
  140. $localhost = $a->get_hostname();
  141. if(strpos($localhost,':'))
  142. $localhost = substr($localhost,0,strpos($localhost,':'));
  143. /**
  144. *
  145. * Be VERY CAREFUL if you make any changes to the following line. Seemingly innocuous changes
  146. * have been known to cause runaway conditions which affected several servers, along with
  147. * permissions issues.
  148. *
  149. */
  150. if((! $top_level) && ($parent['wall'] == 0) && (! $expire) && (stristr($target_item['uri'],$localhost))) {
  151. // local followup to remote post
  152. $followup = true;
  153. $public_message = false; // not public
  154. $conversant_str = dbesc($parent['contact-id']);
  155. }
  156. else {
  157. $followup = false;
  158. if((strlen($parent['allow_cid']))
  159. || (strlen($parent['allow_gid']))
  160. || (strlen($parent['deny_cid']))
  161. || (strlen($parent['deny_gid']))) {
  162. $public_message = false; // private recipients, not public
  163. }
  164. $allow_people = expand_acl($parent['allow_cid']);
  165. $allow_groups = expand_groups(expand_acl($parent['allow_gid']));
  166. $deny_people = expand_acl($parent['deny_cid']);
  167. $deny_groups = expand_groups(expand_acl($parent['deny_gid']));
  168. $conversants = array();
  169. foreach($items as $item) {
  170. $recipients[] = $item['contact-id'];
  171. $conversants[] = $item['contact-id'];
  172. // pull out additional tagged people to notify (if public message)
  173. if($public_message && strlen($item['inform'])) {
  174. $people = explode(',',$item['inform']);
  175. foreach($people as $person) {
  176. if(substr($person,0,4) === 'cid:') {
  177. $recipients[] = intval(substr($person,4));
  178. $conversants[] = intval(substr($person,4));
  179. }
  180. else {
  181. $url_recipients[] = substr($person,4);
  182. }
  183. }
  184. }
  185. }
  186. logger('notifier: url_recipients' . print_r($url_recipients,true));
  187. $conversants = array_unique($conversants);
  188. $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups));
  189. $deny = array_unique(array_merge($deny_people,$deny_groups));
  190. $recipients = array_diff($recipients,$deny);
  191. $conversant_str = dbesc(implode(', ',$conversants));
  192. }
  193. $r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0");
  194. if(count($r))
  195. $contacts = $r;
  196. }
  197. $feed_template = get_markup_template('atom_feed.tpl');
  198. $mail_template = get_markup_template('atom_mail.tpl');
  199. $atom = '';
  200. $slaps = array();
  201. $hubxml = feed_hublinks();
  202. $birthday = feed_birthday($owner['uid'],$owner['timezone']);
  203. if(strlen($birthday))
  204. $birthday = '<dfrn:birthday>' . xmlify($birthday) . '</dfrn:birthday>';
  205. $atom .= replace_macros($feed_template, array(
  206. '$version' => xmlify(FRIENDIKA_VERSION),
  207. '$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner['nickname'] ),
  208. '$feed_title' => xmlify($owner['name']),
  209. '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', $updated . '+00:00' , ATOM_TIME)) ,
  210. '$hub' => $hubxml,
  211. '$salmon' => '', // private feed, we don't use salmon here
  212. '$name' => xmlify($owner['name']),
  213. '$profile_page' => xmlify($owner['url']),
  214. '$photo' => xmlify($owner['photo']),
  215. '$thumb' => xmlify($owner['thumb']),
  216. '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) ,
  217. '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , ATOM_TIME)) ,
  218. '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) ,
  219. '$birthday' => $birthday
  220. ));
  221. if($mail) {
  222. $public_message = false; // mail is not public
  223. $body = fix_private_photos($item['body'],$owner['uid']);
  224. $atom .= replace_macros($mail_template, array(
  225. '$name' => xmlify($owner['name']),
  226. '$profile_page' => xmlify($owner['url']),
  227. '$thumb' => xmlify($owner['thumb']),
  228. '$item_id' => xmlify($item['uri']),
  229. '$subject' => xmlify($item['title']),
  230. '$created' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
  231. '$content' => xmlify($body),
  232. '$parent_id' => xmlify($item['parent-uri'])
  233. ));
  234. }
  235. elseif($fsuggest) {
  236. $public_message = false; // suggestions are not public
  237. $sugg_template = get_markup_template('atom_suggest.tpl');
  238. $atom .= replace_macros($sugg_template, array(
  239. '$name' => xmlify($item['name']),
  240. '$url' => xmlify($item['url']),
  241. '$photo' => xmlify($item['photo']),
  242. '$request' => xmlify($item['request']),
  243. '$note' => xmlify($item['note'])
  244. ));
  245. // We don't need this any more
  246. q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1",
  247. intval($item['id'])
  248. );
  249. }
  250. else {
  251. if($followup) {
  252. foreach($items as $item) { // there is only one item
  253. if(! $item['parent'])
  254. continue;
  255. if($item['id'] == $item_id) {
  256. logger('notifier: followup: item: ' . print_r($item,true), LOGGER_DATA);
  257. $slap = atom_entry($item,'html',$owner,$owner,false);
  258. $atom .= atom_entry($item,'text',$owner,$owner,false);
  259. }
  260. }
  261. }
  262. else {
  263. foreach($items as $item) {
  264. if(! $item['parent'])
  265. continue;
  266. // private emails may be in included in public conversations. Filter them.
  267. if(($public_message) && $item['private'])
  268. continue;
  269. $contact = get_item_contact($item,$contacts);
  270. if(! $contact)
  271. continue;
  272. $atom .= atom_entry($item,'text',$contact,$owner,true);
  273. if(($top_level) && ($public_message) && ($item['author-link'] === $item['owner-link']) && (! $expire))
  274. $slaps[] = atom_entry($item,'html',$contact,$owner,true);
  275. }
  276. }
  277. }
  278. $atom .= '</feed>' . "\r\n";
  279. logger('notifier: ' . $atom, LOGGER_DATA);
  280. logger('notifier: slaps: ' . print_r($slaps,true), LOGGER_DATA);
  281. // If this is a public message and pubmail is set on the parent, include all your email contacts
  282. $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
  283. if(! $mail_disabled) {
  284. if((! strlen($target_item['allow_cid'])) && (! strlen($target_item['allow_gid']))
  285. && (! strlen($target_item['deny_cid'])) && (! strlen($target_item['deny_gid']))
  286. && (intval($target_item['pubmail']))) {
  287. $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `network` = '%s'",
  288. intval($uid),
  289. dbesc(NETWORK_MAIL)
  290. );
  291. if(count($r)) {
  292. foreach($r as $rr)
  293. $recipients[] = $rr['id'];
  294. }
  295. }
  296. }
  297. if($followup)
  298. $recip_str = $parent['contact-id'];
  299. else
  300. $recip_str = implode(', ', $recipients);
  301. $r = q("SELECT * FROM `contact` WHERE `id` IN ( %s ) AND `blocked` = 0 AND `pending` = 0 ",
  302. dbesc($recip_str)
  303. );
  304. require_once('include/salmon.php');
  305. $interval = ((get_config('system','delivery_interval') === false) ? 2 : intval(get_config('system','delivery_interval')));
  306. // delivery loop
  307. if(count($r)) {
  308. foreach($r as $contact) {
  309. if((! $mail) && (! $fsuggest) && (! $followup) && (! $contact['self'])) {
  310. q("insert into deliverq ( `cmd`,`item`,`contact` ) values ('%s', %d, %d )",
  311. dbesc($cmd),
  312. intval($item_id),
  313. intval($contact['id'])
  314. );
  315. }
  316. }
  317. foreach($r as $contact) {
  318. if($contact['self'])
  319. continue;
  320. // potentially more than one recipient. Start a new process and space them out a bit.
  321. // we will deliver single recipient types of message and email receipients here.
  322. if((! $mail) && (! $fsuggest) && (! $followup)) {
  323. proc_run('php','include/delivery.php',$cmd,$item_id,$contact['id']);
  324. if($interval)
  325. @time_sleep_until(microtime(true) + (float) $interval);
  326. continue;
  327. }
  328. $deliver_status = 0;
  329. logger("main delivery by notifier: followup=$followup mail=$mail fsuggest=$fsuggest");
  330. switch($contact['network']) {
  331. case NETWORK_DFRN:
  332. logger('notifier: dfrndelivery: ' . $contact['name']);
  333. $deliver_status = dfrn_deliver($owner,$contact,$atom);
  334. logger('notifier: dfrn_delivery returns ' . $deliver_status);
  335. if($deliver_status == (-1)) {
  336. logger('notifier: delivery failed: queuing message');
  337. // queue message for redelivery
  338. q("INSERT INTO `queue` ( `cid`, `created`, `last`, `content`)
  339. VALUES ( %d, '%s', '%s', '%s') ",
  340. intval($contact['id']),
  341. dbesc(datetime_convert()),
  342. dbesc(datetime_convert()),
  343. dbesc($atom)
  344. );
  345. }
  346. break;
  347. case NETWORK_OSTATUS:
  348. // Do not send to otatus if we are not configured to send to public networks
  349. if($owner['prvnets'])
  350. break;
  351. if(get_config('system','ostatus_disabled') || get_config('system','dfrn_only'))
  352. break;
  353. if($followup && $contact['notify']) {
  354. logger('notifier: slapdelivery: ' . $contact['name']);
  355. $deliver_status = slapper($owner,$contact['notify'],$slap);
  356. if($deliver_status == (-1)) {
  357. // queue message for redelivery
  358. q("INSERT INTO `queue` ( `cid`, `created`, `last`, `content`)
  359. VALUES ( %d, '%s', '%s', '%s') ",
  360. intval($contact['id']),
  361. dbesc(datetime_convert()),
  362. dbesc(datetime_convert()),
  363. dbesc($slap)
  364. );
  365. }
  366. }
  367. else {
  368. // only send salmon if public - e.g. if it's ok to notify
  369. // a public hub, it's ok to send a salmon
  370. if((count($slaps)) && ($public_message) && (! $expire)) {
  371. logger('notifier: slapdelivery: ' . $contact['name']);
  372. foreach($slaps as $slappy) {
  373. if($contact['notify']) {
  374. $deliver_status = slapper($owner,$contact['notify'],$slappy);
  375. if($deliver_status == (-1)) {
  376. // queue message for redelivery
  377. q("INSERT INTO `queue` ( `cid`, `created`, `last`, `content`)
  378. VALUES ( %d, '%s', '%s', '%s') ",
  379. intval($contact['id']),
  380. dbesc(datetime_convert()),
  381. dbesc(datetime_convert()),
  382. dbesc($slappy)
  383. );
  384. }
  385. }
  386. }
  387. }
  388. }
  389. break;
  390. case NETWORK_MAIL:
  391. if(get_config('system','dfrn_only'))
  392. break;
  393. // WARNING: does not currently convert to RFC2047 header encodings, etc.
  394. $addr = $contact['addr'];
  395. if(! strlen($addr))
  396. break;
  397. if($cmd === 'wall-new' || $cmd === 'comment-new') {
  398. $it = null;
  399. if($cmd === 'wall-new')
  400. $it = $items[0];
  401. else {
  402. $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
  403. intval($argv[2]),
  404. intval($uid)
  405. );
  406. if(count($r))
  407. $it = $r[0];
  408. }
  409. if(! $it)
  410. break;
  411. $local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
  412. intval($uid)
  413. );
  414. if(! count($local_user))
  415. break;
  416. $reply_to = '';
  417. $r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
  418. intval($uid)
  419. );
  420. if($r1 && $r1[0]['reply_to'])
  421. $reply_to = $r1[0]['reply_to'];
  422. $subject = (($it['title']) ? $it['title'] : t("\x28no subject\x29")) ;
  423. $headers = 'From: ' . $local_user[0]['username'] . ' <' . $local_user[0]['email'] . '>' . "\n";
  424. if($reply_to)
  425. $headers .= 'Reply-to: ' . $reply_to . "\n";
  426. $headers .= 'Message-id: <' . $it['uri'] . '>' . "\n";
  427. if($it['uri'] !== $it['parent-uri']) {
  428. $header .= 'References: <' . $it['parent-uri'] . '>' . "\n";
  429. if(! strlen($it['title'])) {
  430. $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' LIMIT 1",
  431. dbesc($it['parent-uri'])
  432. );
  433. if(count($r)) {
  434. $subtitle = $r[0]['title'];
  435. if($subtitle) {
  436. if(strncasecmp($subtitle,'RE:',3))
  437. $subject = $subtitle;
  438. else
  439. $subject = 'Re: ' . $subtitle;
  440. }
  441. }
  442. }
  443. }
  444. $headers .= 'MIME-Version: 1.0' . "\n";
  445. $headers .= 'Content-Type: text/html; charset=UTF-8' . "\n";
  446. $headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n";
  447. $html = prepare_body($it);
  448. $message = '<html><body>' . $html . '</body></html>';
  449. logger('notifier: email delivery to ' . $addr);
  450. mail($addr, $subject, $message, $headers);
  451. }
  452. break;
  453. case NETWORK_DIASPORA:
  454. require_once('include/diaspora.php');
  455. if(get_config('system','dfrn_only') || (! get_config('system','diaspora_enabled')) || (! $normal_mode))
  456. break;
  457. if(! $contact['pubkey'])
  458. break;
  459. if($target_item['verb'] === ACTIVITY_DISLIKE) {
  460. // unsupported
  461. break;
  462. }
  463. elseif(($target_item['deleted']) && ($target_item['verb'] !== ACTIVITY_LIKE)) {
  464. // diaspora delete,
  465. diaspora_send_retraction($target_item,$owner,$contact);
  466. break;
  467. }
  468. elseif($followup) {
  469. // send comments, likes and retractions of likes to owner to relay
  470. diaspora_send_followup($target_item,$owner,$contact);
  471. break;
  472. }
  473. elseif($target_item['parent'] != $target_item['id']) {
  474. // we are the relay - send comments, likes and unlikes to our conversants
  475. diaspora_send_relay($target_item,$owner,$contact);
  476. break;
  477. }
  478. elseif($top_level) {
  479. diaspora_send_status($target_item,$owner,$contact);
  480. break;
  481. }
  482. break;
  483. case NETWORK_FEED:
  484. case NETWORK_FACEBOOK:
  485. if(get_config('system','dfrn_only'))
  486. break;
  487. default:
  488. break;
  489. }
  490. }
  491. }
  492. // send additional slaps to mentioned remote tags (@foo@example.com)
  493. if($slap && count($url_recipients) && ($followup || $top_level) && $public_message && (! $expire)) {
  494. if(! get_config('system','dfrn_only')) {
  495. foreach($url_recipients as $url) {
  496. if($url) {
  497. logger('notifier: urldelivery: ' . $url);
  498. $deliver_status = slapper($owner,$url,$slap);
  499. // TODO: redeliver/queue these items on failure, though there is no contact record
  500. }
  501. }
  502. }
  503. }
  504. if($public_message) {
  505. $r = q("SELECT `id`, `name` FROM `contact`
  506. WHERE `network` in ('%s','%s') AND `uid` = %d AND `blocked` = 0 AND `pending` = 0
  507. AND `rel` != %d order by rand() ",
  508. dbesc(NETWORK_DFRN),
  509. dbesc(NETWORK_DIASPORA),
  510. intval($owner['uid']),
  511. intval(CONTACT_IS_SHARING)
  512. );
  513. if(count($r)) {
  514. logger('pubdeliver: ' . print_r($r,true));
  515. // throw everything into the queue in case we get killed
  516. foreach($r as $rr) {
  517. if((! $mail) && (! $fsuggest) && (! $followup)) {
  518. q("insert into deliverq ( `cmd`,`item`,`contact` ) values ('%s', %d, %d )",
  519. dbesc($cmd),
  520. intval($item_id),
  521. intval($rr['id'])
  522. );
  523. }
  524. }
  525. foreach($r as $rr) {
  526. /* Don't deliver to folks who have already been delivered to */
  527. if(in_array($rr['id'],$conversants)) {
  528. logger('notifier: already delivered id=' . $rr['id']);
  529. continue;
  530. }
  531. if((! $mail) && (! $fsuggest) && (! $followup)) {
  532. logger('notifier: delivery agent: ' . $rr['name'] . ' ' . $rr['id']);
  533. proc_run('php','include/delivery.php',$cmd,$item_id,$rr['id']);
  534. if($interval)
  535. @time_sleep_until(microtime(true) + (float) $interval);
  536. }
  537. }
  538. }
  539. if(strlen($hub)) {
  540. $hubs = explode(',', $hub);
  541. if(count($hubs)) {
  542. foreach($hubs as $h) {
  543. $h = trim($h);
  544. if(! strlen($h))
  545. continue;
  546. $params = 'hub.mode=publish&hub.url=' . urlencode($a->get_baseurl() . '/dfrn_poll/' . $owner['nickname'] );
  547. post_url($h,$params);
  548. logger('pubsub: publish: ' . $h . ' ' . $params . ' returned ' . $a->get_curl_code());
  549. if(count($hubs) > 1)
  550. sleep(7); // try and avoid multiple hubs responding at precisely the same time
  551. }
  552. }
  553. }
  554. }
  555. return;
  556. }
  557. if (array_search(__file__,get_included_files())===0){
  558. notifier_run($argv,$argc);
  559. killme();
  560. }