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.

657 lines
20 KiB

11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 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
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
  1. <?php
  2. require_once("boot.php");
  3. function poller_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('include/session.php');
  15. require_once('include/datetime.php');
  16. require_once('library/simplepie/simplepie.inc');
  17. require_once('include/items.php');
  18. require_once('include/Contact.php');
  19. require_once('include/email.php');
  20. require_once('include/socgraph.php');
  21. load_config('config');
  22. load_config('system');
  23. $a->set_baseurl(get_config('system','url'));
  24. load_hooks();
  25. logger('poller: start');
  26. // run queue delivery process in the background
  27. proc_run('php',"include/queue.php");
  28. // expire any expired accounts
  29. q("UPDATE user SET `account_expired` = 1 where `account_expired` = 0
  30. AND `account_expires_on` != '0000-00-00 00:00:00'
  31. AND `account_expires_on` < UTC_TIMESTAMP() ");
  32. $abandon_days = intval(get_config('system','account_abandon_days'));
  33. if($abandon_days < 1)
  34. $abandon_days = 0;
  35. // once daily run birthday_updates and then expire in background
  36. $d1 = get_config('system','last_expire_day');
  37. $d2 = intval(datetime_convert('UTC','UTC','now','d'));
  38. if($d2 != intval($d1)) {
  39. update_contact_birthdays();
  40. update_suggestions();
  41. set_config('system','last_expire_day',$d2);
  42. proc_run('php','include/expire.php');
  43. }
  44. // clear old cache
  45. Cache::clear();
  46. // clear item cache files if they are older than one day
  47. $cache = get_config('system','itemcache');
  48. if (($cache != '') and is_dir($cache)) {
  49. if ($dh = opendir($cache)) {
  50. while (($file = readdir($dh)) !== false) {
  51. $fullpath = $cache."/".$file;
  52. if ((filetype($fullpath) == "file") and filectime($fullpath) < (time() - 86400))
  53. unlink($fullpath);
  54. }
  55. closedir($dh);
  56. }
  57. }
  58. $manual_id = 0;
  59. $generation = 0;
  60. $hub_update = false;
  61. $force = false;
  62. $restart = false;
  63. if(($argc > 1) && ($argv[1] == 'force'))
  64. $force = true;
  65. if(($argc > 1) && ($argv[1] == 'restart')) {
  66. $restart = true;
  67. $generation = intval($argv[2]);
  68. if(! $generation)
  69. killme();
  70. }
  71. if(($argc > 1) && intval($argv[1])) {
  72. $manual_id = intval($argv[1]);
  73. $force = true;
  74. }
  75. $sql_extra = (($manual_id) ? " AND `id` = $manual_id " : "");
  76. reload_plugins();
  77. $d = datetime_convert();
  78. if(! $restart)
  79. proc_run('php','include/cronhooks.php');
  80. // Only poll from those with suitable relationships,
  81. // and which have a polling address and ignore Diaspora since
  82. // we are unable to match those posts with a Diaspora GUID and prevent duplicates.
  83. $abandon_sql = (($abandon_days)
  84. ? sprintf(" AND `user`.`login_date` > UTC_TIMESTAMP() - INTERVAL %d DAY ", intval($abandon_days))
  85. : ''
  86. );
  87. $contacts = q("SELECT `contact`.`id` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
  88. WHERE ( `rel` = %d OR `rel` = %d ) AND `poll` != ''
  89. AND NOT `network` IN ( '%s', '%s' )
  90. $sql_extra
  91. AND `self` = 0 AND `contact`.`blocked` = 0 AND `contact`.`readonly` = 0
  92. AND `user`.`account_expired` = 0 $abandon_sql ORDER BY RAND()",
  93. intval(CONTACT_IS_SHARING),
  94. intval(CONTACT_IS_FRIEND),
  95. dbesc(NETWORK_DIASPORA),
  96. dbesc(NETWORK_FACEBOOK)
  97. );
  98. if(! count($contacts)) {
  99. return;
  100. }
  101. foreach($contacts as $c) {
  102. $res = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
  103. intval($c['id'])
  104. );
  105. if((! $res) || (! count($res)))
  106. continue;
  107. foreach($res as $contact) {
  108. $xml = false;
  109. if($manual_id)
  110. $contact['last-update'] = '0000-00-00 00:00:00';
  111. if($contact['network'] === NETWORK_DFRN)
  112. $contact['priority'] = 2;
  113. if(!get_config('system','ostatus_use_priority') and ($contact['network'] === NETWORK_OSTATUS))
  114. $contact['priority'] = 2;
  115. if($contact['priority'] || $contact['subhub']) {
  116. $hub_update = true;
  117. $update = false;
  118. $t = $contact['last-update'];
  119. // We should be getting everything via a hub. But just to be sure, let's check once a day.
  120. // (You can make this more or less frequent if desired by setting 'pushpoll_frequency' appropriately)
  121. // This also lets us update our subscription to the hub, and add or replace hubs in case it
  122. // changed. We will only update hubs once a day, regardless of 'pushpoll_frequency'.
  123. if($contact['subhub']) {
  124. $interval = get_config('system','pushpoll_frequency');
  125. $contact['priority'] = (($interval !== false) ? intval($interval) : 3);
  126. $hub_update = false;
  127. if((datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day")) || $force)
  128. $hub_update = true;
  129. }
  130. else
  131. $hub_update = false;
  132. /**
  133. * Based on $contact['priority'], should we poll this site now? Or later?
  134. */
  135. switch ($contact['priority']) {
  136. case 5:
  137. if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 month"))
  138. $update = true;
  139. break;
  140. case 4:
  141. if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 week"))
  142. $update = true;
  143. break;
  144. case 3:
  145. if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day"))
  146. $update = true;
  147. break;
  148. case 2:
  149. if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 12 hour"))
  150. $update = true;
  151. break;
  152. case 1:
  153. default:
  154. if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 hour"))
  155. $update = true;
  156. break;
  157. }
  158. if((! $update) && (! $force))
  159. continue;
  160. }
  161. // Check to see if we are running out of memory - if so spawn a new process and kill this one
  162. $avail_memory = return_bytes(ini_get('memory_limit'));
  163. $memused = memory_get_peak_usage(true);
  164. if(intval($avail_memory)) {
  165. if(($memused / $avail_memory) > 0.95) {
  166. if($generation + 1 > 10) {
  167. logger('poller: maximum number of spawns exceeded. Terminating.');
  168. killme();
  169. }
  170. logger('poller: memory exceeded. ' . $memused . ' bytes used. Spawning new poll.');
  171. proc_run('php', 'include/poller.php', 'restart', (string) $generation + 1);
  172. killme();
  173. }
  174. }
  175. $importer_uid = $contact['uid'];
  176. $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
  177. intval($importer_uid)
  178. );
  179. if(! count($r))
  180. continue;
  181. $importer = $r[0];
  182. logger("poller: poll: ({$contact['id']}) IMPORTER: {$importer['name']}, CONTACT: {$contact['name']}");
  183. $last_update = (($contact['last-update'] === '0000-00-00 00:00:00')
  184. ? datetime_convert('UTC','UTC','now - 30 days', ATOM_TIME)
  185. : datetime_convert('UTC','UTC',$contact['last-update'], ATOM_TIME)
  186. );
  187. if($contact['network'] === NETWORK_DFRN) {
  188. $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
  189. if(intval($contact['duplex']) && $contact['dfrn-id'])
  190. $idtosend = '0:' . $orig_id;
  191. if(intval($contact['duplex']) && $contact['issued-id'])
  192. $idtosend = '1:' . $orig_id;
  193. // they have permission to write to us. We already filtered this in the contact query.
  194. $perm = 'rw';
  195. $url = $contact['poll'] . '?dfrn_id=' . $idtosend
  196. . '&dfrn_version=' . DFRN_PROTOCOL_VERSION
  197. . '&type=data&last_update=' . $last_update
  198. . '&perm=' . $perm ;
  199. $handshake_xml = fetch_url($url);
  200. logger('poller: handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA);
  201. if(! $handshake_xml) {
  202. logger("poller: $url appears to be dead - marking for death ");
  203. // dead connection - might be a transient event, or this might
  204. // mean the software was uninstalled or the domain expired.
  205. // Will keep trying for one month.
  206. mark_for_death($contact);
  207. // set the last-update so we don't keep polling
  208. $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1",
  209. dbesc(datetime_convert()),
  210. intval($contact['id'])
  211. );
  212. continue;
  213. }
  214. if(! strstr($handshake_xml,'<?xml')) {
  215. logger('poller: response from ' . $url . ' did not contain XML.');
  216. $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1",
  217. dbesc(datetime_convert()),
  218. intval($contact['id'])
  219. );
  220. continue;
  221. }
  222. $res = parse_xml_string($handshake_xml);
  223. if(intval($res->status) == 1) {
  224. logger("poller: $url replied status 1 - marking for death ");
  225. // we may not be friends anymore. Will keep trying for one month.
  226. // set the last-update so we don't keep polling
  227. $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1",
  228. dbesc(datetime_convert()),
  229. intval($contact['id'])
  230. );
  231. mark_for_death($contact);
  232. }
  233. else {
  234. if($contact['term-date'] != '0000-00-00 00:00:00') {
  235. logger("poller: $url back from the dead - removing mark for death");
  236. unmark_for_death($contact);
  237. }
  238. }
  239. if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id)))
  240. continue;
  241. if(((float) $res->dfrn_version > 2.21) && ($contact['poco'] == '')) {
  242. q("update contact set poco = '%s' where id = %d limit 1",
  243. dbesc(str_replace('/profile/','/poco/', $contact['url'])),
  244. intval($contact['id'])
  245. );
  246. }
  247. $postvars = array();
  248. $sent_dfrn_id = hex2bin((string) $res->dfrn_id);
  249. $challenge = hex2bin((string) $res->challenge);
  250. $final_dfrn_id = '';
  251. if(($contact['duplex']) && strlen($contact['prvkey'])) {
  252. openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']);
  253. openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']);
  254. }
  255. else {
  256. openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']);
  257. openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']);
  258. }
  259. $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
  260. if(strpos($final_dfrn_id,':') == 1)
  261. $final_dfrn_id = substr($final_dfrn_id,2);
  262. if($final_dfrn_id != $orig_id) {
  263. logger('poller: ID did not decode: ' . $contact['id'] . ' orig: ' . $orig_id . ' final: ' . $final_dfrn_id);
  264. // did not decode properly - cannot trust this site
  265. continue;
  266. }
  267. $postvars['dfrn_id'] = $idtosend;
  268. $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION;
  269. $postvars['perm'] = 'rw';
  270. $xml = post_url($contact['poll'],$postvars);
  271. }
  272. elseif(($contact['network'] === NETWORK_OSTATUS)
  273. || ($contact['network'] === NETWORK_DIASPORA)
  274. || ($contact['network'] === NETWORK_FEED) ) {
  275. // Upgrading DB fields from an older Friendica version
  276. // Will only do this once per notify-enabled OStatus contact
  277. // or if relationship changes
  278. $stat_writeable = ((($contact['notify']) && ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['rel'] == CONTACT_IS_FRIEND)) ? 1 : 0);
  279. if($stat_writeable != $contact['writable']) {
  280. q("UPDATE `contact` SET `writable` = %d WHERE `id` = %d LIMIT 1",
  281. intval($stat_writeable),
  282. intval($contact['id'])
  283. );
  284. }
  285. // Are we allowed to import from this person?
  286. if($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['blocked'] || $contact['readonly'])
  287. continue;
  288. $xml = fetch_url($contact['poll']);
  289. }
  290. elseif($contact['network'] === NETWORK_MAIL || $contact['network'] === NETWORK_MAIL2) {
  291. logger("Mail: Fetching");
  292. $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
  293. if($mail_disabled)
  294. continue;
  295. logger("Mail: Enabled");
  296. $mbox = null;
  297. $x = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1",
  298. intval($importer_uid)
  299. );
  300. $mailconf = q("SELECT * FROM `mailacct` WHERE `server` != '' AND `uid` = %d LIMIT 1",
  301. intval($importer_uid)
  302. );
  303. if(count($x) && count($mailconf)) {
  304. $mailbox = construct_mailbox_name($mailconf[0]);
  305. $password = '';
  306. openssl_private_decrypt(hex2bin($mailconf[0]['pass']),$password,$x[0]['prvkey']);
  307. $mbox = email_connect($mailbox,$mailconf[0]['user'],$password);
  308. unset($password);
  309. logger("Mail: Connect");
  310. if($mbox) {
  311. q("UPDATE `mailacct` SET `last_check` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
  312. dbesc(datetime_convert()),
  313. intval($mailconf[0]['id']),
  314. intval($importer_uid)
  315. );
  316. }
  317. }
  318. if($mbox) {
  319. logger("Mail: mbox");
  320. $msgs = email_poll($mbox,$contact['addr']);
  321. if(count($msgs)) {
  322. logger("Mail: Parsing ".count($msgs)." mails.");
  323. foreach($msgs as $msg_uid) {
  324. logger("Mail: Parsing mail ".$msg_uid);
  325. $datarray = array();
  326. $meta = email_msg_meta($mbox,$msg_uid);
  327. $headers = email_msg_headers($mbox,$msg_uid);
  328. // look for a 'references' header and try and match with a parent item we have locally.
  329. $raw_refs = ((x($headers,'references')) ? str_replace("\t",'',$headers['references']) : '');
  330. $datarray['uri'] = msgid2iri(trim($meta->message_id,'<>'));
  331. if($raw_refs) {
  332. $refs_arr = explode(' ', $raw_refs);
  333. if(count($refs_arr)) {
  334. for($x = 0; $x < count($refs_arr); $x ++)
  335. $refs_arr[$x] = "'" . msgid2iri(str_replace(array('<','>',' '),array('','',''),dbesc($refs_arr[$x]))) . "'";
  336. }
  337. $qstr = implode(',',$refs_arr);
  338. $r = q("SELECT `uri` , `parent-uri` FROM `item` WHERE `uri` IN ( $qstr ) AND `uid` = %d LIMIT 1",
  339. intval($importer_uid)
  340. );
  341. if(count($r))
  342. $datarray['parent-uri'] = $r[0]['uri'];
  343. }
  344. if(! x($datarray,'parent-uri'))
  345. $datarray['parent-uri'] = $datarray['uri'];
  346. // Have we seen it before?
  347. $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `uri` = '%s' LIMIT 1",
  348. intval($importer_uid),
  349. dbesc($datarray['uri'])
  350. );
  351. if(count($r)) {
  352. logger("Mail: Seen before ".$msg_uid);
  353. if($meta->deleted && ! $r[0]['deleted']) {
  354. q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d LIMIT 1",
  355. dbesc(datetime_convert()),
  356. intval($r[0]['id'])
  357. );
  358. }
  359. switch ($mailconf[0]['action']) {
  360. case 0:
  361. break;
  362. case 1:
  363. logger("Mail: Deleting ".$msg_uid);
  364. imap_delete($mbox, $msg_uid, FT_UID);
  365. break;
  366. case 2:
  367. logger("Mail: Mark as seen ".$msg_uid);
  368. imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID);
  369. break;
  370. case 3:
  371. logger("Mail: Moving ".$msg_uid." to ".$mailconf[0]['movetofolder']);
  372. imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID);
  373. if ($mailconf[0]['movetofolder'] != "")
  374. imap_mail_move($mbox, $msg_uid, $mailconf[0]['movetofolder'], FT_UID);
  375. break;
  376. }
  377. continue;
  378. }
  379. // Decoding the header
  380. $subject = imap_mime_header_decode($meta->subject);
  381. $datarray['title'] = "";
  382. foreach($subject as $subpart)
  383. if ($subpart->charset != "default")
  384. $datarray['title'] .= iconv($subpart->charset, 'UTF-8//IGNORE', $subpart->text);
  385. else
  386. $datarray['title'] .= $subpart->text;
  387. $datarray['title'] = notags(trim($datarray['title']));
  388. //$datarray['title'] = notags(trim($meta->subject));
  389. $datarray['created'] = datetime_convert('UTC','UTC',$meta->date);
  390. // Is it reply?
  391. $reply = ((substr(strtolower($datarray['title']), 0, 3) == "re:") or
  392. (substr(strtolower($datarray['title']), 0, 3) == "re-") or
  393. (raw_refs != ""));
  394. $r = email_get_msg($mbox,$msg_uid, $reply);
  395. if(! $r) {
  396. logger("Mail: can't fetch msg ".$msg_uid);
  397. continue;
  398. }
  399. $datarray['body'] = escape_tags($r['body']);
  400. logger("Mail: Importing ".$msg_uid);
  401. // some mailing lists have the original author as 'from' - add this sender info to msg body.
  402. // todo: adding a gravatar for the original author would be cool
  403. if(! stristr($meta->from,$contact['addr'])) {
  404. $from = imap_mime_header_decode($meta->from);
  405. $fromdecoded = "";
  406. foreach($from as $frompart)
  407. if ($frompart->charset != "default")
  408. $fromdecoded .= iconv($frompart->charset, 'UTF-8//IGNORE', $frompart->text);
  409. else
  410. $fromdecoded .= $frompart->text;
  411. $datarray['body'] = "[b]".t('From: ') . escape_tags($fromdecoded) . "[/b]\n\n" . $datarray['body'];
  412. }
  413. $datarray['uid'] = $importer_uid;
  414. $datarray['contact-id'] = $contact['id'];
  415. if($datarray['parent-uri'] === $datarray['uri'])
  416. $datarray['private'] = 1;
  417. if(($contact['network'] === NETWORK_MAIL) && (! get_pconfig($importer_uid,'system','allow_public_email_replies'))) {
  418. $datarray['private'] = 1;
  419. $datarray['allow_cid'] = '<' . $contact['id'] . '>';
  420. }
  421. $datarray['author-name'] = $contact['name'];
  422. $datarray['author-link'] = 'mailbox';
  423. $datarray['author-avatar'] = $contact['photo'];
  424. $stored_item = item_store($datarray);
  425. q("UPDATE `item` SET `last-child` = 0 WHERE `parent-uri` = '%s' AND `uid` = %d",
  426. dbesc($datarray['parent-uri']),
  427. intval($importer_uid)
  428. );
  429. q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d LIMIT 1",
  430. intval($stored_item)
  431. );
  432. switch ($mailconf[0]['action']) {
  433. case 0:
  434. break;
  435. case 1:
  436. logger("Mail: Deleting ".$msg_uid);
  437. imap_delete($mbox, $msg_uid, FT_UID);
  438. break;
  439. case 2:
  440. logger("Mail: Mark as seen ".$msg_uid);
  441. imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID);
  442. break;
  443. case 3:
  444. logger("Mail: Moving ".$msg_uid." to ".$mailconf[0]['movetofolder']);
  445. imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID);
  446. if ($mailconf[0]['movetofolder'] != "")
  447. imap_mail_move($mbox, $msg_uid, $mailconf[0]['movetofolder'], FT_UID);
  448. break;
  449. }
  450. }
  451. }
  452. imap_close($mbox);
  453. }
  454. }
  455. elseif($contact['network'] === NETWORK_FACEBOOK) {
  456. // This is picked up by the Facebook plugin on a cron hook.
  457. // Ignored here.
  458. }
  459. if($xml) {
  460. logger('poller: received xml : ' . $xml, LOGGER_DATA);
  461. if(! strstr($xml,'<?xml')) {
  462. logger('poller: post_handshake: response from ' . $url . ' did not contain XML.');
  463. $r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d LIMIT 1",
  464. dbesc(datetime_convert()),
  465. intval($contact['id'])
  466. );
  467. continue;
  468. }
  469. consume_feed($xml,$importer,$contact,$hub,1,1);
  470. // do it twice. Ensures that children of parents which may be later in the stream aren't tossed
  471. consume_feed($xml,$importer,$contact,$hub,1,2);
  472. $hubmode = 'subscribe';
  473. if($contact['network'] === NETWORK_DFRN || $contact['blocked'] || $contact['readonly'])
  474. $hubmode = 'unsubscribe';
  475. if((strlen($hub)) && ($hub_update) && ($contact['rel'] != CONTACT_IS_FOLLOWER)) {
  476. logger('poller: hub ' . $hubmode . ' : ' . $hub . ' contact name : ' . $contact['name'] . ' local user : ' . $importer['name']);
  477. $hubs = explode(',', $hub);
  478. if(count($hubs)) {
  479. foreach($hubs as $h) {
  480. $h = trim($h);
  481. if(! strlen($h))
  482. continue;
  483. subscribe_to_hub($h,$importer,$contact,$hubmode);
  484. }
  485. }
  486. }
  487. }
  488. $updated = datetime_convert();
  489. $r = q("UPDATE `contact` SET `last-update` = '%s', `success_update` = '%s' WHERE `id` = %d LIMIT 1",
  490. dbesc($updated),
  491. dbesc($updated),
  492. intval($contact['id'])
  493. );
  494. // load current friends if possible.
  495. if($contact['poco']) {
  496. $r = q("SELECT count(*) as total from glink
  497. where `cid` = %d and updated > UTC_TIMESTAMP() - INTERVAL 1 DAY",
  498. intval($contact['id'])
  499. );
  500. }
  501. if(count($r)) {
  502. if(! $r[0]['total']) {
  503. poco_load($contact['id'],$importer_uid,$contact['poco']);
  504. }
  505. }
  506. // loop - next contact
  507. }
  508. }
  509. return;
  510. }
  511. if (array_search(__file__,get_included_files())===0){
  512. poller_run($argv,$argc);
  513. killme();
  514. }