3 require_once('bbcode.php');
5 function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update, $direction = 0) {
8 // default permissions - anonymous user
17 if(strlen($owner_id) && ! intval($owner_id)) {
18 $r = q("SELECT `uid`, `nickname` FROM `user` WHERE `nickname` = '%s' LIMIT 1",
22 $owner_id = $r[0]['uid'];
23 $owner_nick = $r[0]['nickname'];
27 $r = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
35 if($dfrn_id && $dfrn_id != '*') {
40 $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($dfrn_id));
44 $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
45 $my_id = '1:' . $dfrn_id;
48 $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
49 $my_id = '0:' . $dfrn_id;
56 $r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `contact`.`uid` = %d $sql_extra LIMIT 1",
64 $groups = init_groups_visitor($contact['id']);
67 for($x = 0; $x < count($groups); $x ++)
68 $groups[$x] = '<' . intval($groups[$x]) . '>' ;
69 $gs = implode('|', $groups);
72 $gs = '<<>>' ; // Impossible to match
74 $sql_extra = sprintf("
75 AND ( `allow_cid` = '' OR `allow_cid` REGEXP '<%d>' )
76 AND ( `deny_cid` = '' OR NOT `deny_cid` REGEXP '<%d>' )
77 AND ( `allow_gid` = '' OR `allow_gid` REGEXP '%s' )
78 AND ( `deny_gid` = '' OR NOT `deny_gid` REGEXP '%s')
80 intval($contact['id']),
81 intval($contact['id']),
87 if($dfrn_id === '' || $dfrn_id === '*')
92 if(! strlen($last_update))
93 $last_update = 'now - 30 days';
95 $check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s');
97 $r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
98 `contact`.`name`, `contact`.`photo`, `contact`.`url`,
99 `contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`,
100 `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
101 `contact`.`id` AS `contact-id`, `contact`.`uid` AS `contact-uid`
102 FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
103 WHERE `item`.`uid` = %d AND `item`.`visible` = 1
104 AND `item`.`wall` = 1 AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
105 AND ( `item`.`edited` > '%s' OR `item`.`changed` > '%s' )
107 ORDER BY `parent` %s, `created` ASC LIMIT 0, 300",
114 // Will check further below if this actually returned results.
115 // We will provide an empty feed in any case.
119 $feed_template = load_view_file('view/atom_feed.tpl');
120 $tomb_template = load_view_file('view/atom_tomb.tpl');
121 $item_template = load_view_file('view/atom_item.tpl');
122 $cmnt_template = load_view_file('view/atom_cmnt.tpl');
126 $hub = get_config('system','huburl');
128 $hubxml = ((strlen($hub)) ? '<link rel="hub" href="' . xmlify($hub) . '" />' . "\n" : '');
130 $salmon = '<link rel="salmon" href="' . xmlify($a->get_baseurl() . '/salmon/' . $owner_nick) . '" />' . "\n" ;
131 $salmon = ''; // remove this line when salmon handler is finished
133 $atom .= replace_macros($feed_template, array(
134 '$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner_nick),
135 '$feed_title' => xmlify($owner['name']),
136 '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', $updated . '+00:00' , ATOM_TIME)) ,
138 '$salmon' => $salmon,
139 '$name' => xmlify($owner['name']),
140 '$profile_page' => xmlify($owner['url']),
141 '$photo' => xmlify($owner['photo']),
142 '$thumb' => xmlify($owner['thumb']),
143 '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) ,
144 '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , ATOM_TIME)) ,
145 '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME))
149 if(! count($items)) {
150 $atom .= '</feed>' . "\r\n";
154 foreach($items as $item) {
156 // public feeds get html, our own nodes use bbcode
158 if($dfrn_id === '*') {
159 $allow = (($item['last-child']) ? 1 : 0);
160 $item['body'] = bbcode($item['body']);
164 $allow = ((($item['last-child']) && ($contact['rel']) && ($contact['rel'] != REL_FAN)) ? 1 : 0);
168 if($item['deleted']) {
169 $atom .= replace_macros($tomb_template, array(
170 '$id' => xmlify($item['uri']),
171 '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME))
175 $verb = construct_verb($item);
176 $actobj = construct_activity($item);
178 if($item['parent'] == $item['id']) {
179 $atom .= replace_macros($item_template, array(
180 '$name' => xmlify($item['name']),
181 '$profile_page' => xmlify($item['url']),
182 '$thumb' => xmlify($item['thumb']),
183 '$owner_name' => xmlify($item['owner-name']),
184 '$owner_profile_page' => xmlify($item['owner-link']),
185 '$owner_thumb' => xmlify($item['owner-avatar']),
186 '$item_id' => xmlify($item['uri']),
187 '$title' => xmlify($item['title']),
188 '$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
189 '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME)),
190 '$location' => xmlify($item['location']),
192 '$alt' => xmlify($a->get_baseurl() . '/display/' . $owner_nick . '/' . $item['id']),
193 '$content' => xmlify($item['body']),
194 '$verb' => xmlify($verb),
195 '$actobj' => $actobj, // do not xmlify
196 '$comment_allow' => $allow
200 $atom .= replace_macros($cmnt_template, array(
201 '$name' => xmlify($item['name']),
202 '$profile_page' => xmlify($item['url']),
203 '$thumb' => xmlify($item['thumb']),
204 '$item_id' => xmlify($item['uri']),
205 '$title' => xmlify($item['title']),
206 '$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)),
207 '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00' , ATOM_TIME)),
209 '$content' => xmlify($item['body']),
210 '$alt' => xmlify($a->get_baseurl() . '/display/' . $owner_nick . '/' . $item['id']),
211 '$verb' => xmlify($verb),
212 '$actobj' => $actobj, // do not xmlify
213 '$parent_id' => xmlify($item['parent-uri']),
214 '$comment_allow' => $allow
220 $atom .= '</feed>' . "\r\n";
225 function construct_verb($item) {
227 return $item['verb'];
228 return ACTIVITY_POST;
231 function construct_activity($item) {
233 if($item['object']) {
234 $o = '<as:object>' . "\r\n";
235 $r = @simplexml_load_string($item['object']);
237 $o .= '<as:object-type>' . xmlify($r->type) . '</as:object-type>' . "\r\n";
239 $o .= '<id>' . xmlify($r->id) . '</id>' . "\r\n";
241 $o .= '<link rel="alternate" type="text/html" href="' . xmlify($r->link) . '" />' . "\r\n";
243 $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n";
245 $o .= '<content type="html" >' . xmlify(bbcode($r->content)) . '</content>' . "\r\n";
246 $o .= '</as:object>' . "\r\n";
256 function get_atom_elements($item) {
258 require_once('library/HTMLPurifier.auto.php');
259 require_once('include/html2bbcode.php');
263 $raw_author = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
265 if($raw_author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] === 'photo')
266 $res['author-avatar'] = unxmlify($raw_author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href']);
269 $author = $item->get_author();
270 $res['author-name'] = unxmlify($author->get_name());
271 $res['author-link'] = unxmlify($author->get_link());
272 if(! $res['author-avatar'])
273 $res['author-avatar'] = unxmlify($author->get_avatar());
274 $res['uri'] = unxmlify($item->get_id());
275 $res['title'] = unxmlify($item->get_title());
276 $res['body'] = unxmlify($item->get_content());
278 $maxlen = get_max_import_size();
279 if($maxlen && (strlen($res['body']) > $maxlen))
280 $res['body'] = substr($res['body'],0, $maxlen);
282 // It isn't certain at this point whether our content is plaintext or html and we'd be foolish to trust
283 // the content type. Our own network only emits text normally, though it might have been converted to
284 // html if we used a pubsubhubbub transport. But if we see even one html open tag in our text, we will
285 // have to assume it is all html and needs to be purified.
287 // It doesn't matter all that much security wise - because before this content is used anywhere, we are
288 // going to escape any tags we find regardless, but this lets us import a limited subset of html from
289 // the wild, by sanitising it and converting supported tags to bbcode before we rip out any remaining
293 if(strpos($res['body'],'<')) {
295 $res['body'] = preg_replace('#<object[^>]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s',
296 '[youtube]$1[/youtube]', $res['body']);
298 $config = HTMLPurifier_Config::createDefault();
299 $config->set('Core.DefinitionCache', null);
301 // we shouldn't need a whitelist, because the bbcode converter
302 // will strip out any unsupported tags.
303 // $config->set('HTML.Allowed', 'p,b,a[href],i');
305 $purifier = new HTMLPurifier($config);
306 $res['body'] = $purifier->purify($res['body']);
310 $res['body'] = html2bbcode($res['body']);
313 $allow = $item->get_item_tags(NAMESPACE_DFRN,'comment-allow');
314 if($allow && $allow[0]['data'] == 1)
315 $res['last-child'] = 1;
317 $res['last-child'] = 0;
319 $rawcreated = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'published');
321 $res['created'] = unxmlify($rawcreated[0]['data']);
323 $rawlocation = $item->get_item_tags(NAMESPACE_DFRN, 'location');
325 $res['location'] = unxmlify($rawlocation[0]['data']);
328 $rawedited = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'updated');
330 $res['edited'] = unxmlify($rawcreated[0]['data']);
332 $rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner');
333 if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])
334 $res['owner-name'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']);
335 elseif($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data'])
336 $res['owner-name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']);
337 if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])
338 $res['owner-link'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']);
339 elseif($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])
340 $res['owner-link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
342 if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] === 'photo')
343 $res['owner-avatar'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href']);
344 elseif($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data'])
345 $res['owner-avatar'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['avatar'][0]['data']);
347 $rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
348 // select between supported verbs
350 $res['verb'] = unxmlify($rawverb[0]['data']);
352 $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
356 $res['object'] = '<object>' . "\n";
357 if($rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
358 $res['object-type'] = $rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'];
359 $res['object'] .= '<type>' . $rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '</type>' . "\n";
361 if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
362 $res['object'] .= '<id>' . $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '</id>' . "\n";
364 if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['rel'] === 'alternate')
365 $res['object'] .= '<link>' . $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'][0]['attribs']['']['href'] . '</link>' . "\n";
366 if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'])
367 $res['object'] .= '<title>' . $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '</title>' . "\n";
368 if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) {
369 $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data'];
371 $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
372 if(strpos($body,'<')) {
374 $body = preg_replace('#<object[^>]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s',
375 '[youtube]$1[/youtube]', $body);
377 $config = HTMLPurifier_Config::createDefault();
378 $config->set('Core.DefinitionCache', null);
380 $purifier = new HTMLPurifier($config);
381 $body = $purifier->purify($body);
384 $body = html2bbcode($body);
385 $res['object'] .= '<content>' . $body . '</content>' . "\n";
388 $res['object'] .= '</object>' . "\n";
394 function item_store($arr) {
400 $arr['gravity'] = intval($arr['gravity']);
401 elseif($arr['parent-uri'] == $arr['uri'])
403 elseif($arr['verb'] == ACTIVITY_POST)
407 $arr['type'] = 'remote';
408 $arr['wall'] = ((intval($arr['wall'])) ? 1 : 0);
409 $arr['uri'] = notags(trim($arr['uri']));
410 $arr['author-name'] = notags(trim($arr['author-name']));
411 $arr['author-link'] = notags(trim($arr['author-link']));
412 $arr['author-avatar'] = notags(trim($arr['author-avatar']));
413 $arr['owner-name'] = notags(trim($arr['owner-name']));
414 $arr['owner-link'] = notags(trim($arr['owner-link']));
415 $arr['owner-avatar'] = notags(trim($arr['owner-avatar']));
416 $arr['created'] = ((x($arr,'created') !== false) ? datetime_convert('UTC','UTC',$arr['created']) : datetime_convert());
417 $arr['edited'] = ((x($arr,'edited') !== false) ? datetime_convert('UTC','UTC',$arr['edited']) : datetime_convert());
418 $arr['changed'] = datetime_convert();
419 $arr['title'] = notags(trim($arr['title']));
420 $arr['location'] = notags(trim($arr['location']));
421 $arr['body'] = escape_tags(trim($arr['body']));
422 $arr['last-child'] = intval($arr['last-child']);
423 $arr['visible'] = ((x($arr,'visible') !== false) ? intval($arr['visible']) : 1);
425 $arr['parent-uri'] = notags(trim($arr['parent-uri']));
426 $arr['verb'] = notags(trim($arr['verb']));
427 $arr['object-type'] = notags(trim($arr['object-type']));
428 $arr['object'] = trim($arr['object']);
431 $parent_missing = false;
435 $r = q("INSERT INTO `item` (`"
436 . implode("`, `", array_keys($arr))
438 . implode("', '", array_values($arr))
441 // find the parent and snarf the item id and ACL's
443 $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
444 dbesc($arr['parent-uri']),
449 $parent_id = $r[0]['id'];
450 $allow_cid = $r[0]['allow_cid'];
451 $allow_gid = $r[0]['allow_gid'];
452 $deny_cid = $r[0]['deny_cid'];
453 $deny_gid = $r[0]['deny_gid'];
456 $parent_missing = true;
459 $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
460 $arr['uri'], // already dbesc'd
464 $current_post = $r[0]['id'];
468 if($parent_missing) {
470 // perhaps the parent was deleted, but in any case, this thread is dead
471 // and unfortunately our brand new item now has to be destroyed
473 q("DELETE FROM `item` WHERE `id` = %d LIMIT 1",
474 intval($current_post)
479 // Set parent id - all of the parent's ACL's are also inherited by this post
481 $r = q("UPDATE `item` SET `parent` = %d, `allow_cid` = '%s', `allow_gid` = '%s',
482 `deny_cid` = '%s', `deny_gid` = '%s' WHERE `id` = %d LIMIT 1",
488 intval($current_post)
491 return $current_post;
494 function get_item_contact($item,$contacts) {
495 if(! count($contacts) || (! is_array($item)))
497 foreach($contacts as $contact) {
498 if($contact['id'] == $item['contact-id']) {
507 function dfrn_deliver($contact,$atom,$debugging = false) {
510 if((! strlen($contact['dfrn-id'])) && (! $contact['duplex']))
513 $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
515 if($contact['duplex'] && $contact['dfrn-id'])
516 $idtosend = '0:' . $orig_id;
517 if($contact['duplex'] && $contact['issued-id'])
518 $idtosend = '1:' . $orig_id;
520 $url = $contact['notify'] . '?dfrn_id=' . $idtosend;
525 $xml = fetch_url($url);
533 $res = simplexml_load_string($xml);
535 if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id)))
536 return (($res->status) ? $res->status : 3);
539 $sent_dfrn_id = hex2bin($res->dfrn_id);
540 $challenge = hex2bin($res->challenge);
544 if($contact['duplex'] && strlen($contact['prvkey'])) {
545 openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']);
546 openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']);
549 openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']);
550 openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']);
553 $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
555 if(strpos($final_dfrn_id,':') == 1)
556 $final_dfrn_id = substr($final_dfrn_id,2);
558 if($final_dfrn_id != $orig_id) {
559 // did not decode properly - cannot trust this site
563 $postvars['dfrn_id'] = $idtosend;
566 if(($contact['rel']) && ($contact['rel'] != REL_FAN) && (! $contact['blocked']) && (! $contact['readonly'])) {
567 $postvars['data'] = $atom;
570 $postvars['data'] = str_replace('<dfrn:comment-allow>1','<dfrn:comment-allow>0',$atom);
573 $xml = post_url($contact['notify'],$postvars);
578 $res = simplexml_load_string($xml);
585 function consume_feed($xml,$importer,$contact, &$hub) {
587 require_once('simplepie/simplepie.inc');
589 $feed = new SimplePie();
590 $feed->set_raw_data($xml);
591 $feed->enable_order_by_date(false);
594 // Check at the feed level for updated contact name and/or photo
598 $photo_timestamp = '';
602 $foundhub = $feed->get_link(0,'hub');
604 if(strlen($foundhub))
607 $rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
609 $elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10];
610 if($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) {
611 $name_updated = $elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated'];
612 $new_name = $elems['name'][0]['data'];
614 if(($elems['link'][0]['attribs']['']['rel'] === 'photo') && ($elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated'])) {
615 $photo_timestamp = datetime_convert('UTC','UTC',$elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']);
616 $photo_url = $elems['link'][0]['attribs']['']['href'];
619 if(! $photo_timestamp) {
620 $photo_rawupdate = $feed->get_feed_tags(NAMESPACE_DFRN,'icon-updated');
621 if($photo_rawupdate) {
622 $photo_timestamp = datetime_convert('UTC','UTC',$photo_rawupdate[0]['data']);
623 $photo_url = $feed->get_image_url();
626 if(($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $contact['avatar-date'])) {
628 require_once("Photo.php");
629 $photo_failure = false;
631 $r = q("SELECT `resource-id` FROM `photo` WHERE `contact-id` = %d AND `uid` = %d LIMIT 1",
632 intval($contact['id']),
633 intval($contact['uid'])
636 $resource_id = $r[0]['resource-id'];
637 $img_str = fetch_url($photo_url,true);
638 $img = new Photo($img_str);
639 if($img->is_valid()) {
640 q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND contact-id` = %d AND `uid` = %d",
642 intval($contact['id']),
643 intval($contact['uid'])
646 $img->scaleImageSquare(175);
648 $hash = $resource_id;
649 $r = $img->store($contact['uid'], $contact['id'], $hash, basename($photo_url), t('Contact Photos') , 4);
651 $img->scaleImage(80);
652 $r = $img->store($contact['uid'], $contact['id'], $hash, basename($photo_url), t('Contact Photos') , 5);
654 q("UPDATE `contact` SET `avatar-date` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1",
655 dbesc(datetime_convert()),
656 intval($contact['uid']),
657 intval($contact['id'])
663 if(($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) {
664 q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1",
665 dbesc(notags(trim($new_name))),
666 dbesc(datetime_convert()),
667 intval($contact['uid']),
668 intval($contact['id'])
672 // Now process the feed
673 if($feed->get_item_quantity()) {
674 foreach($feed->get_items() as $item) {
678 $rawdelete = $item->get_item_tags( NAMESPACE_TOMB, 'deleted-entry');
679 if(isset($rawdelete[0]['attribs']['']['ref'])) {
680 $uri = $rawthread[0]['attribs']['']['ref'];
682 if(isset($rawdelete[0]['attribs']['']['when'])) {
683 $when = $rawthread[0]['attribs']['']['when'];
684 $when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s');
687 $when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
690 $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
692 intval($importer['uid'])
696 if($item['uri'] == $item['parent-uri']) {
697 $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
698 `body` = '', `title` = ''
699 WHERE `parent-uri` = '%s' AND `uid` = %d",
701 dbesc(datetime_convert()),
703 intval($importer['uid'])
707 $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
708 `body` = '', `title` = ''
709 WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
711 dbesc(datetime_convert()),
713 intval($importer['uid'])
715 if($item['last-child']) {
716 // ensure that last-child is set in case the comment that had it just got wiped.
717 $q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ",
718 dbesc(datetime_convert()),
719 dbesc($item['parent-uri']),
722 // who is the last child now?
723 $r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d
724 ORDER BY `created` DESC LIMIT 1",
725 dbesc($item['parent-uri']),
726 intval($importer['uid'])
729 q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d LIMIT 1",
741 $item_id = $item->get_id();
742 $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
743 if(isset($rawthread[0]['attribs']['']['ref'])) {
745 $parent_uri = $rawthread[0]['attribs']['']['ref'];
751 // Have we seen it? If not, import it.
753 $item_id = $item->get_id();
755 $r = q("SELECT `uid`, `last-child`, `edited` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
757 intval($importer['uid'])
759 // FIXME update content if 'updated' changes
761 $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
762 if($allow && $allow[0]['data'] != $r[0]['last-child']) {
763 $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
764 dbesc(datetime_convert()),
766 intval($importer['uid'])
768 $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
769 intval($allow[0]['data']),
770 dbesc(datetime_convert()),
772 intval($importer['uid'])
778 $datarray = get_atom_elements($item);
779 $datarray['parent-uri'] = $parent_uri;
780 $datarray['uid'] = $importer['uid'];
781 $datarray['contact-id'] = $contact['id'];
782 if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) {
783 $datarray['type'] = 'activity';
784 $datarray['gravity'] = GRAVITY_LIKE;
787 $r = item_store($datarray);
792 // Head post of a conversation. Have we seen it? If not, import it.
794 $item_id = $item->get_id();
795 $r = q("SELECT `uid`, `last-child`, `edited` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
797 intval($importer['uid'])
800 $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
801 if($allow && $allow[0]['data'] != $r[0]['last-child']) {
802 $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
803 intval($allow[0]['data']),
804 dbesc(datetime_convert()),
806 intval($importer['uid'])
811 $datarray = get_atom_elements($item);
812 $datarray['parent-uri'] = $item_id;
813 $datarray['uid'] = $importer['uid'];
814 $datarray['contact-id'] = $contact['id'];
815 $r = item_store($datarray);
825 function subscribe_to_hub($url,$importer,$contact) {
827 if(is_array($importer)) {
828 $r = q("SELECT `nickname` FROM `user` WHERE `uid` = %d LIMIT 1",
829 intval($importer['uid'])
835 $push_url = get_config('system','url') . '/pubsub/' . $r[0]['nickname'] . '/' . $contact['id'];
837 $verify_token = random_string();
839 $params= 'hub.mode=subscribe&hub.callback=' . urlencode($push_url) . '&hub.topic=' . urlencode($contact['poll']) . '&hub.verify=async&hub.verify_token=' . $verify_token;
841 $r = q("UPDATE `contact` SET `hub-verify` = '%s' WHERE `id` = %d LIMIT 1",
842 dbesc($verify_token),
843 intval($contact['id'])
846 post_url($url,$params);