function subthread_content(&$a) { if (!local_user() && !remote_user()) { return; } $activity = ACTIVITY_FOLLOW; $item_id = $a->argc > 1 ? notags(trim($a->argv[1])) : 0; $r = q("SELECT * FROM `item` WHERE `parent` = '%s' OR `parent-uri` = '%s' and parent = id LIMIT 1", dbesc($item_id), dbesc($item_id)); if (!$item_id || !count($r)) { logger('subthread: no item ' . $item_id); return; } $item = $r[0]; $owner_uid = $item['uid']; if (!can_write_wall($a, $owner_uid)) { return; } $remote_owner = null; if (!$item['wall']) { // The top level post may have been written by somebody on another system $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['contact-id']), intval($item['uid'])); if (!count($r)) { return; } if (!$r[0]['self']) { $remote_owner = $r[0]; } } // this represents the post owner on this system. $r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\tWHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1", intval($owner_uid)); if (count($r)) { $owner = $r[0]; } if (!$owner) { logger('like: no owner'); return; } if (!$remote_owner) { $remote_owner = $owner; } // This represents the person posting if (local_user() && local_user() == $owner_uid) { $contact = $owner; } else { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($_SESSION['visitor_id']), intval($owner_uid)); if (count($r)) { $contact = $r[0]; } } if (!$contact) { return; } $uri = item_new_uri($a->get_hostname(), $owner_uid); $post_type = $item['resource-id'] ? t('photo') : t('status'); $objtype = $item['resource-id'] ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE; $link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n"); $body = $item['body']; $obj = <<<EOT \t<object> \t\t<type>{$objtype}</type> \t\t<local>1</local> \t\t<id>{$item['uri']}</id> \t\t<link>{$link}</link> \t\t<title></title> \t\t<content>{$body}</content> \t</object> EOT; $bodyverb = t('%1$s is following %2$s\'s %3$s'); if (!isset($bodyverb)) { return; } $arr = array(); $arr['uri'] = $uri; $arr['uid'] = $owner_uid; $arr['contact-id'] = $contact['id']; $arr['type'] = 'activity'; $arr['wall'] = $item['wall']; $arr['origin'] = 1; $arr['gravity'] = GRAVITY_LIKE; $arr['parent'] = $item['id']; $arr['parent-uri'] = $item['uri']; $arr['thr-parent'] = $item['uri']; $arr['owner-name'] = $remote_owner['name']; $arr['owner-link'] = $remote_owner['url']; $arr['owner-avatar'] = $remote_owner['thumb']; $arr['author-name'] = $contact['name']; $arr['author-link'] = $contact['url']; $arr['author-avatar'] = $contact['thumb']; $ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]'; $plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]'; $arr['body'] = sprintf($bodyverb, $ulink, $alink, $plink); $arr['verb'] = $activity; $arr['object-type'] = $objtype; $arr['object'] = $obj; $arr['allow_cid'] = $item['allow_cid']; $arr['allow_gid'] = $item['allow_gid']; $arr['deny_cid'] = $item['deny_cid']; $arr['deny_gid'] = $item['deny_gid']; $arr['visible'] = 1; $arr['unseen'] = 1; $arr['last-child'] = 0; $post_id = item_store($arr); if (!$item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['id']), intval($owner_uid)); } $arr['id'] = $post_id; call_hooks('post_local_end', $arr); killme(); }
function pumpio_dolike(&$a, $uid, $self, $post, $own_id, $threadcompletion = true) { require_once 'include/items.php'; // Searching for the liked post // Two queries for speed issues $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($post->object->id), intval($uid)); if (count($r)) { $orig_post = $r[0]; } else { $r = q("SELECT * FROM `item` WHERE `extid` = '%s' AND `uid` = %d LIMIT 1", dbesc($post->object->id), intval($uid)); if (!count($r)) { return; } else { $orig_post = $r[0]; } } // thread completion if ($threadcompletion) { pumpio_fetchallcomments($a, $uid, $post->object->id); } $contactid = 0; if (link_compare($post->actor->url, $own_id)) { $contactid = $self[0]['id']; $post->actor->displayName = $self[0]['name']; $post->actor->url = $self[0]['url']; $post->actor->image->url = $self[0]['photo']; } else { $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1", dbesc($post->actor->url), intval($uid)); if (count($r)) { $contactid = $r[0]['id']; } if ($contactid == 0) { $contactid = $orig_post['contact-id']; } } $r = q("SELECT parent FROM `item` WHERE `verb` = '%s' AND `uid` = %d AND `contact-id` = %d AND `thr-parent` = '%s' LIMIT 1", dbesc(ACTIVITY_LIKE), intval($uid), intval($contactid), dbesc($orig_post['uri'])); if (count($r)) { logger("pumpio_dolike: found existing like. User " . $own_id . " " . $uid . " Contact: " . $contactid . " Url " . $orig_post['uri']); return; } $likedata = array(); $likedata['parent'] = $orig_post['id']; $likedata['verb'] = ACTIVITY_LIKE; $likedata['gravity'] = 3; $likedata['uid'] = $uid; $likedata['wall'] = 0; $likedata['uri'] = item_new_uri($a->get_baseurl(), $uid); $likedata['parent-uri'] = $orig_post["uri"]; $likedata['contact-id'] = $contactid; $likedata['app'] = $post->generator->displayName; $likedata['author-name'] = $post->actor->displayName; $likedata['author-link'] = $post->actor->url; $likedata['author-avatar'] = $post->actor->image->url; $author = '[url=' . $likedata['author-link'] . ']' . $likedata['author-name'] . '[/url]'; $objauthor = '[url=' . $orig_post['author-link'] . ']' . $orig_post['author-name'] . '[/url]'; $post_type = t('status'); $plink = '[url=' . $orig_post['plink'] . ']' . $post_type . '[/url]'; $likedata['object-type'] = ACTIVITY_OBJ_NOTE; $likedata['body'] = sprintf(t('%1$s likes %2$s\'s %3$s'), $author, $objauthor, $plink); $likedata['object'] = '<object><type>' . ACTIVITY_OBJ_NOTE . '</type><local>1</local>' . '<id>' . $orig_post['uri'] . '</id><link>' . xmlify('<link rel="alternate" type="text/html" href="' . xmlify($orig_post['plink']) . '" />') . '</link><title>' . $orig_post['title'] . '</title><content>' . $orig_post['body'] . '</content></object>'; $ret = item_store($likedata); logger("pumpio_dolike: " . $ret . " User " . $own_id . " " . $uid . " Contact: " . $contactid . " Url " . $orig_post['uri']); }
function event_store($arr) { require_once 'include/datetime.php'; require_once 'include/items.php'; require_once 'include/bbcode.php'; $a = get_app(); $arr['created'] = $arr['created'] ? $arr['created'] : datetime_convert(); $arr['edited'] = $arr['edited'] ? $arr['edited'] : datetime_convert(); $arr['type'] = $arr['type'] ? $arr['type'] : 'event'; $arr['cid'] = intval($arr['cid']) ? intval($arr['cid']) : 0; $arr['uri'] = x($arr, 'uri') ? $arr['uri'] : item_new_uri($a->get_hostname(), $arr['uid']); $arr['private'] = x($arr, 'private') ? intval($arr['private']) : 0; if ($arr['cid']) { $c = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($arr['cid']), intval($arr['uid'])); } else { $c = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($arr['uid'])); } if (count($c)) { $contact = $c[0]; } // Existing event being modified if ($arr['id']) { // has the event actually changed? $r = q("SELECT * FROM `event` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($arr['id']), intval($arr['uid'])); if (!count($r) || $r[0]['edited'] === $arr['edited']) { // Nothing has changed. Grab the item id to return. $r = q("SELECT * FROM `item` WHERE `event-id` = %d AND `uid` = %d LIMIT 1", intval($arr['id']), intval($arr['uid'])); return count($r) ? $r[0]['id'] : 0; } // The event changed. Update it. $r = q("UPDATE `event` SET\n\t\t\t`edited` = '%s',\n\t\t\t`start` = '%s',\n\t\t\t`finish` = '%s',\n\t\t\t`desc` = '%s',\n\t\t\t`location` = '%s',\n\t\t\t`type` = '%s',\n\t\t\t`adjust` = %d,\n\t\t\t`nofinish` = %d,\n\t\t\t`allow_cid` = '%s',\n\t\t\t`allow_gid` = '%s',\n\t\t\t`deny_cid` = '%s',\n\t\t\t`deny_gid` = '%s'\n\t\t\tWHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($arr['edited']), dbesc($arr['start']), dbesc($arr['finish']), dbesc($arr['desc']), dbesc($arr['location']), dbesc($arr['type']), intval($arr['adjust']), intval($arr['nofinish']), dbesc($arr['allow_cid']), dbesc($arr['allow_gid']), dbesc($arr['deny_cid']), dbesc($arr['deny_gid']), intval($arr['id']), intval($arr['uid'])); $r = q("SELECT * FROM `item` WHERE `event-id` = %d AND `uid` = %d LIMIT 1", intval($arr['id']), intval($arr['uid'])); if (count($r)) { $object = '<object><type>' . xmlify(ACTIVITY_OBJ_EVENT) . '</type><title></title><id>' . xmlify($arr['uri']) . '</id>'; $object .= '<content>' . xmlify(format_event_bbcode($arr)) . '</content>'; $object .= '</object>' . "\n"; q("UPDATE `item` SET `body` = '%s', `object` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `edited` = '%s', `private` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc(format_event_bbcode($arr)), dbesc($object), dbesc($arr['allow_cid']), dbesc($arr['allow_gid']), dbesc($arr['deny_cid']), dbesc($arr['deny_gid']), dbesc($arr['edited']), intval($arr['private']), intval($r[0]['id']), intval($arr['uid'])); return $r[0]['id']; } else { return 0; } } else { // New event. Store it. $r = q("INSERT INTO `event` ( `uid`,`cid`,`uri`,`created`,`edited`,`start`,`finish`,`desc`,`location`,`type`,\n\t\t\t`adjust`,`nofinish`,`allow_cid`,`allow_gid`,`deny_cid`,`deny_gid`)\n\t\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' ) ", intval($arr['uid']), intval($arr['cid']), dbesc($arr['uri']), dbesc($arr['created']), dbesc($arr['edited']), dbesc($arr['start']), dbesc($arr['finish']), dbesc($arr['desc']), dbesc($arr['location']), dbesc($arr['type']), intval($arr['adjust']), intval($arr['nofinish']), dbesc($arr['allow_cid']), dbesc($arr['allow_gid']), dbesc($arr['deny_cid']), dbesc($arr['deny_gid'])); $r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($arr['uri']), intval($arr['uid'])); if (count($r)) { $event = $r[0]; } $item_arr = array(); $item_arr['uid'] = $arr['uid']; $item_arr['contact-id'] = $arr['cid']; $item_arr['uri'] = $arr['uri']; $item_arr['parent-uri'] = $arr['uri']; $item_arr['type'] = 'activity'; $item_arr['wall'] = $arr['cid'] ? 0 : 1; $item_arr['contact-id'] = $contact['id']; $item_arr['owner-name'] = $contact['name']; $item_arr['owner-link'] = $contact['url']; $item_arr['owner-avatar'] = $contact['thumb']; $item_arr['author-name'] = $contact['name']; $item_arr['author-link'] = $contact['url']; $item_arr['author-avatar'] = $contact['thumb']; $item_arr['title'] = ''; $item_arr['allow_cid'] = $arr['allow_cid']; $item_arr['allow_gid'] = $arr['allow_gid']; $item_arr['deny_cid'] = $arr['deny_cid']; $item_arr['deny_gid'] = $arr['deny_gid']; $item_arr['private'] = $arr['private']; $item_arr['last-child'] = 1; $item_arr['visible'] = 1; $item_arr['verb'] = ACTIVITY_POST; $item_arr['object-type'] = ACTIVITY_OBJ_EVENT; $item_arr['origin'] = intval($arr['cid']) == 0 ? 1 : 0; $item_arr['body'] = format_event_bbcode($event); $item_arr['object'] = '<object><type>' . xmlify(ACTIVITY_OBJ_EVENT) . '</type><title></title><id>' . xmlify($uri) . '</id>'; $item_arr['object'] .= '<content>' . xmlify(format_event_bbcode($event)) . '</content>'; $item_arr['object'] .= '</object>' . "\n"; $item_id = item_store($item_arr); $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($arr['uid'])); if (count($r)) { $plink = $a->get_baseurl() . '/display/' . $r[0]['nickname'] . '/' . $item_id; } if ($item_id) { q("UPDATE `item` SET `plink` = '%s', `event-id` = %d WHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc($plink), intval($event['id']), intval($arr['uid']), intval($item_id)); } return $item_id; } }
function profile_activity($changed, $value) { $a = get_app(); if (!local_user() || !is_array($changed) || !count($changed)) { return; } if ($a->user['hidewall'] || get_config('system', 'block_public')) { return; } if (!get_pconfig(local_user(), 'system', 'post_profilechange')) { return; } require_once 'include/items.php'; $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval(local_user())); if (!count($self)) { return; } $arr = array(); $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), local_user()); $arr['uid'] = local_user(); $arr['contact-id'] = $self[0]['id']; $arr['wall'] = 1; $arr['type'] = 'wall'; $arr['gravity'] = 0; $arr['origin'] = 1; $arr['author-name'] = $arr['owner-name'] = $self[0]['name']; $arr['author-link'] = $arr['owner-link'] = $self[0]['url']; $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb']; $arr['verb'] = ACTIVITY_UPDATE; $arr['object-type'] = ACTIVITY_OBJ_PROFILE; $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]'; $changes = ''; $t = count($changed); $z = 0; foreach ($changed as $ch) { if (strlen($changes)) { if ($z == $t - 1) { $changes .= t(' and '); } else { $changes .= ', '; } } $z++; $changes .= $ch; } $prof = '[url=' . $self[0]['url'] . '?tab=profile' . ']' . t('public profile') . '[/url]'; if ($t == 1 && strlen($value)) { $message = sprintf(t('%1$s changed %2$s to “%3$s”'), $A, $changes, $value); $message .= "\n\n" . sprintf(t(' - Visit %1$s\'s %2$s'), $A, $prof); } else { $message = sprintf(t('%1$s has an updated %2$s, changing %3$s.'), $A, $prof, $changes); } $arr['body'] = $message; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PROFILE . '</type><title>' . $self[0]['name'] . '</title>' . '<id>' . $self[0]['url'] . '/' . $self[0]['name'] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $self[0]['url'] . '?tab=profile' . '" />' . "\n"); $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $self[0]['thumb'] . '" />' . "\n"); $arr['object'] .= '</link></object>' . "\n"; $arr['last-child'] = 1; $arr['allow_cid'] = $a->user['allow_cid']; $arr['allow_gid'] = $a->user['allow_gid']; $arr['deny_cid'] = $a->user['deny_cid']; $arr['deny_gid'] = $a->user['deny_gid']; $i = item_store($arr); if ($i) { // give it a permanent link //q("update item set plink = '%s' where id = %d", // dbesc($a->get_baseurl() . '/display/' . $a->user['nickname'] . '/' . $i), // intval($i) //); proc_run('php', "include/notifier.php", "activity", "{$i}"); } }
function tagger_content(&$a) { if (!local_user() && !remote_user()) { return; } $term = notags(trim($_GET['term'])); // no commas allowed $term = str_replace(array(',', ' '), array('', '_'), $term); if (!$term) { return; } $item_id = $a->argc > 1 ? notags(trim($a->argv[1])) : 0; logger('tagger: tag ' . $term . ' item ' . $item_id); $r = q("SELECT * FROM `item` WHERE `id` = '%s' LIMIT 1", dbesc($item_id)); if (!$item_id || !count($r)) { logger('tagger: no item ' . $item_id); return; } $item = $r[0]; $owner_uid = $item['uid']; $r = q("select `nickname`,`blocktags` from user where uid = %d limit 1", intval($owner_uid)); if (count($r)) { $owner_nick = $r[0]['nickname']; $blocktags = $r[0]['blocktags']; } if (local_user() != $owner_uid) { return; } if (remote_user()) { $r = q("select * from contact where id = %d AND `uid` = %d limit 1", intval(remote_user()), intval($item['uid'])); } else { $r = q("select * from contact where self = 1 and uid = %d limit 1", intval(local_user())); } if (count($r)) { $contact = $r[0]; } else { logger('tagger: no contact_id'); return; } $uri = item_new_uri($a->get_hostname(), $owner_uid); $post_type = $item['resource-id'] ? t('photo') : t('status'); $targettype = $item['resource-id'] ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE; $link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n"); $body = $item['body']; $target = <<<EOT \t<target> \t\t<type>{$targettype}</type> \t\t<local>1</local> \t\t<id>{$item['uri']}</id> \t\t<link>{$link}</link> \t\t<title></title> \t\t<content>{$body}</content> \t</target> EOT; $tagid = $a->get_baseurl() . '/search?search=' . $term; $objtype = ACTIVITY_OBJ_TAGTERM; $obj = <<<EOT \t<object> \t\t<type>{$objtype}</type> \t\t<local>1</local> \t\t<id>{$tagid}</id> \t\t<link>{$tagid}</link> \t\t<title>{$term}</title> \t\t<content>{$term}</content> \t</object> EOT; $bodyverb = t('%1$s tagged %2$s\'s %3$s with %4$s'); if (!isset($bodyverb)) { return; } $termlink = html_entity_decode('⌗') . '[url=' . $a->get_baseurl() . '/search?search=' . urlencode($term) . ']' . $term . '[/url]'; $arr = array(); $arr['uri'] = $uri; $arr['uid'] = $owner_uid; $arr['contact-id'] = $contact['id']; $arr['type'] = 'activity'; $arr['wall'] = $item['wall']; $arr['gravity'] = GRAVITY_COMMENT; $arr['parent'] = $item['id']; $arr['parent-uri'] = $item['uri']; $arr['owner-name'] = $item['author-name']; $arr['owner-link'] = $item['author-link']; $arr['owner-avatar'] = $item['author-avatar']; $arr['author-name'] = $contact['name']; $arr['author-link'] = $contact['url']; $arr['author-avatar'] = $contact['thumb']; $ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]'; $plink = '[url=' . $item['plink'] . ']' . $post_type . '[/url]'; $arr['body'] = sprintf($bodyverb, $ulink, $alink, $plink, $termlink); $arr['verb'] = ACTIVITY_TAG; $arr['target-type'] = $targettype; $arr['target'] = $target; $arr['object-type'] = $objtype; $arr['object'] = $obj; $arr['allow_cid'] = $item['allow_cid']; $arr['allow_gid'] = $item['allow_gid']; $arr['deny_cid'] = $item['deny_cid']; $arr['deny_gid'] = $item['deny_gid']; $arr['visible'] = 1; $arr['unseen'] = 1; $arr['last-child'] = 1; $arr['origin'] = 1; $post_id = item_store($arr); q("UPDATE `item` set plink = '%s' where id = %d limit 1", dbesc($a->get_baseurl() . '/display/' . $owner_nick . '/' . $post_id), intval($post_id)); if (!$item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['id']), intval($owner_uid)); } if (!$blocktags && !stristr($item['tag'], ']' . $term . '[')) { q("update item set tag = '%s' where id = %d limit 1", dbesc($item['tag'] . (strlen($item['tag']) ? ',' : '') . '#[url=' . $a->get_baseurl() . '/search?search=' . $term . ']' . $term . '[/url]'), intval($item['id'])); } // if the original post is on this site, update it. $r = q("select `tag`,`id`,`uid` from item where `origin` = 1 AND `uri` = '%s' LIMIT 1", dbesc($item['uri'])); if (count($r)) { $x = q("SELECT `blocktags` FROM `user` WHERE `uid` = %d limit 1", intval($r[0]['uid'])); if (count($x) && !$x[0]['blocktags'] && !stristr($r[0]['tag'], ']' . $term . '[')) { q("update item set tag = '%s' where id = %d limit 1", dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . '#[url=' . $a->get_baseurl() . '/search?search=' . $term . ']' . $term . '[/url]'), intval($r[0]['id'])); } } $arr['id'] = $post_id; call_hooks('post_local_end', $arr); proc_run('php', "include/notifier.php", "tag", "{$post_id}"); killme(); return; // NOTREACHED }
function fbsync_createlike($a, $uid, $self_id, $self, $contacts, $like) { $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc("fb::" . $like->post_id), intval($uid)); if (count($r)) { $orig_post = $r[0]; } else { return; } // If we posted the like locally, it will be found with our url, not the FB url. $second_url = $like->user_id == $self_id ? $self[0]["url"] : $contacts[$like->user_id]->url; $r = q("SELECT * FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s'\n\t\tAND (`author-link` = '%s' OR `author-link` = '%s') LIMIT 1", dbesc($orig_post["uri"]), intval($uid), dbesc(ACTIVITY_LIKE), dbesc($contacts[$like->user_id]->url), dbesc($second_url)); if (count($r)) { return; } $contact_id = fbsync_fetch_contact($uid, $contacts[$like->user_id], array(), false); if ($contact_id <= 0) { $contact_id = $self[0]["id"]; } $likedata = array(); $likedata['parent'] = $orig_post['id']; $likedata['verb'] = ACTIVITY_LIKE; $likedata['object-type'] = ACTIVITY_OBJ_NOTE; $likedate['network'] = dbesc(NETWORK_FACEBOOK); $likedata['gravity'] = 3; $likedata['uid'] = $uid; $likedata['wall'] = 0; $likedata['uri'] = item_new_uri($a->get_baseurl(), $uid); $likedata['parent-uri'] = $orig_post["uri"]; $likedata['app'] = "Facebook"; if ($like->user_id != $self_id) { $likedata['contact-id'] = $contact_id; $likedata['author-name'] = $contacts[$like->user_id]->name; $likedata['author-link'] = $contacts[$like->user_id]->url; $likedata['author-avatar'] = $contacts[$like->user_id]->pic_square; } else { $likedata['contact-id'] = $self[0]["id"]; $likedata['author-name'] = $self[0]["name"]; $likedata['author-link'] = $self[0]["url"]; $likedata['author-avatar'] = $self[0]["photo"]; } $author = '[url=' . $likedata['author-link'] . ']' . $likedata['author-name'] . '[/url]'; $objauthor = '[url=' . $orig_post['author-link'] . ']' . $orig_post['author-name'] . '[/url]'; $post_type = t('status'); $plink = '[url=' . $orig_post['plink'] . ']' . $post_type . '[/url]'; $likedata['object-type'] = ACTIVITY_OBJ_NOTE; $likedata['body'] = sprintf(t('%1$s likes %2$s\'s %3$s'), $author, $objauthor, $plink); $likedata['object'] = '<object><type>' . ACTIVITY_OBJ_NOTE . '</type><local>1</local>' . '<id>' . $orig_post['uri'] . '</id><link>' . xmlify('<link rel="alternate" type="text/html" href="' . xmlify($orig_post['plink']) . '" />') . '</link><title>' . $orig_post['title'] . '</title><content>' . $orig_post['body'] . '</content></object>'; $r = q("SELECT * FROM `item` WHERE `parent-uri` = '%s' AND `author-link` = '%s' AND `verb` = '%s' AND `uid` = %d LIMIT 1", dbesc($likedata['parent-uri']), dbesc($likedata['author-link']), dbesc(ACTIVITY_LIKE), intval($uid)); if (count($r)) { return; } $item = item_store($likedata); logger('fbsync_createlike: liked item ' . $item . '. User ' . $self[0]["nick"], LOGGER_DEBUG); }
function item_post(&$a) { if (!local_user() && !remote_user()) { return; } require_once 'include/security.php'; $uid = local_user(); if (x($_POST, 'dropitems')) { require_once 'include/items.php'; $arr_drop = explode(',', $_POST['dropitems']); drop_items($arr_drop); $json = array('success' => 1); echo json_encode($json); killme(); } call_hooks('post_local_start', $_POST); $api_source = x($_POST, 'api_source') && $_POST['api_source'] ? true : false; $return_path = x($_POST, 'return') ? $_POST['return'] : ''; /** * Is this a reply to something? */ $parent = x($_POST, 'parent') ? intval($_POST['parent']) : 0; $parent_uri = x($_POST, 'parent_uri') ? trim($_POST['parent_uri']) : ''; $parent_item = null; $parent_contact = null; $thr_parent = ''; $parid = 0; $r = false; $preview = x($_POST, 'preview') ? intval($_POST['preview']) : 0; if ($parent || $parent_uri) { if (!x($_POST, 'type')) { $_POST['type'] = 'net-comment'; } if ($parent) { $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent)); } elseif ($parent_uri && local_user()) { // This is coming from an API source, and we are logged in $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_uri), intval(local_user())); } // if this isn't the real parent of the conversation, find it if ($r !== false && count($r)) { $parid = $r[0]['parent']; if ($r[0]['id'] != $r[0]['parent']) { $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1", intval($parid)); } } if ($r === false || !count($r)) { notice(t('Unable to locate original post.') . EOL); if (x($_POST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } $parent_item = $r[0]; $parent = $r[0]['id']; // multi-level threading - preserve the info but re-parent to our single level threading if ($parid && $parid != $parent) { $thr_parent = $parent_uri; } if ($parent_item['contact-id'] && $uid) { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($parent_item['contact-id']), intval($uid)); if (count($r)) { $parent_contact = $r[0]; } } } if ($parent) { logger('mod_post: parent=' . $parent); } $profile_uid = x($_POST, 'profile_uid') ? intval($_POST['profile_uid']) : 0; $post_id = x($_POST['post_id']) ? intval($_POST['post_id']) : 0; $app = x($_POST['source']) ? strip_tags($_POST['source']) : ''; if (!can_write_wall($a, $profile_uid)) { notice(t('Permission denied.') . EOL); if (x($_POST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } // is this an edited post? $orig_post = null; if ($post_id) { $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($post_id)); if (!count($i)) { killme(); } $orig_post = $i[0]; } $user = null; $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($profile_uid)); if (count($r)) { $user = $r[0]; } if ($orig_post) { $str_group_allow = $orig_post['allow_gid']; $str_contact_allow = $orig_post['allow_cid']; $str_group_deny = $orig_post['deny_gid']; $str_contact_deny = $orig_post['deny_cid']; $title = $orig_post['title']; $location = $orig_post['location']; $coord = $orig_post['coord']; $verb = $orig_post['verb']; $emailcc = $orig_post['emailcc']; $app = $orig_post['app']; $body = escape_tags(trim($_POST['body'])); $private = $orig_post['private']; $pubmail_enable = $orig_post['pubmail']; } else { $str_group_allow = perms2str($_POST['group_allow']); $str_contact_allow = perms2str($_POST['contact_allow']); $str_group_deny = perms2str($_POST['group_deny']); $str_contact_deny = perms2str($_POST['contact_deny']); $title = notags(trim($_POST['title'])); $location = notags(trim($_POST['location'])); $coord = notags(trim($_POST['coord'])); $verb = notags(trim($_POST['verb'])); $emailcc = notags(trim($_POST['emailcc'])); $body = escape_tags(trim($_POST['body'])); $private = strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) ? 1 : 0; if ($parent_item && ($parent_item['private'] || strlen($parent_item['allow_cid']) || strlen($parent_item['allow_gid']) || strlen($parent_item['deny_cid']) || strlen($parent_item['deny_gid']))) { $private = 1; } $pubmail_enable = x($_POST, 'pubmail_enable') && intval($_POST['pubmail_enable']) && !$private ? 1 : 0; // if using the API, we won't see pubmail_enable - figure out if it should be set if ($api_source && $profile_uid && $profile_uid == local_user() && !$private) { $mail_disabled = function_exists('imap_open') && !get_config('system', 'imap_disabled') ? 0 : 1; if (!$mail_disabled) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user())); if (count($r) && intval($r[0]['pubmail'])) { $pubmail_enabled = true; } } } if (!strlen($body)) { info(t('Empty post discarded.') . EOL); if (x($_POST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } } if ($api_source && !array_key_exists('allow_cid', $_REQUEST) && !array_key_exists('allow_gid', $_REQUEST) && !array_key_exists('deny_cid', $_REQUEST) && !array_key_exists('deny_gid', $_REQUEST)) { $str_group_allow = $user['allow_gid']; $str_contact_allow = $user['allow_cid']; $str_group_deny = $user['deny_gid']; $str_contact_deny = $user['deny_cid']; } // get contact info for poster $author = null; $self = false; if ($_SESSION['uid'] && $_SESSION['uid'] == $profile_uid) { $self = true; $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($_SESSION['uid'])); } else { if (x($_SESSION, 'visitor_id') && intval($_SESSION['visitor_id'])) { $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($_SESSION['visitor_id'])); } } if (count($r)) { $author = $r[0]; $contact_id = $author['id']; } // get contact info for owner if ($profile_uid == $_SESSION['uid']) { $contact_record = $author; } else { $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($profile_uid)); if (count($r)) { $contact_record = $r[0]; } } $post_type = notags(trim($_POST['type'])); if ($post_type === 'net-comment') { if ($parent_item !== null) { if ($parent_item['wall'] == 1) { $post_type = 'wall-comment'; } else { $post_type = 'remote-comment'; } } } /** * * When a photo was uploaded into the message using the (profile wall) ajax * uploader, The permissions are initially set to disallow anybody but the * owner from seeing it. This is because the permissions may not yet have been * set for the post. If it's private, the photo permissions should be set * appropriately. But we didn't know the final permissions on the post until * now. So now we'll look for links of uploaded messages that are in the * post and set them to the same permissions as the post itself. * */ $match = null; if (!$preview && preg_match_all("/\\[img\\](.*?)\\[\\/img\\]/", $body, $match)) { $images = $match[1]; if (count($images)) { foreach ($images as $image) { if (!stristr($image, $a->get_baseurl() . '/photo/')) { continue; } $image_uri = substr($image, strrpos($image, '/') + 1); $image_uri = substr($image_uri, 0, strpos($image_uri, '-')); if (!strlen($image_uri)) { continue; } $srch = '<' . intval($profile_uid) . '>'; $r = q("SELECT `id` FROM `photo` WHERE `allow_cid` = '%s' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = ''\n\t\t\t\t\tAND `resource-id` = '%s' AND `uid` = %d LIMIT 1", dbesc($srch), dbesc($image_uri), intval($profile_uid)); if (!count($r)) { continue; } $r = q("UPDATE `photo` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\tWHERE `resource-id` = '%s' AND `uid` = %d AND `album` = '%s' ", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), dbesc($image_uri), intval($profile_uid), dbesc(t('Wall Photos'))); } } } /** * Next link in any attachment references we find in the post. */ $match = false; if (!$preview && preg_match_all("/\\[attachment\\](.*?)\\[\\/attachment\\]/", $body, $match)) { $attaches = $match[1]; if (count($attaches)) { foreach ($attaches as $attach) { $r = q("SELECT * FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($attach)); if (count($r)) { $r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\t\tWHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), intval($profile_uid), intval($attach)); } } } } // embedded bookmark in post? set bookmark flag $bookmark = 0; if (preg_match_all("/\\[bookmark\\=([^\\]]*)\\](.*?)\\[\\/bookmark\\]/ism", $body, $match, PREG_SET_ORDER)) { $bookmark = 1; } $body = bb_translate_video($body); /** * Fold multi-line [code] sequences */ $body = preg_replace('/\\[\\/code\\]\\s*\\[code\\]/ism', "\n", $body); /** * Look for any tags and linkify them */ $str_tags = ''; $inform = ''; $tags = get_tags($body); /** * add a statusnet style reply tag if the original post was from there * and we are replying, and there isn't one already */ if ($parent_contact && $parent_contact['network'] === NETWORK_OSTATUS && $parent_contact['nick'] && !in_array('@' . $parent_contact['nick'], $tags)) { $body = '@' . $parent_contact['nick'] . ' ' . $body; $tags[] = '@' . $parent_contact['nick']; } if (count($tags)) { foreach ($tags as $tag) { if (isset($profile)) { unset($profile); } if (strpos($tag, '#') === 0) { if (strpos($tag, '[url=')) { continue; } $basetag = str_replace('_', ' ', substr($tag, 1)); $body = str_replace($tag, '#[url=' . $a->get_baseurl() . '/search?search=' . rawurlencode($basetag) . ']' . $basetag . '[/url]', $body); $newtag = '#[url=' . $a->get_baseurl() . '/search?search=' . rawurlencode($basetag) . ']' . $basetag . '[/url]'; if (!stristr($str_tags, $newtag)) { if (strlen($str_tags)) { $str_tags .= ','; } $str_tags .= $newtag; } continue; } if (strpos($tag, '@') === 0) { if (strpos($tag, '[url=')) { continue; } $stat = false; $name = substr($tag, 1); if (strpos($name, '@') || strpos($name, 'http://')) { $newname = $name; $links = @lrdd($name); if (count($links)) { foreach ($links as $link) { if ($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') { $profile = $link['@attributes']['href']; } if ($link['@attributes']['rel'] === 'salmon') { if (strlen($inform)) { $inform .= ','; } $inform .= 'url:' . str_replace(',', '%2c', $link['@attributes']['href']); } } } } else { $newname = $name; $alias = ''; $tagcid = 0; if (strrpos($newname, '+')) { $tagcid = intval(substr($newname, strrpos($newname, '+') + 1)); if (strpos($name, ' ')) { $name = substr($name, 0, strpos($name, ' ')); } } if ($tagcid) { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($tagcid), intval($profile_uid)); } elseif (strstr($name, '_') || strstr($name, ' ')) { $newname = str_replace('_', ' ', $name); $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1", dbesc($newname), intval($profile_uid)); } else { $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1", dbesc($name), dbesc($name), intval($profile_uid)); } if (count($r)) { $profile = $r[0]['url']; if ($r[0]['network'] === 'stat') { $newname = $r[0]['nick']; $stat = true; if ($r[0]['alias']) { $alias = $r[0]['alias']; } } else { $newname = $r[0]['name']; } if (strlen($inform)) { $inform .= ','; } $inform .= 'cid:' . $r[0]['id']; } } if ($profile) { $body = str_replace('@' . $name, '@' . '[url=' . $profile . ']' . $newname . '[/url]', $body); $profile = str_replace(',', '%2c', $profile); $newtag = '@[url=' . $profile . ']' . $newname . '[/url]'; if (!stristr($str_tags, $newtag)) { if (strlen($str_tags)) { $str_tags .= ','; } $str_tags .= $newtag; } // Status.Net seems to require the numeric ID URL in a mention if the person isn't // subscribed to you. But the nickname URL is OK if they are. Grrr. We'll tag both. if (strlen($alias)) { $newtag = '@[url=' . $alias . ']' . $newname . '[/url]'; if (!stristr($str_tags, $newtag)) { if (strlen($str_tags)) { $str_tags .= ','; } $str_tags .= $newtag; } } } } } } $attachments = ''; $match = false; if (preg_match_all('/(\\[attachment\\]([0-9]+)\\[\\/attachment\\])/', $body, $match)) { foreach ($match[2] as $mtch) { $r = q("SELECT `id`,`filename`,`filesize`,`filetype` FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($mtch)); if (count($r)) { if (strlen($attachments)) { $attachments .= ','; } $attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" length="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . ($r[0]['filename'] ? $r[0]['filename'] : '') . '"[/attach]'; } $body = str_replace($match[1], '', $body); } } $wall = 0; if ($post_type === 'wall' || $post_type === 'wall-comment') { $wall = 1; } if (!strlen($verb)) { $verb = ACTIVITY_POST; } $gravity = $parent ? 6 : 0; // even if the post arrived via API we are considering that it // originated on this site by default for determining relayability. $origin = x($_REQUEST, 'origin') ? intval($_REQUEST['origin']) : 1; $notify_type = $parent ? 'comment-new' : 'wall-new'; $uri = item_new_uri($a->get_hostname(), $profile_uid); $datarray = array(); $datarray['uid'] = $profile_uid; $datarray['type'] = $post_type; $datarray['wall'] = $wall; $datarray['gravity'] = $gravity; $datarray['contact-id'] = $contact_id; $datarray['owner-name'] = $contact_record['name']; $datarray['owner-link'] = $contact_record['url']; $datarray['owner-avatar'] = $contact_record['thumb']; $datarray['author-name'] = $author['name']; $datarray['author-link'] = $author['url']; $datarray['author-avatar'] = $author['thumb']; $datarray['created'] = datetime_convert(); $datarray['edited'] = datetime_convert(); $datarray['commented'] = datetime_convert(); $datarray['received'] = datetime_convert(); $datarray['changed'] = datetime_convert(); $datarray['uri'] = $uri; $datarray['title'] = $title; $datarray['body'] = $body; $datarray['app'] = $app; $datarray['location'] = $location; $datarray['coord'] = $coord; $datarray['tag'] = $str_tags; $datarray['inform'] = $inform; $datarray['verb'] = $verb; $datarray['allow_cid'] = $str_contact_allow; $datarray['allow_gid'] = $str_group_allow; $datarray['deny_cid'] = $str_contact_deny; $datarray['deny_gid'] = $str_group_deny; $datarray['private'] = $private; $datarray['pubmail'] = $pubmail_enable; $datarray['attach'] = $attachments; $datarray['bookmark'] = intval($bookmark); $datarray['thr-parent'] = $thr_parent; $datarray['postopts'] = ''; $datarray['origin'] = $origin; /** * These fields are for the convenience of plugins... * 'self' if true indicates the owner is posting on their own wall * If parent is 0 it is a top-level post. */ $datarray['parent'] = $parent; $datarray['self'] = $self; // $datarray['prvnets'] = $user['prvnets']; if ($orig_post) { $datarray['edit'] = true; } else { $datarray['guid'] = get_guid(); } // preview mode - prepare the body for display and send it via json if ($preview) { require_once 'include/conversation.php'; $o = conversation(&$a, array(array_merge($contact_record, $datarray)), 'search', false, true); echo json_encode(array('preview' => $o)); killme(); } call_hooks('post_local', $datarray); if ($orig_post) { $r = q("UPDATE `item` SET `body` = '%s', `edited` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($body), dbesc(datetime_convert()), intval($post_id), intval($profile_uid)); proc_run('php', "include/notifier.php", 'edit_post', "{$post_id}"); if (x($_POST, 'return') && strlen($return_path)) { logger('return: ' . $return_path); goaway($a->get_baseurl() . "/" . $return_path); } killme(); } else { $post_id = 0; } $r = q("INSERT INTO `item` (`guid`, `uid`,`type`,`wall`,`gravity`,`contact-id`,`owner-name`,`owner-link`,`owner-avatar`, \n\t\t`author-name`, `author-link`, `author-avatar`, `created`, `edited`, `commented`, `received`, `changed`, `uri`, `thr-parent`, `title`, `body`, `app`, `location`, `coord`, \n\t\t`tag`, `inform`, `verb`, `postopts`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `private`, `pubmail`, `attach`, `bookmark`,`origin` )\n\t\tVALUES( '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d )", dbesc($datarray['guid']), intval($datarray['uid']), dbesc($datarray['type']), intval($datarray['wall']), intval($datarray['gravity']), intval($datarray['contact-id']), dbesc($datarray['owner-name']), dbesc($datarray['owner-link']), dbesc($datarray['owner-avatar']), dbesc($datarray['author-name']), dbesc($datarray['author-link']), dbesc($datarray['author-avatar']), dbesc($datarray['created']), dbesc($datarray['edited']), dbesc($datarray['commented']), dbesc($datarray['received']), dbesc($datarray['changed']), dbesc($datarray['uri']), dbesc($datarray['thr-parent']), dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['app']), dbesc($datarray['location']), dbesc($datarray['coord']), dbesc($datarray['tag']), dbesc($datarray['inform']), dbesc($datarray['verb']), dbesc($datarray['postopts']), dbesc($datarray['allow_cid']), dbesc($datarray['allow_gid']), dbesc($datarray['deny_cid']), dbesc($datarray['deny_gid']), intval($datarray['private']), intval($datarray['pubmail']), dbesc($datarray['attach']), intval($datarray['bookmark']), intval($datarray['origin'])); $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($datarray['uri'])); if (count($r)) { $post_id = $r[0]['id']; logger('mod_item: saved item ' . $post_id); if ($parent) { // This item is the last leaf and gets the comment box, clear any ancestors $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent` = %d ", dbesc(datetime_convert()), intval($parent)); // Inherit ACL's from the parent item. $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `private` = %d\n\t\t\t\tWHERE `id` = %d LIMIT 1", dbesc($parent_item['allow_cid']), dbesc($parent_item['allow_gid']), dbesc($parent_item['deny_cid']), dbesc($parent_item['deny_gid']), intval($parent_item['private']), intval($post_id)); if ($contact_record != $author) { notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id, 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item')); } // We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key if ($self) { require_once 'include/bb2diaspora.php'; $signed_body = html_entity_decode(bb2diaspora($datarray['body'])); $myaddr = $a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3); if ($datarray['verb'] === ACTIVITY_LIKE) { $signed_text = $datarray['guid'] . ';' . 'Post' . ';' . $parent_item['guid'] . ';' . 'true' . ';' . $myaddr; } else { $signed_text = $datarray['guid'] . ';' . $parent_item['guid'] . ';' . $signed_body . ';' . $myaddr; } $authorsig = base64_encode(rsa_sign($signed_text, $a->user['prvkey'], 'sha256')); q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($post_id), dbesc($signed_text), dbesc(base64_encode($authorsig)), dbesc($myaddr)); } } else { $parent = $post_id; if ($contact_record != $author) { notification(array('type' => NOTIFY_WALL, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id, 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item')); } } // fallback so that parent always gets set to non-zero. if (!$parent) { $parent = $post_id; } $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s', `plink` = '%s', `changed` = '%s', `last-child` = 1, `visible` = 1\n\t\t\tWHERE `id` = %d LIMIT 1", intval($parent), dbesc($parent == $post_id ? $uri : $parent_item['uri']), dbesc($a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id), dbesc(datetime_convert()), intval($post_id)); // photo comments turn the corresponding item visible to the profile wall // This way we don't see every picture in your new photo album posted to your wall at once. // They will show up as people comment on them. if (!$parent_item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d LIMIT 1", intval($parent_item['id'])); } } else { logger('mod_item: unable to retrieve post that was just stored.'); notify(t('System error. Post not saved.')); goaway($a->get_baseurl() . "/" . $return_path); // NOTREACHED } // update the commented timestamp on the parent q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($parent)); $datarray['id'] = $post_id; $datarray['plink'] = $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id; call_hooks('post_local_end', $datarray); if (strlen($emailcc) && $profile_uid == local_user()) { $erecips = explode(',', $emailcc); if (count($erecips)) { foreach ($erecips as $recip) { $addr = trim($recip); if (!strlen($addr)) { continue; } $disclaimer = '<hr />' . sprintf(t('This message was sent to you by %s, a member of the Friendica social network.'), $a->user['username']) . '<br />'; $disclaimer .= sprintf(t('You may visit them online at %s'), $a->get_baseurl() . '/profile/' . $a->user['nickname']) . EOL; $disclaimer .= t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL; $subject = '[Friendica]' . ' ' . sprintf(t('%s posted an update.'), $a->user['username']); $headers = 'From: ' . $a->user['username'] . ' <' . $a->user['email'] . '>' . "\n"; $headers .= 'MIME-Version: 1.0' . "\n"; $headers .= 'Content-Type: text/html; charset=UTF-8' . "\n"; $headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; $link = '<a href="' . $a->get_baseurl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />'; $html = prepare_body($datarray); $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>'; @mail($addr, $subject, $message, $headers); } } } // This is a real juggling act on shared hosting services which kill your processes // e.g. dreamhost. We used to start delivery to our native delivery agents in the background // and then run our plugin delivery from the foreground. We're now doing plugin delivery first, // because as soon as you start loading up a bunch of remote delivey processes, *this* page is // likely to get killed off. If you end up looking at an /item URL and a blank page, // it's very likely the delivery got killed before all your friends could be notified. // Currently the only realistic fixes are to use a reliable server - which precludes shared hosting, // or cut back on plugins which do remote deliveries. proc_run('php', "include/notifier.php", $notify_type, "{$post_id}"); logger('post_complete'); // figure out how to return, depending on from whence we came if ($api_source) { return; } if ($return_path) { goaway($a->get_baseurl() . "/" . $return_path); } $json = array('success' => 1); if (x($_POST, 'jsreload') && strlen($_POST['jsreload'])) { $json['reload'] = $a->get_baseurl() . '/' . $_POST['jsreload']; } logger('post_json: ' . print_r($json, true), LOGGER_DEBUG); echo json_encode($json); killme(); // NOTREACHED }
function photos_post(&$a) { logger('mod-photos: photos_post: begin', LOGGER_DEBUG); logger('mod_photos: REQUEST ' . print_r($_REQUEST, true), LOGGER_DATA); logger('mod_photos: FILES ' . print_r($_FILES, true), LOGGER_DATA); $can_post = false; $visitor = 0; $page_owner_uid = $a->data['user']['uid']; $community_page = $a->data['user']['page-flags'] == PAGE_COMMUNITY ? true : false; if (local_user() && local_user() == $page_owner_uid) { $can_post = true; } else { if ($community_page && remote_user()) { $r = q("SELECT `uid` FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `id` = %d AND `uid` = %d LIMIT 1", intval(remote_user()), intval($page_owner_uid)); if (count($r)) { $can_post = true; $visitor = remote_user(); } } } if (!$can_post) { notice(t('Permission denied.') . EOL); killme(); } $r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid` \n\t\tWHERE `user`.`uid` = %d AND `self` = 1 LIMIT 1", intval($page_owner_uid)); if (!count($r)) { notice(t('Contact information unavailable') . EOL); logger('photos_post: unable to locate contact record for page owner. uid=' . $page_owner_uid); killme(); } $owner_record = $r[0]; if ($a->argc > 3 && $a->argv[2] === 'album') { $album = hex2bin($a->argv[3]); if ($album === t('Profile Photos') || $album === 'Contact Photos' || $album === t('Contact Photos')) { goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } $r = q("SELECT count(*) FROM `photo` WHERE `album` = '%s' AND `uid` = %d", dbesc($album), intval($page_owner_uid)); if (!count($r)) { notice(t('Album not found.') . EOL); goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } $newalbum = notags(trim($_POST['albumname'])); if ($newalbum != $album) { q("UPDATE `photo` SET `album` = '%s' WHERE `album` = '%s' AND `uid` = %d", dbesc($newalbum), dbesc($album), intval($page_owner_uid)); $newurl = str_replace(bin2hex($album), bin2hex($newalbum), $_SESSION['photo_return']); goaway($a->get_baseurl() . '/' . $newurl); return; // NOTREACHED } if ($_POST['dropalbum'] == t('Delete Album')) { $res = array(); // get the list of photos we are about to delete if ($visitor) { $r = q("SELECT distinct(`resource-id`) as `rid` FROM `photo` WHERE `contact-id` = %d AND `uid` = %d AND `album` = '%s'", intval($visitor), intval($page_owner_uid), dbesc($album)); } else { $r = q("SELECT distinct(`resource-id`) as `rid` FROM `photo` WHERE `uid` = %d AND `album` = '%s'", intval(local_user()), dbesc($album)); } if (count($r)) { foreach ($r as $rr) { $res[] = "'" . dbesc($rr['rid']) . "'"; } } else { goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } $str_res = implode(',', $res); // remove the associated photos q("DELETE FROM `photo` WHERE `resource-id` IN ( {$str_res} ) AND `uid` = %d", intval($page_owner_uid)); // find and delete the corresponding item with all the comments and likes/dislikes $r = q("SELECT `parent-uri` FROM `item` WHERE `resource-id` IN ( {$str_res} ) AND `uid` = %d", intval($page_owner_uid)); if (count($r)) { foreach ($r as $rr) { q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", dbesc(datetime_convert()), dbesc($rr['parent-uri']), intval($page_owner_uid)); $drop_id = intval($rr['id']); // send the notification upstream/downstream as the case may be if ($rr['visible']) { proc_run('php', "include/notifier.php", "drop", "{$drop_id}"); } } } } goaway($a->get_baseurl() . '/photos/' . $a->data['user']['nickname']); return; // NOTREACHED } if ($a->argc > 2 && x($_POST, 'delete') && $_POST['delete'] == t('Delete Photo')) { // same as above but remove single photo if ($visitor) { $r = q("SELECT `id`, `resource-id` FROM `photo` WHERE `contact-id` = %d AND `uid` = %d AND `resource-id` = '%s' LIMIT 1", intval($visitor), intval($page_owner_uid), dbesc($a->argv[2])); } else { $r = q("SELECT `id`, `resource-id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' LIMIT 1", intval(local_user()), dbesc($a->argv[2])); } if (count($r)) { q("DELETE FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'", intval($page_owner_uid), dbesc($r[0]['resource-id'])); $i = q("SELECT * FROM `item` WHERE `resource-id` = '%s' AND `uid` = %d LIMIT 1", dbesc($r[0]['resource-id']), intval($page_owner_uid)); if (count($i)) { q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($i[0]['uri']), intval($page_owner_uid)); $url = $a->get_baseurl(); $drop_id = intval($i[0]['id']); if ($i[0]['visible']) { proc_run('php', "include/notifier.php", "drop", "{$drop_id}"); } } } goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } if ($a->argc > 2 && (x($_POST, 'desc') !== false || x($_POST, 'newtag') !== false) || x($_POST, 'albname') !== false) { $desc = x($_POST, 'desc') ? notags(trim($_POST['desc'])) : ''; $rawtags = x($_POST, 'newtag') ? notags(trim($_POST['newtag'])) : ''; $item_id = x($_POST, 'item_id') ? intval($_POST['item_id']) : 0; $albname = x($_POST, 'albname') ? notags(trim($_POST['albname'])) : ''; $str_group_allow = perms2str($_POST['group_allow']); $str_contact_allow = perms2str($_POST['contact_allow']); $str_group_deny = perms2str($_POST['group_deny']); $str_contact_deny = perms2str($_POST['contact_deny']); $resource_id = $a->argv[2]; if (!strlen($albname)) { $albname = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y'); } if (x($_POST, 'rotate') !== false && intval($_POST['rotate']) == 1) { logger('rotate'); $r = q("select * from photo where `resource-id` = '%s' and uid = %d and scale = 0 limit 1", dbesc($resource_id), intval($page_owner_uid)); if (count($r)) { $ph = new Photo($r[0]['data']); if ($ph->is_valid()) { $ph->rotate(270); $width = $ph->getWidth(); $height = $ph->getHeight(); $x = q("update photo set data = '%s', height = %d, width = %d where `resource-id` = '%s' and uid = %d and scale = 0 limit 1", dbesc($ph->imageString()), intval($height), intval($width), dbesc($resource_id), intval($page_owner_uid)); if ($width > 640 || $height > 640) { $ph->scaleImage(640); $width = $ph->getWidth(); $height = $ph->getHeight(); $x = q("update photo set data = '%s', height = %d, width = %d where `resource-id` = '%s' and uid = %d and scale = 1 limit 1", dbesc($ph->imageString()), intval($height), intval($width), dbesc($resource_id), intval($page_owner_uid)); } if ($width > 320 || $height > 320) { $ph->scaleImage(320); $width = $ph->getWidth(); $height = $ph->getHeight(); $x = q("update photo set data = '%s', height = %d, width = %d where `resource-id` = '%s' and uid = %d and scale = 2 limit 1", dbesc($ph->imageString()), intval($height), intval($width), dbesc($resource_id), intval($page_owner_uid)); } } } } $p = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d ORDER BY `scale` DESC", dbesc($resource_id), intval($page_owner_uid)); if (count($p)) { $r = q("UPDATE `photo` SET `desc` = '%s', `album` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource-id` = '%s' AND `uid` = %d", dbesc($desc), dbesc($albname), dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), dbesc($resource_id), intval($page_owner_uid)); } /* Don't make the item visible if the only change was the album name */ $visibility = 0; if ($p[0]['desc'] !== $desc || strlen($rawtags)) { $visibility = 1; } if (!$item_id) { // Create item container $title = ''; $uri = item_new_uri($a->get_hostname(), $page_owner_uid); $arr = array(); $arr['uid'] = $page_owner_uid; $arr['uri'] = $uri; $arr['parent-uri'] = $uri; $arr['type'] = 'photo'; $arr['wall'] = 1; $arr['resource-id'] = $p[0]['resource-id']; $arr['contact-id'] = $owner_record['id']; $arr['owner-name'] = $owner_record['name']; $arr['owner-link'] = $owner_record['url']; $arr['owner-avatar'] = $owner_record['thumb']; $arr['author-name'] = $owner_record['name']; $arr['author-link'] = $owner_record['url']; $arr['author-avatar'] = $owner_record['thumb']; $arr['title'] = $title; $arr['allow_cid'] = $p[0]['allow_cid']; $arr['allow_gid'] = $p[0]['allow_gid']; $arr['deny_cid'] = $p[0]['deny_cid']; $arr['deny_gid'] = $p[0]['deny_gid']; $arr['last-child'] = 1; $arr['visible'] = $visibility; $arr['origin'] = 1; $arr['body'] = '[url=' . $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . '[img]' . $a->get_baseurl() . '/photo/' . $p[0]['resource-id'] . '-' . $p[0]['scale'] . '.jpg' . '[/img]' . '[/url]'; $item_id = item_store($arr); } if ($item_id) { $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item_id), intval($page_owner_uid)); } if (count($r)) { $old_tag = $r[0]['tag']; $old_inform = $r[0]['inform']; } if (strlen($rawtags)) { $str_tags = ''; $inform = ''; // if the new tag doesn't have a namespace specifier (@foo or #foo) give it a hashtag $x = substr($rawtags, 0, 1); if ($x !== '@' && $x !== '#') { $rawtags = '#' . $rawtags; } $taginfo = array(); $tags = get_tags($rawtags); if (count($tags)) { foreach ($tags as $tag) { if (isset($profile)) { unset($profile); } if (strpos($tag, '@') === 0) { $name = substr($tag, 1); if (strpos($name, '@') || strpos($name, 'http://')) { $newname = $name; $links = @lrdd($name); if (count($links)) { foreach ($links as $link) { if ($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') { $profile = $link['@attributes']['href']; } if ($link['@attributes']['rel'] === 'salmon') { $salmon = '$url:' . str_replace(',', '%sc', $link['@attributes']['href']); if (strlen($inform)) { $inform .= ','; } $inform .= $salmon; } } } $taginfo[] = array($newname, $profile, $salmon); } else { $newname = $name; $alias = ''; $tagcid = 0; if (strrpos($newname, '+')) { $tagcid = intval(substr($newname, strrpos($newname, '+') + 1)); } if ($tagcid) { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($tagcid), intval($profile_uid)); } elseif (strstr($name, '_') || strstr($name, ' ')) { $newname = str_replace('_', ' ', $name); $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1", dbesc($newname), intval($page_owner_uid)); } else { $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1", dbesc($name), dbesc($name), intval($page_owner_uid)); } if (count($r)) { $newname = $r[0]['name']; $profile = $r[0]['url']; $notify = 'cid:' . $r[0]['id']; if (strlen($inform)) { $inform .= ','; } $inform .= $notify; } } if ($profile) { if (substr($notify, 0, 4) === 'cid:') { $taginfo[] = array($newname, $profile, $notify, $r[0], '@[url=' . str_replace(',', '%2c', $profile) . ']' . $newname . '[/url]'); } else { $taginfo[] = array($newname, $profile, $notify, null, $str_tags .= '@[url=' . $profile . ']' . $newname . '[/url]'); } if (strlen($str_tags)) { $str_tags .= ','; } $profile = str_replace(',', '%2c', $profile); $str_tags .= '@[url=' . $profile . ']' . $newname . '[/url]'; } } } } $newtag = $old_tag; if (strlen($newtag) && strlen($str_tags)) { $newtag .= ','; } $newtag .= $str_tags; $newinform = $old_inform; if (strlen($newinform) && strlen($inform)) { $newinform .= ','; } $newinform .= $inform; $r = q("UPDATE `item` SET `tag` = '%s', `inform` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($newtag), dbesc($newinform), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($item_id), intval($page_owner_uid)); $best = 0; foreach ($p as $scales) { if (intval($scales['scale']) == 2) { $best = 2; break; } if (intval($scales['scale']) == 4) { $best = 4; break; } } if (count($taginfo)) { foreach ($taginfo as $tagged) { $uri = item_new_uri($a->get_hostname(), $page_owner_uid); $arr = array(); $arr['uid'] = $page_owner_uid; $arr['uri'] = $uri; $arr['parent-uri'] = $uri; $arr['type'] = 'activity'; $arr['wall'] = 1; $arr['contact-id'] = $owner_record['id']; $arr['owner-name'] = $owner_record['name']; $arr['owner-link'] = $owner_record['url']; $arr['owner-avatar'] = $owner_record['thumb']; $arr['author-name'] = $owner_record['name']; $arr['author-link'] = $owner_record['url']; $arr['author-avatar'] = $owner_record['thumb']; $arr['title'] = ''; $arr['allow_cid'] = $p[0]['allow_cid']; $arr['allow_gid'] = $p[0]['allow_gid']; $arr['deny_cid'] = $p[0]['deny_cid']; $arr['deny_gid'] = $p[0]['deny_gid']; $arr['last-child'] = 1; $arr['visible'] = 1; $arr['verb'] = ACTIVITY_TAG; $arr['object-type'] = ACTIVITY_OBJ_PERSON; $arr['target-type'] = ACTIVITY_OBJ_PHOTO; $arr['tag'] = $tagged[4]; $arr['inform'] = $tagged[2]; $arr['origin'] = 1; $arr['body'] = '[url=' . $tagged[1] . ']' . $tagged[0] . '[/url]' . ' ' . t('was tagged in a') . ' ' . '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . t('photo') . '[/url]' . ' ' . t('by') . ' ' . '[url=' . $owner_record['url'] . ']' . $owner_record['name'] . '[/url]'; $arr['body'] .= "\n\n" . '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . '[img]' . $a->get_baseurl() . "/photo/" . $p[0]['resource-id'] . '-' . $best . '.jpg' . '[/img][/url]' . "\n"; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $tagged[0] . '</title><id>' . $tagged[1] . '/' . $tagged[0] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $tagged[1] . '" />' . "\n"); if ($tagged[3]) { $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $tagged[3]['photo'] . '" />' . "\n"); } $arr['object'] .= '</link></object>' . "\n"; $arr['target'] = '<target><type>' . ACTIVITY_OBJ_PHOTO . '</type><title>' . $p[0]['desc'] . '</title><id>' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . '</id>'; $arr['target'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . '" />' . "\n" . '<link rel="preview" type="image/jpeg" href="' . $a->get_baseurl() . "/photo/" . $p[0]['resource-id'] . '-' . $best . '.jpg' . '" />') . '</link></target>'; $item_id = item_store($arr); if ($item_id) { q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc($a->get_baseurl() . '/display/' . $owner_record['nickname'] . '/' . $item_id), intval($page_owner_uid), intval($item_id)); proc_run('php', "include/notifier.php", "tag", "{$item_id}"); } } } } goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } /** * default post action - upload a photo */ call_hooks('photo_post_init', $_POST); /** * Determine the album to use */ $album = notags(trim($_REQUEST['album'])); $newalbum = notags(trim($_REQUEST['newalbum'])); logger('mod/photos.php: photos_post(): album= ' . $album . ' newalbum= ' . $newalbum, LOGGER_DEBUG); if (!strlen($album)) { if (strlen($newalbum)) { $album = $newalbum; } else { $album = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y'); } } /** * * We create a wall item for every photo, but we don't want to * overwhelm the data stream with a hundred newly uploaded photos. * So we will make the first photo uploaded to this album in the last several hours * visible by default, the rest will become visible over time when and if * they acquire comments, likes, dislikes, and/or tags * */ $r = q("SELECT * FROM `photo` WHERE `album` = '%s' AND `uid` = %d AND `created` > UTC_TIMESTAMP() - INTERVAL 3 HOUR ", dbesc($album), intval($page_owner_uid)); if (!count($r) || $album == t('Profile Photos')) { $visible = 1; } else { $visible = 0; } if (intval($_REQUEST['not_visible']) || $_REQUEST['not_visible'] === 'true') { $visible = 0; } $str_group_allow = perms2str(is_array($_REQUEST['group_allow']) ? $_REQUEST['group_allow'] : explode(',', $_REQUEST['group_allow'])); $str_contact_allow = perms2str(is_array($_REQUEST['contact_allow']) ? $_REQUEST['contact_allow'] : explode(',', $_REQUEST['contact_allow'])); $str_group_deny = perms2str(is_array($_REQUEST['group_deny']) ? $_REQUEST['group_deny'] : explode(',', $_REQUEST['group_deny'])); $str_contact_deny = perms2str(is_array($_REQUEST['contact_deny']) ? $_REQUEST['contact_deny'] : explode(',', $_REQUEST['contact_deny'])); $ret = array('src' => '', 'filename' => '', 'filesize' => 0); call_hooks('photo_post_file', $ret); if (x($ret, 'src') && x($ret, 'filesize')) { $src = $ret['src']; $filename = $ret['filename']; $filesize = $ret['filesize']; } else { $src = $_FILES['userfile']['tmp_name']; $filename = basename($_FILES['userfile']['name']); $filesize = intval($_FILES['userfile']['size']); } logger('photos: upload: received file: ' . $filename . ' as ' . $src . ' ' . $filesize . ' bytes', LOGGER_DEBUG); $maximagesize = get_config('system', 'maximagesize'); if ($maximagesize && $filesize > $maximagesize) { notice(t('Image exceeds size limit of ') . $maximagesize . EOL); @unlink($src); $foo = 0; call_hooks('photo_post_end', $foo); return; } if (!$filesize) { notice(t('Image file is empty.') . EOL); @unlink($src); $foo = 0; call_hooks('photo_post_end', $foo); return; } logger('mod/photos.php: photos_post(): loading the contents of ' . $src, LOGGER_DEBUG); $imagedata = @file_get_contents($src); $ph = new Photo($imagedata); if (!$ph->is_valid()) { logger('mod/photos.php: photos_post(): unable to process image', LOGGER_DEBUG); notice(t('Unable to process image.') . EOL); @unlink($src); $foo = 0; call_hooks('photo_post_end', $foo); killme(); } @unlink($src); $width = $ph->getWidth(); $height = $ph->getHeight(); $smallest = 0; $photo_hash = photo_new_resource(); $r = $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 0, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); if (!$r) { logger('mod/photos.php: photos_post(): image store failed', LOGGER_DEBUG); notice(t('Image upload failed.') . EOL); killme(); } if ($width > 640 || $height > 640) { $ph->scaleImage(640); $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 1, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); $smallest = 1; } if ($width > 320 || $height > 320) { $ph->scaleImage(320); $ph->store($page_owner_uid, $visitor, $photo_hash, $filename, $album, 2, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); $smallest = 2; } $basename = basename($filename); $uri = item_new_uri($a->get_hostname(), $page_owner_uid); // Create item container $arr = array(); $arr['uid'] = $page_owner_uid; $arr['uri'] = $uri; $arr['parent-uri'] = $uri; $arr['type'] = 'photo'; $arr['wall'] = 1; $arr['resource-id'] = $photo_hash; $arr['contact-id'] = $owner_record['id']; $arr['owner-name'] = $owner_record['name']; $arr['owner-link'] = $owner_record['url']; $arr['owner-avatar'] = $owner_record['thumb']; $arr['author-name'] = $owner_record['name']; $arr['author-link'] = $owner_record['url']; $arr['author-avatar'] = $owner_record['thumb']; $arr['title'] = ''; $arr['allow_cid'] = $str_contact_allow; $arr['allow_gid'] = $str_group_allow; $arr['deny_cid'] = $str_contact_deny; $arr['deny_gid'] = $str_group_deny; $arr['last-child'] = 1; $arr['visible'] = $visible; $arr['origin'] = 1; $arr['body'] = '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $photo_hash . ']' . '[img]' . $a->get_baseurl() . "/photo/{$photo_hash}-{$smallest}.jpg" . '[/img]' . '[/url]'; $item_id = item_store($arr); if ($item_id) { q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc($a->get_baseurl() . '/display/' . $owner_record['nickname'] . '/' . $item_id), intval($page_owner_uid), intval($item_id)); } if ($visible) { proc_run('php', "include/notifier.php", 'wall-new', $item_id); } call_hooks('photo_post_end', intval($item_id)); // addon uploaders should call "killme()" [e.g. exit] within the photo_post_end hook // if they do not wish to be redirected goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); // NOTREACHED }
function photos_post(&$a) { if (!local_user()) { notice(t('Permission denied.') . EOL); killme(); } $r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = 1 WHERE `self` = 1 LIMIT 1"); $contact_record = $r[0]; if ($a->argc > 2 && $a->argv[1] == 'album') { $album = hex2bin($a->argv[2]); if ($album == t('Profile Photos') || $album == t('Contact Photos')) { goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } $r = q("SELECT count(*) FROM `photo` WHERE `album` = '%s' ", dbesc($album)); if (!count($r)) { notice(t('Album not found.') . EOL); goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } $newalbum = notags(trim($_POST['albumname'])); if ($newalbum != $album) { q("UPDATE `photo` SET `album` = '%s' WHERE `album` = '%s' ", dbesc($newalbum), dbesc($album)); $newurl = str_replace(bin2hex($album), bin2hex($newalbum), $_SESSION['photo_return']); goaway($a->get_baseurl() . '/' . $newurl); return; // NOTREACHED } if ($_POST['dropalbum'] == t('Delete Album')) { $res = array(); $r = q("SELECT distinct(`resource-id`) as `rid` FROM `photo` WHERE `album` = '%s'", dbesc($album)); if (count($r)) { foreach ($r as $rr) { $res[] = "'" . dbesc($rr['rid']) . "'"; } } else { goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } $str_res = implode(',', $res); q("DELETE FROM `photo` WHERE `resource-id` IN ( {$str_res} ) "); $r = q("SELECT `parent-uri` FROM `item` WHERE `resource-id` IN ( {$str_res} ) "); if (count($r)) { foreach ($r as $rr) { q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `parent-uri` = '%s' ", dbesc(datetime_convert()), dbesc($rr['parent-uri'])); $drop_id = intval($rr['id']); $php_path = strlen($a->config['php_path']) ? $a->config['php_path'] : 'php'; // send the notification upstream/downstream as the case may be if ($rr['visible']) { proc_close(proc_open("\"{$php_path}\" \"include/notifier.php\" \"drop\" \"{$drop_id}\" & ", array(), $foo)); } } } } goaway($a->get_baseurl() . '/photos/' . $a->data['user']['nickname']); return; // NOTREACHED } if ($a->argc > 1 && x($_POST, 'delete') && $_POST['delete'] == t('Delete Photo')) { $r = q("SELECT `id` FROM `photo` WHERE `resource-id` = '%s' LIMIT 1", dbesc($a->argv[1])); if (count($r)) { q("DELETE FROM `photo` WHERE `resource-id` = '%s'", dbesc($r[0]['resource-id'])); $i = q("SELECT * FROM `item` WHERE `resource-id` = '%s' LIMIT 1", dbesc($r[0]['resource-id'])); if (count($i)) { q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' ", dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($i[0]['uri'])); $drop_id = intval($i[0]['id']); $php_path = strlen($a->config['php_path']) ? $a->config['php_path'] : 'php'; // send the notification upstream/downstream as the case may be if ($i[0]['visible']) { proc_close(proc_open("\"{$php_path}\" \"include/notifier.php\" \"drop\" \"{$drop_id}\" & ", array(), $foo)); } } } goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } if ($a->argc > 1 && x($_POST, 'desc') !== false) { $desc = notags(trim($_POST['desc'])); $tags = notags(trim($_POST['tags'])); $item_id = intval($_POST['item_id']); $resource_id = $a->argv[1]; $p = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' ORDER BY `scale` DESC", dbesc($resource_id)); if (count($r)) { $r = q("UPDATE `photo` SET `desc` = '%s' WHERE `resource-id` = '%s' ", dbesc($desc), dbesc($resource_id)); } if (!$item_id) { $title = ''; $basename = basename($filename); // Create item container $body = '[url=' . $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . '[img]' . $a->get_baseurl() . '/photo/' . $p[0]['resource-id'] . '-' . $p[0]['scale'] . '.jpg' . '[/img]' . '[/url]'; $uri = item_new_uri($a->get_hostname(), get_uid()); $r = q("INSERT INTO `item` (`type`, `wall`, `resource-id`, `contact-id`,\n\t\t\t\t`owner-name`,`owner-link`,`owner-avatar`, `created`,\n\t\t\t\t`edited`, `changed`, `uri`, `parent-uri`, `title`, `body`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`)\n\t\t\t\tVALUES( '%s', %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )", dbesc('photo'), intval(1), dbesc($p[0]['resource-id']), intval($contact_record['id']), dbesc($contact_record['name']), dbesc($contact_record['url']), dbesc($contact_record['thumb']), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($uri), dbesc($uri), dbesc($title), dbesc($body), dbesc($p[0]['allow_cid']), dbesc($p[0]['allow_gid']), dbesc($p[0]['deny_cid']), dbesc($p[0]['deny_gid'])); if ($r) { $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($uri)); if (count($r)) { $item_id = $r[0]['id']; } q("UPDATE `item` SET `parent` = %d, `last-child` = 1 WHERE `id` = %d LIMIT 1", intval($r[0]['id']), intval($r[0]['id'])); } } $r = q("UPDATE `item` SET `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc($tags), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($item_id)); goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } if (!x($_FILES, 'userfile')) { killme(); } if ($_POST['partitionCount']) { $java_upload = true; } else { $java_upload = false; } $album = notags(trim($_POST['album'])); $newalbum = notags(trim($_POST['newalbum'])); if (!strlen($album)) { if (strlen($newalbum)) { $album = $newalbum; } else { $album = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y'); } } $r = q("SELECT * FROM `photo` WHERE `album` = '%s' ", dbesc($album)); if (!count($r) || $album == t('Profile Photos')) { $visible = 1; } else { $visibile = 0; } $str_group_allow = perms2str($_POST['group_allow']); $str_contact_allow = perms2str($_POST['contact_allow']); $str_group_deny = perms2str($_POST['group_deny']); $str_contact_deny = perms2str($_POST['contact_deny']); $src = $_FILES['userfile']['tmp_name']; $filename = basename($_FILES['userfile']['name']); $filesize = intval($_FILES['userfile']['size']); $imagedata = @file_get_contents($src); $ph = new Photo($imagedata); if (!($image = $ph->getImage())) { notice(t('Unable to process image.') . EOL); @unlink($src); killme(); } @unlink($src); $width = $ph->getWidth(); $height = $ph->getHeight(); $smallest = 0; $photo_hash = hash('md5', uniqid(mt_rand(), true)); $r = $ph->store(0, $photo_hash, $filename, $album, 0, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); if (!$r) { notice(t('Image upload failed.') . EOL); killme(); } if ($width > 640 || $height > 640) { $ph->scaleImage(640); $ph->store(0, $photo_hash, $filename, $album, 1, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); $smallest = 1; } if ($width > 320 || $height > 320) { $ph->scaleImage(320); $ph->store(0, $photo_hash, $filename, $album, 2, 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); $smallest = 2; } $basename = basename($filename); // Create item container $body = '[url=' . $a->get_baseurl() . '/photos/' . $contact_record['nickname'] . '/image/' . $photo_hash . ']' . '[img]' . $a->get_baseurl() . "/photo/{$photo_hash}-{$smallest}.jpg" . '[/img]' . '[/url]'; $uri = item_new_uri($a->get_hostname(), get_uid()); $r = q("INSERT INTO `item` (`type`, `wall`, `resource-id`, `contact-id`,`owner-name`,`owner-link`,`owner-avatar`, `created`,\n\t\t`edited`, `changed`, `uri`, `parent-uri`, `title`, `body`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `visible`)\n\t\tVALUES( '%s', %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d )", dbesc('photo'), intval(1), dbesc($photo_hash), intval($contact_record['id']), dbesc($contact_record['name']), dbesc($contact_record['url']), dbesc($contact_record['thumb']), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($uri), dbesc($uri), dbesc($title), dbesc($body), dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), intval($visible)); if ($r) { $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($uri)); if (count($r)) { q("UPDATE `item` SET `parent` = %d, `last-child` = 1 WHERE `id` = %d LIMIT 1", intval($r[0]['id']), intval($r[0]['id'])); } } if (!$java_upload) { goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } killme(); return; // NOTREACHED }
function diaspora_request($importer, $xml) { $a = get_app(); $sender_handle = unxmlify($xml->sender_handle); $recipient_handle = unxmlify($xml->recipient_handle); if (!$sender_handle || !$recipient_handle) { return; } $contact = diaspora_get_contact_by_handle($importer['uid'], $sender_handle); if ($contact) { // perhaps we were already sharing with this person. Now they're sharing with us. // That makes us friends. if ($contact['rel'] == CONTACT_IS_FOLLOWER) { q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1", intval(CONTACT_IS_FRIEND), intval($contact['id']), intval($importer['uid'])); } // send notification $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", intval($importer['uid'])); if (count($r) && $r[0]['hide-friends'] == 0) { require_once 'include/items.php'; $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($importer['uid'])); // they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array if (count($self) && $contact['rel'] == CONTACT_IS_FOLLOWER) { $arr = array(); $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $importer['uid']); $arr['uid'] = $importer['uid']; $arr['contact-id'] = $self[0]['id']; $arr['wall'] = 1; $arr['type'] = 'wall'; $arr['gravity'] = 0; $arr['origin'] = 1; $arr['author-name'] = $arr['owner-name'] = $self[0]['name']; $arr['author-link'] = $arr['owner-link'] = $self[0]['url']; $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb']; $arr['verb'] = ACTIVITY_FRIEND; $arr['object-type'] = ACTIVITY_OBJ_PERSON; $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]'; $B = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $BPhoto = '[url=' . $contact['url'] . ']' . '[img]' . $contact['thumb'] . '[/img][/url]'; $arr['body'] = sprintf(t('%1$s is now friends with %2$s'), $A, $B) . "\n\n\n" . $Bphoto; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact['name'] . '</title>' . '<id>' . $contact['url'] . '/' . $contact['name'] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact['url'] . '" />' . "\n"); $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact['thumb'] . '" />' . "\n"); $arr['object'] .= '</link></object>' . "\n"; $arr['last-child'] = 1; $arr['allow_cid'] = $user[0]['allow_cid']; $arr['allow_gid'] = $user[0]['allow_gid']; $arr['deny_cid'] = $user[0]['deny_cid']; $arr['deny_gid'] = $user[0]['deny_gid']; $i = item_store($arr); if ($i) { proc_run('php', "include/notifier.php", "activity", "{$i}"); } } } return; } $ret = find_diaspora_person_by_handle($sender_handle); if (!count($ret) || $ret['network'] != NETWORK_DIASPORA) { logger('diaspora_request: Cannot resolve diaspora handle ' . $sender_handle . ' for ' . $recipient_handle); return; } $batch = $ret['batch'] ? $ret['batch'] : implode('/', array_slice(explode('/', $ret['url']), 0, 3)) . '/receive/public'; $r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)\n\t\tVALUES ( %d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d) ", intval($importer['uid']), dbesc($ret['network']), dbesc($ret['addr']), datetime_convert(), dbesc($ret['url']), dbesc(normalise_link($ret['url'])), dbesc($batch), dbesc($ret['name']), dbesc($ret['nick']), dbesc($ret['photo']), dbesc($ret['pubkey']), dbesc($ret['notify']), dbesc($ret['poll']), 1, 2); // find the contact record we just created $contact_record = diaspora_get_contact_by_handle($importer['uid'], $sender_handle); $hash = random_string() . (string) time(); // Generate a confirm_key if ($contact_record) { $ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime` )\n\t\t\tVALUES ( %d, %d, %d, %d, '%s', '%s', '%s' )", intval($importer['uid']), intval($contact_record['id']), 0, 0, dbesc(t('Sharing notification from Diaspora network')), dbesc($hash), dbesc(datetime_convert())); } return; }
function mood_init(&$a) { if (!local_user()) { return; } $uid = local_user(); $verb = notags(trim($_GET['verb'])); if (!$verb) { return; } $verbs = get_mood_verbs(); if (!in_array($verb, $verbs)) { return; } $activity = ACTIVITY_MOOD . '#' . urlencode($verb); $parent = x($_GET, 'parent') ? intval($_GET['parent']) : 0; logger('mood: verb ' . $verb, LOGGER_DEBUG); if ($parent) { $r = q("select uri, private, allow_cid, allow_gid, deny_cid, deny_gid\n\t\t\tfrom item where id = %d and parent = %d and uid = %d limit 1", intval($parent), intval($parent), intval($uid)); if (count($r)) { $parent_uri = $r[0]['uri']; $private = $r[0]['private']; $allow_cid = $r[0]['allow_cid']; $allow_gid = $r[0]['allow_gid']; $deny_cid = $r[0]['deny_cid']; $deny_gid = $r[0]['deny_gid']; } } else { $private = 0; $allow_cid = $a->user['allow_cid']; $allow_gid = $a->user['allow_gid']; $deny_cid = $a->user['deny_cid']; $deny_gid = $a->user['deny_gid']; } $poster = $a->contact; $uri = item_new_uri($a->get_hostname(), $uid); $action = sprintf(t('%1$s is currently %2$s'), '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]', $verbs[$verb]); $arr = array(); $arr['uid'] = $uid; $arr['uri'] = $uri; $arr['parent-uri'] = $parent_uri ? $parent_uri : $uri; $arr['type'] = 'activity'; $arr['wall'] = 1; $arr['contact-id'] = $poster['id']; $arr['owner-name'] = $poster['name']; $arr['owner-link'] = $poster['url']; $arr['owner-avatar'] = $poster['thumb']; $arr['author-name'] = $poster['name']; $arr['author-link'] = $poster['url']; $arr['author-avatar'] = $poster['thumb']; $arr['title'] = ''; $arr['allow_cid'] = $allow_cid; $arr['allow_gid'] = $allow_gid; $arr['deny_cid'] = $deny_cid; $arr['deny_gid'] = $deny_gid; $arr['last-child'] = 1; $arr['visible'] = 1; $arr['verb'] = $activity; $arr['private'] = $private; $arr['origin'] = 1; $arr['body'] = $action; $item_id = item_store($arr); if ($item_id) { q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d", dbesc($a->get_baseurl() . '/display/' . $poster['nickname'] . '/' . $item_id), intval($uid), intval($item_id)); proc_run('php', "include/notifier.php", "tag", "{$item_id}"); } call_hooks('post_local_end', $arr); proc_run('php', "include/notifier.php", "like", "{$post_id}"); return; }
/** * @param App $a * @param array $user * @param array $self * @param string $fb_id * @param bool $wall * @param array $orig_post * @param object $likes */ function fb_consume_like(&$a, &$user, &$self, $fb_id, $wall, &$orig_post, &$likes) { $top_item = $orig_post['id']; $uid = IntVal($user[0]['uid']); if (!$orig_post) { return; } // If we posted the like locally, it will be found with our url, not the FB url. $second_url = $likes->id == $fb_id ? $self[0]['url'] : 'http://facebook.com/profile.php?id=' . $likes->id; $r = q("SELECT * FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s'\n \tAND ( `author-link` = '%s' OR `author-link` = '%s' ) LIMIT 1", dbesc($orig_post['uri']), intval($uid), dbesc(ACTIVITY_LIKE), dbesc('http://facebook.com/profile.php?id=' . $likes->id), dbesc($second_url)); if (count($r)) { return; } $likedata = array(); $likedata['parent'] = $top_item; $likedata['verb'] = ACTIVITY_LIKE; $likedata['gravity'] = 3; $likedata['uid'] = $uid; $likedata['wall'] = $wall ? 1 : 0; $likedata['uri'] = item_new_uri($a->get_baseurl(), $uid); $likedata['parent-uri'] = $orig_post['uri']; if ($likes->id == $fb_id) { $likedata['contact-id'] = $self[0]['id']; } else { $r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1", dbesc($likes->id), intval($uid)); if (count($r)) { $likedata['contact-id'] = $r[0]['id']; } } if (!x($likedata, 'contact-id')) { $likedata['contact-id'] = $orig_post['contact-id']; } $likedata['app'] = 'facebook'; $likedata['verb'] = ACTIVITY_LIKE; $likedata['author-name'] = $likes->name; $likedata['author-link'] = 'http://facebook.com/profile.php?id=' . $likes->id; $likedata['author-avatar'] = 'https://graph.facebook.com/' . $likes->id . '/picture'; $author = '[url=' . $likedata['author-link'] . ']' . $likedata['author-name'] . '[/url]'; $objauthor = '[url=' . $orig_post['author-link'] . ']' . $orig_post['author-name'] . '[/url]'; $post_type = t('status'); $plink = '[url=' . $orig_post['plink'] . ']' . $post_type . '[/url]'; $likedata['object-type'] = ACTIVITY_OBJ_NOTE; $likedata['body'] = sprintf(t('%1$s likes %2$s\'s %3$s'), $author, $objauthor, $plink); $likedata['object'] = '<object><type>' . ACTIVITY_OBJ_NOTE . '</type><local>1</local>' . '<id>' . $orig_post['uri'] . '</id><link>' . xmlify('<link rel="alternate" type="text/html" href="' . xmlify($orig_post['plink']) . '" />') . '</link><title>' . $orig_post['title'] . '</title><content>' . $orig_post['body'] . '</content></object>'; item_store($likedata); }
function item_post(&$a) { if (!local_user() && !remote_user()) { return; } require_once 'include/security.php'; $uid = $_SESSION['uid']; $parent = x($_POST, 'parent') ? intval($_POST['parent']) : 0; $parent_item = null; if ($parent) { $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent)); if (!count($r)) { notice(t('Unable to locate original post.') . EOL); goaway($a->get_baseurl() . "/" . $_POST['return']); } $parent_item = $r[0]; } $profile_uid = x($_POST, 'profile_uid') ? intval($_POST['profile_uid']) : 0; if (!can_write_wall($a, $profile_uid)) { notice(t('Permission denied.') . EOL); return; } $user = null; $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($profile_uid)); if (count($r)) { $user = $r[0]; } $str_group_allow = perms2str($_POST['group_allow']); $str_contact_allow = perms2str($_POST['contact_allow']); $str_group_deny = perms2str($_POST['group_deny']); $str_contact_deny = perms2str($_POST['contact_deny']); $title = notags(trim($_POST['title'])); $body = escape_tags(trim($_POST['body'])); $location = notags(trim($_POST['location'])); $verb = notags(trim($_POST['verb'])); if (!strlen($body)) { notice(t('Empty post discarded.') . EOL); goaway($a->get_baseurl() . "/" . $_POST['return']); } // get contact info for poster $author = null; if ($_SESSION['uid'] && $_SESSION['uid'] == $profile_uid) { $r = q("SELECT * FROM `contact` WHERE `self` = 1 LIMIT 1", intval($_SESSION['uid'])); } else { if (x($_SESSION, 'visitor_id') && intval($_SESSION['visitor_id'])) { $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($_SESSION['visitor_id'])); } } if (count($r)) { $author = $r[0]; $contact_id = $author['id']; } // get contact info for owner if ($profile_uid == $_SESSION['uid']) { $contact_record = $author; } else { $r = q("SELECT * FROM `contact` WHERE `self` = 1 LIMIT 1", intval($profile_uid)); if (count($r)) { $contact_record = $r[0]; } } $post_type = notags(trim($_POST['type'])); if ($post_type == 'net-comment') { if ($parent_item !== null) { if ($parent_item['type'] == 'remote') { $post_type = 'remote-comment'; } else { $post_type = 'wall-comment'; } } } $wall = 0; if ($post_type == 'wall' || $post_type == 'wall-comment') { $wall = 1; } if (!strlen($verb)) { $verb = ACTIVITY_POST; } $gravity = $parent ? 6 : 0; $notify_type = $parent ? 'comment-new' : 'wall-new'; $uri = item_new_uri($a->get_hostname(), $profile_uid); $r = q("INSERT INTO `item` (`type`,`wall`,`gravity`,`contact-id`,`owner-name`,`owner-link`,`owner-avatar`, \n\t\t`author-name`, `author-link`, `author-avatar`, `created`,\n\t\t`edited`, `changed`, `uri`, `title`, `body`, `location`, `verb`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`)\n\t\tVALUES( '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )", dbesc($post_type), intval($wall), intval($gravity), intval($contact_id), dbesc($contact_record['name']), dbesc($contact_record['url']), dbesc($contact_record['thumb']), dbesc($author['name']), dbesc($author['url']), dbesc($author['thumb']), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($uri), dbesc($title), dbesc($body), dbesc($location), dbesc($verb), dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny)); $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($uri)); if (count($r)) { $post_id = $r[0]['id']; if ($parent) { // This item is the last leaf and gets the comment box, clear any ancestors $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent` = %d ", dbesc(datetime_convert()), intval($parent)); // Inherit ACL's from the parent item. // TODO merge with subsequent UPDATE operation and save a db write $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\tWHERE `id` = %d LIMIT 1", dbesc($parent_item['allow_cid']), dbesc($parent_item['allow_gid']), dbesc($parent_item['deny_cid']), dbesc($parent_item['deny_gid']), intval($post_id)); if ($user['notify-flags'] & NOTIFY_COMMENT && $contact_record != $author) { require_once 'bbcode.php'; $from = $author['name']; $tpl = file_get_contents('view/cmnt_received_eml.tpl'); $email_tpl = replace_macros($tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $user['username'], '$email' => $user['email'], '$from' => $from, '$body' => strip_tags(bbcode($body)))); $res = mail($user['email'], $from . t(" commented on your item at ") . $a->config['sitename'], $email_tpl, t("From: Administrator@") . $a->get_hostname()); } } else { $parent = $post_id; if ($user['notify-flags'] & NOTIFY_WALL && $contact_record != $author) { require_once 'bbcode.php'; $from = $author['name']; $tpl = file_get_contents('view/wall_received_eml.tpl'); $email_tpl = replace_macros($tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $user['username'], '$email' => $user['email'], '$from' => $from, '$body' => strip_tags(bbcode($body)))); $res = mail($user['email'], $from . t(" posted on your profile wall at ") . $a->config['sitename'], $email_tpl, t("From: Administrator@") . $a->get_hostname()); } } $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s', `changed` = '%s', `last-child` = 1, `visible` = 1\n\t\t\tWHERE `id` = %d LIMIT 1", intval($parent), dbesc($parent == $post_id ? $uri : $parent_item['uri']), dbesc(datetime_convert()), intval($post_id)); // photo comments turn the corresponding item visible to the profile wall if (!$parent_item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d LIMIT 1", intval($parent_item['id'])); } } $php_path = strlen($a->config['php_path']) ? $a->config['php_path'] : 'php'; proc_close(proc_open("\"{$php_path}\" \"include/notifier.php\" \"{$notify_type}\" \"{$post_id}\" &", array(), $foo)); goaway($a->get_baseurl() . "/" . $_POST['return']); return; // NOTREACHED }
function item_post(&$a) { if (!local_user() && !remote_user() && !x($_REQUEST, 'commenter')) { return; } require_once 'include/security.php'; $uid = local_user(); if (x($_REQUEST, 'dropitems')) { $arr_drop = explode(',', $_REQUEST['dropitems']); drop_items($arr_drop); $json = array('success' => 1); echo json_encode($json); killme(); } call_hooks('post_local_start', $_REQUEST); // logger('postinput ' . file_get_contents('php://input')); logger('postvars ' . print_r($_REQUEST, true), LOGGER_DATA); $api_source = x($_REQUEST, 'api_source') && $_REQUEST['api_source'] ? true : false; $message_id = x($_REQUEST, 'message_id') && $api_source ? strip_tags($_REQUEST['message_id']) : ''; $return_path = x($_REQUEST, 'return') ? $_REQUEST['return'] : ''; $preview = x($_REQUEST, 'preview') ? intval($_REQUEST['preview']) : 0; // Check for doubly-submitted posts, and reject duplicates // Note that we have to ignore previews, otherwise nothing will post // after it's been previewed if (!$preview && x($_REQUEST['post_id_random'])) { if (x($_SESSION['post-random']) && $_SESSION['post-random'] == $_REQUEST['post_id_random']) { logger("item post: duplicate post", LOGGER_DEBUG); item_post_return($a->get_baseurl(), $api_source, $return_path); } else { $_SESSION['post-random'] = $_REQUEST['post_id_random']; } } /** * Is this a reply to something? */ $parent = x($_REQUEST, 'parent') ? intval($_REQUEST['parent']) : 0; $parent_uri = x($_REQUEST, 'parent_uri') ? trim($_REQUEST['parent_uri']) : ''; $parent_item = null; $parent_contact = null; $thr_parent = ''; $parid = 0; $r = false; $objecttype = null; if ($parent || $parent_uri) { $objecttype = ACTIVITY_OBJ_COMMENT; if (!x($_REQUEST, 'type')) { $_REQUEST['type'] = 'net-comment'; } if ($parent) { $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent)); } elseif ($parent_uri && local_user()) { // This is coming from an API source, and we are logged in $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_uri), intval(local_user())); } // if this isn't the real parent of the conversation, find it if ($r !== false && count($r)) { $parid = $r[0]['parent']; $parent_uri = $r[0]['uri']; if ($r[0]['id'] != $r[0]['parent']) { $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1", intval($parid)); } } if ($r === false || !count($r)) { notice(t('Unable to locate original post.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } $parent_item = $r[0]; $parent = $r[0]['id']; // multi-level threading - preserve the info but re-parent to our single level threading //if(($parid) && ($parid != $parent)) $thr_parent = $parent_uri; if ($parent_item['contact-id'] && $uid) { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($parent_item['contact-id']), intval($uid)); if (count($r)) { $parent_contact = $r[0]; // If the contact id doesn't fit with the contact, then set the contact to null $thrparent = q("SELECT `author-link`, `network` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($thr_parent)); if (count($thrparent) and $thrparent[0]["network"] === NETWORK_OSTATUS and normalise_link($parent_contact["url"]) != normalise_link($thrparent[0]["author-link"])) { $parent_contact = null; require_once "include/Scrape.php"; $probed_contact = probe_url($thrparent[0]["author-link"]); if ($probed_contact["network"] != NETWORK_FEED) { $parent_contact = $probed_contact; $parent_contact["nurl"] = normalise_link($probed_contact["url"]); $parent_contact["thumb"] = $probed_contact["photo"]; $parent_contact["micro"] = $probed_contact["photo"]; } logger('parent contact: ' . print_r($parent_contact, true), LOGGER_DEBUG); } else { logger('no contact found: ' . print_r($thrparent, true), LOGGER_DEBUG); } } } } if ($parent) { logger('mod_item: item_post parent=' . $parent); } $profile_uid = x($_REQUEST, 'profile_uid') ? intval($_REQUEST['profile_uid']) : 0; $post_id = x($_REQUEST, 'post_id') ? intval($_REQUEST['post_id']) : 0; $app = x($_REQUEST, 'source') ? strip_tags($_REQUEST['source']) : ''; $extid = x($_REQUEST, 'extid') ? strip_tags($_REQUEST['extid']) : ''; $allow_moderated = false; // here is where we are going to check for permission to post a moderated comment. // First check that the parent exists and it is a wall item. if (x($_REQUEST, 'commenter') && (!$parent || !$parent_item['wall'])) { notice(t('Permission denied.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } // Now check that it is a page_type of PAGE_BLOG, and that valid personal details // have been provided, and run any anti-spam plugins // TODO if (!can_write_wall($a, $profile_uid) && !$allow_moderated) { notice(t('Permission denied.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } // is this an edited post? $orig_post = null; if ($post_id) { $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($post_id)); if (!count($i)) { killme(); } $orig_post = $i[0]; } $user = null; $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($profile_uid)); if (count($r)) { $user = $r[0]; } if ($orig_post) { $str_group_allow = $orig_post['allow_gid']; $str_contact_allow = $orig_post['allow_cid']; $str_group_deny = $orig_post['deny_gid']; $str_contact_deny = $orig_post['deny_cid']; $location = $orig_post['location']; $coord = $orig_post['coord']; $verb = $orig_post['verb']; $objecttype = $orig_post['object-type']; $emailcc = $orig_post['emailcc']; $app = $orig_post['app']; $categories = $orig_post['file']; $title = notags(trim($_REQUEST['title'])); $body = escape_tags(trim($_REQUEST['body'])); $private = $orig_post['private']; $pubmail_enable = $orig_post['pubmail']; $network = $orig_post['network']; $guid = $orig_post['guid']; $extid = $orig_post['extid']; } else { // if coming from the API and no privacy settings are set, // use the user default permissions - as they won't have // been supplied via a form. if ($api_source && !array_key_exists('contact_allow', $_REQUEST) && !array_key_exists('group_allow', $_REQUEST) && !array_key_exists('contact_deny', $_REQUEST) && !array_key_exists('group_deny', $_REQUEST)) { $str_group_allow = $user['allow_gid']; $str_contact_allow = $user['allow_cid']; $str_group_deny = $user['deny_gid']; $str_contact_deny = $user['deny_cid']; } else { // use the posted permissions $str_group_allow = perms2str($_REQUEST['group_allow']); $str_contact_allow = perms2str($_REQUEST['contact_allow']); $str_group_deny = perms2str($_REQUEST['group_deny']); $str_contact_deny = perms2str($_REQUEST['contact_deny']); } $title = notags(trim($_REQUEST['title'])); $location = notags(trim($_REQUEST['location'])); $coord = notags(trim($_REQUEST['coord'])); $verb = notags(trim($_REQUEST['verb'])); $emailcc = notags(trim($_REQUEST['emailcc'])); $body = escape_tags(trim($_REQUEST['body'])); $network = notags(trim($_REQUEST['network'])); $guid = get_guid(32); $naked_body = preg_replace('/\\[(.+?)\\]/', '', $body); if (version_compare(PHP_VERSION, '5.3.0', '>=')) { $l = new Text_LanguageDetect(); //$lng = $l->detectConfidence($naked_body); //$postopts = (($lng['language']) ? 'lang=' . $lng['language'] . ';' . $lng['confidence'] : ''); $lng = $l->detect($naked_body, 3); if (sizeof($lng) > 0) { $postopts = ""; foreach ($lng as $language => $score) { if ($postopts == "") { $postopts = "lang="; } else { $postopts .= ":"; } $postopts .= $language . ";" . $score; } } logger('mod_item: detect language' . print_r($lng, true) . $naked_body, LOGGER_DATA); } else { $postopts = ''; } $private = strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) ? 1 : 0; if ($user['hidewall']) { $private = 2; } // If this is a comment, set the permissions from the parent. if ($parent_item) { $private = 0; // for non native networks use the network of the original post as network of the item if ($parent_item['network'] != NETWORK_DIASPORA and $parent_item['network'] != NETWORK_OSTATUS and $network == "") { $network = $parent_item['network']; } if ($parent_item['private'] || strlen($parent_item['allow_cid']) || strlen($parent_item['allow_gid']) || strlen($parent_item['deny_cid']) || strlen($parent_item['deny_gid'])) { $private = $parent_item['private'] ? $parent_item['private'] : 1; } $str_contact_allow = $parent_item['allow_cid']; $str_group_allow = $parent_item['allow_gid']; $str_contact_deny = $parent_item['deny_cid']; $str_group_deny = $parent_item['deny_gid']; } $pubmail_enable = x($_REQUEST, 'pubmail_enable') && intval($_REQUEST['pubmail_enable']) && !$private ? 1 : 0; // if using the API, we won't see pubmail_enable - figure out if it should be set if ($api_source && $profile_uid && $profile_uid == local_user() && !$private) { $mail_disabled = function_exists('imap_open') && !get_config('system', 'imap_disabled') ? 0 : 1; if (!$mail_disabled) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user())); if (count($r) && intval($r[0]['pubmail'])) { $pubmail_enabled = true; } } } if (!strlen($body)) { if ($preview) { killme(); } info(t('Empty post discarded.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } } if (strlen($categories)) { // get the "fileas" tags for this post $filedas = file_tag_file_to_list($categories, 'file'); } // save old and new categories, so we can determine what needs to be deleted from pconfig $categories_old = $categories; $categories = file_tag_list_to_file(trim($_REQUEST['category']), 'category'); $categories_new = $categories; if (strlen($filedas)) { // append the fileas stuff to the new categories list $categories .= file_tag_list_to_file($filedas, 'file'); } // Work around doubled linefeeds in Tinymce 3.5b2 // First figure out if it's a status post that would've been // created using tinymce. Otherwise leave it alone. /* $plaintext = (local_user() ? intval(get_pconfig(local_user(),'system','plaintext')) || !feature_enabled($profile_uid,'richtext') : 0); if((! $parent) && (! $api_source) && (! $plaintext)) { $body = fix_mce_lf($body); }*/ $plaintext = local_user() ? !feature_enabled($profile_uid, 'richtext') : 0; if (!$parent && !$api_source && !$plaintext) { $body = fix_mce_lf($body); } // get contact info for poster $author = null; $self = false; $contact_id = 0; if (local_user() && local_user() == $profile_uid) { $self = true; $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($_SESSION['uid'])); } elseif (remote_user()) { if (is_array($_SESSION['remote'])) { foreach ($_SESSION['remote'] as $v) { if ($v['uid'] == $profile_uid) { $contact_id = $v['cid']; break; } } } if ($contact_id) { $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($contact_id)); } } if (count($r)) { $author = $r[0]; $contact_id = $author['id']; } // get contact info for owner if ($profile_uid == local_user()) { $contact_record = $author; } else { $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($profile_uid)); if (count($r)) { $contact_record = $r[0]; } } $post_type = notags(trim($_REQUEST['type'])); if ($post_type === 'net-comment') { if ($parent_item !== null) { if ($parent_item['wall'] == 1) { $post_type = 'wall-comment'; } else { $post_type = 'remote-comment'; } } } /** * * When a photo was uploaded into the message using the (profile wall) ajax * uploader, The permissions are initially set to disallow anybody but the * owner from seeing it. This is because the permissions may not yet have been * set for the post. If it's private, the photo permissions should be set * appropriately. But we didn't know the final permissions on the post until * now. So now we'll look for links of uploaded messages that are in the * post and set them to the same permissions as the post itself. * */ $match = null; if (!$preview && preg_match_all("/\\[img([\\=0-9x]*?)\\](.*?)\\[\\/img\\]/", $body, $match)) { $images = $match[2]; if (count($images)) { $objecttype = ACTIVITY_OBJ_IMAGE; foreach ($images as $image) { if (!stristr($image, $a->get_baseurl() . '/photo/')) { continue; } $image_uri = substr($image, strrpos($image, '/') + 1); $image_uri = substr($image_uri, 0, strpos($image_uri, '-')); if (!strlen($image_uri)) { continue; } $srch = '<' . intval($contact_id) . '>'; $r = q("SELECT `id` FROM `photo` WHERE `allow_cid` = '%s' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = ''\n\t\t\t\t\tAND `resource-id` = '%s' AND `uid` = %d LIMIT 1", dbesc($srch), dbesc($image_uri), intval($profile_uid)); if (!count($r)) { continue; } $r = q("UPDATE `photo` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\tWHERE `resource-id` = '%s' AND `uid` = %d AND `album` = '%s' ", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), dbesc($image_uri), intval($profile_uid), dbesc(t('Wall Photos'))); } } } /** * Next link in any attachment references we find in the post. */ $match = false; if (!$preview && preg_match_all("/\\[attachment\\](.*?)\\[\\/attachment\\]/", $body, $match)) { $attaches = $match[1]; if (count($attaches)) { foreach ($attaches as $attach) { $r = q("SELECT * FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($attach)); if (count($r)) { $r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\t\tWHERE `uid` = %d AND `id` = %d", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), intval($profile_uid), intval($attach)); } } } } // embedded bookmark in post? set bookmark flag $bookmark = 0; if (preg_match_all("/\\[bookmark\\=([^\\]]*)\\](.*?)\\[\\/bookmark\\]/ism", $body, $match, PREG_SET_ORDER)) { $objecttype = ACTIVITY_OBJ_BOOKMARK; $bookmark = 1; } $body = bb_translate_video($body); /** * Fold multi-line [code] sequences */ $body = preg_replace('/\\[\\/code\\]\\s*\\[code\\]/ism', "\n", $body); $body = scale_external_images($body, false); // Setting the object type if not defined before if (!$objecttype) { $objecttype = ACTIVITY_OBJ_NOTE; // Default value require_once "include/plaintext.php"; $objectdata = get_attached_data($body); if ($post["type"] == "link") { $objecttype = ACTIVITY_OBJ_BOOKMARK; } elseif ($post["type"] == "video") { $objecttype = ACTIVITY_OBJ_VIDEO; } elseif ($post["type"] == "photo") { $objecttype = ACTIVITY_OBJ_IMAGE; } } /** * Look for any tags and linkify them */ $str_tags = ''; $inform = ''; $tags = get_tags($body); /** * add a statusnet style reply tag if the original post was from there * and we are replying, and there isn't one already */ if ($parent_contact && $parent_contact['network'] === NETWORK_OSTATUS && $parent_contact['nick'] && !in_array('@' . $parent_contact['nick'], $tags)) { $body = '@' . $parent_contact['nick'] . ' ' . $body; $tags[] = '@' . $parent_contact['nick']; } $tagged = array(); $private_forum = false; if (count($tags)) { foreach ($tags as $tag) { if (strpos($tag, '#') === 0) { continue; } // If we already tagged 'Robert Johnson', don't try and tag 'Robert'. // Robert Johnson should be first in the $tags array $fullnametagged = false; for ($x = 0; $x < count($tagged); $x++) { if (stristr($tagged[$x], $tag . ' ')) { $fullnametagged = true; break; } } if ($fullnametagged) { continue; } $success = handle_tag($a, $body, $inform, $str_tags, local_user() ? local_user() : $profile_uid, $tag, $network); if ($success['replaced']) { $tagged[] = $tag; } if (is_array($success['contact']) && intval($success['contact']['prv'])) { $private_forum = true; $private_id = $success['contact']['id']; } } } if ($private_forum && !$parent && !$private) { // we tagged a private forum in a top level post and the message was public. // Restrict it. $private = 1; $str_contact_allow = '<' . $private_id . '>'; } $attachments = ''; $match = false; if (preg_match_all('/(\\[attachment\\]([0-9]+)\\[\\/attachment\\])/', $body, $match)) { foreach ($match[2] as $mtch) { $r = q("SELECT `id`,`filename`,`filesize`,`filetype` FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($mtch)); if (count($r)) { if (strlen($attachments)) { $attachments .= ','; } $attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" length="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . ($r[0]['filename'] ? $r[0]['filename'] : '') . '"[/attach]'; } $body = str_replace($match[1], '', $body); } } $wall = 0; if ($post_type === 'wall' || $post_type === 'wall-comment') { $wall = 1; } if (!strlen($verb)) { $verb = ACTIVITY_POST; } if ($network == "") { $network = NETWORK_DFRN; } $gravity = $parent ? 6 : 0; // even if the post arrived via API we are considering that it // originated on this site by default for determining relayability. $origin = x($_REQUEST, 'origin') ? intval($_REQUEST['origin']) : 1; $notify_type = $parent ? 'comment-new' : 'wall-new'; $uri = $message_id ? $message_id : item_new_uri($a->get_hostname(), $profile_uid); // Fallback so that we alway have a thr-parent if (!$thr_parent) { $thr_parent = $uri; } $datarray = array(); $datarray['uid'] = $profile_uid; $datarray['type'] = $post_type; $datarray['wall'] = $wall; $datarray['gravity'] = $gravity; $datarray['network'] = $network; $datarray['contact-id'] = $contact_id; $datarray['owner-name'] = $contact_record['name']; $datarray['owner-link'] = $contact_record['url']; $datarray['owner-avatar'] = $contact_record['thumb']; $datarray['author-name'] = $author['name']; $datarray['author-link'] = $author['url']; $datarray['author-avatar'] = $author['thumb']; $datarray['created'] = datetime_convert(); $datarray['edited'] = datetime_convert(); $datarray['commented'] = datetime_convert(); $datarray['received'] = datetime_convert(); $datarray['changed'] = datetime_convert(); $datarray['extid'] = $extid; $datarray['guid'] = $guid; $datarray['uri'] = $uri; $datarray['title'] = $title; $datarray['body'] = $body; $datarray['app'] = $app; $datarray['location'] = $location; $datarray['coord'] = $coord; $datarray['tag'] = $str_tags; $datarray['file'] = $categories; $datarray['inform'] = $inform; $datarray['verb'] = $verb; $datarray['object-type'] = $objecttype; $datarray['allow_cid'] = $str_contact_allow; $datarray['allow_gid'] = $str_group_allow; $datarray['deny_cid'] = $str_contact_deny; $datarray['deny_gid'] = $str_group_deny; $datarray['private'] = $private; $datarray['pubmail'] = $pubmail_enable; $datarray['attach'] = $attachments; $datarray['bookmark'] = intval($bookmark); $datarray['thr-parent'] = $thr_parent; $datarray['postopts'] = $postopts; $datarray['origin'] = $origin; $datarray['moderated'] = $allow_moderated; /** * These fields are for the convenience of plugins... * 'self' if true indicates the owner is posting on their own wall * If parent is 0 it is a top-level post. */ $datarray['parent'] = $parent; $datarray['self'] = $self; // $datarray['prvnets'] = $user['prvnets']; if ($orig_post) { $datarray['edit'] = true; } // Search for hashtags item_body_set_hashtags($datarray); // preview mode - prepare the body for display and send it via json if ($preview) { require_once 'include/conversation.php'; $o = conversation($a, array(array_merge($contact_record, $datarray)), 'search', false, true); logger('preview: ' . $o); echo json_encode(array('preview' => $o)); killme(); } call_hooks('post_local', $datarray); if (x($datarray, 'cancel')) { logger('mod_item: post cancelled by plugin.'); if ($return_path) { goaway($a->get_baseurl() . "/" . $return_path); } $json = array('cancel' => 1); if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) { $json['reload'] = $a->get_baseurl() . '/' . $_REQUEST['jsreload']; } echo json_encode($json); killme(); } // Fill the cache field put_item_in_cache($datarray); if ($orig_post) { $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `attach` = '%s', `file` = '%s', `rendered-html` = '%s', `rendered-hash` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc($datarray['attach']), dbesc($datarray['file']), dbesc($datarray['rendered-html']), dbesc($datarray['rendered-hash']), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($post_id), intval($profile_uid)); create_tags_from_item($post_id); create_files_from_item($post_id); update_thread($post_id); // update filetags in pconfig file_tag_update_pconfig($uid, $categories_old, $categories_new, 'category'); proc_run('php', "include/notifier.php", 'edit_post', "{$post_id}"); if (x($_REQUEST, 'return') && strlen($return_path)) { logger('return: ' . $return_path); goaway($a->get_baseurl() . "/" . $return_path); } killme(); } else { $post_id = 0; } $r = q("INSERT INTO `item` (`guid`, `extid`, `uid`,`type`,`wall`,`gravity`, `network`, `contact-id`,`owner-name`,`owner-link`,`owner-avatar`, `author-name`, `author-link`, `author-avatar`,\n\t\t`created`, `edited`, `commented`, `received`, `changed`, `uri`, `thr-parent`, `title`, `body`, `app`, `location`, `coord`, `tag`, `inform`, `verb`, `object-type`, `postopts`,\n\t\t`allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `private`, `pubmail`, `attach`, `bookmark`,`origin`, `moderated`, `file`, `rendered-html`, `rendered-hash`)\n\t\tVALUES( '%s', '%s', %d, '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s')", dbesc($datarray['guid']), dbesc($datarray['extid']), intval($datarray['uid']), dbesc($datarray['type']), intval($datarray['wall']), intval($datarray['gravity']), dbesc($datarray['network']), intval($datarray['contact-id']), dbesc($datarray['owner-name']), dbesc($datarray['owner-link']), dbesc($datarray['owner-avatar']), dbesc($datarray['author-name']), dbesc($datarray['author-link']), dbesc($datarray['author-avatar']), dbesc($datarray['created']), dbesc($datarray['edited']), dbesc($datarray['commented']), dbesc($datarray['received']), dbesc($datarray['changed']), dbesc($datarray['uri']), dbesc($datarray['thr-parent']), dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['app']), dbesc($datarray['location']), dbesc($datarray['coord']), dbesc($datarray['tag']), dbesc($datarray['inform']), dbesc($datarray['verb']), dbesc($datarray['object-type']), dbesc($datarray['postopts']), dbesc($datarray['allow_cid']), dbesc($datarray['allow_gid']), dbesc($datarray['deny_cid']), dbesc($datarray['deny_gid']), intval($datarray['private']), intval($datarray['pubmail']), dbesc($datarray['attach']), intval($datarray['bookmark']), intval($datarray['origin']), intval($datarray['moderated']), dbesc($datarray['file']), dbesc($datarray['rendered-html']), dbesc($datarray['rendered-hash'])); $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($datarray['uri'])); if (!count($r)) { logger('mod_item: unable to retrieve post that was just stored.'); notice(t('System error. Post not saved.') . EOL); goaway($a->get_baseurl() . "/" . $return_path); // NOTREACHED } $post_id = $r[0]['id']; logger('mod_item: saved item ' . $post_id); $datarray["id"] = $post_id; $datarray["plink"] = $a->get_baseurl() . '/display/' . urlencode($datarray["guid"]); // update filetags in pconfig file_tag_update_pconfig($uid, $categories_old, $categories_new, 'category'); if ($parent) { // This item is the last leaf and gets the comment box, clear any ancestors $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent` = %d ", dbesc(datetime_convert()), intval($parent)); update_thread($parent, true); // Inherit ACLs from the parent item. $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `private` = %d\n\t\t\tWHERE `id` = %d", dbesc($parent_item['allow_cid']), dbesc($parent_item['allow_gid']), dbesc($parent_item['deny_cid']), dbesc($parent_item['deny_gid']), intval($parent_item['private']), intval($post_id)); if ($contact_record != $author) { notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'uid' => $user['uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode($datarray['guid']), 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, 'parent_uri' => $parent_item['uri'])); } // Store the comment signature information in case we need to relay to Diaspora store_diaspora_comment_sig($datarray, $author, $self ? $a->user['prvkey'] : false, $parent_item, $post_id); } else { $parent = $post_id; if ($contact_record != $author) { notification(array('type' => NOTIFY_WALL, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'uid' => $user['uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode($datarray['guid']), 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item')); } } // fallback so that parent always gets set to non-zero. if (!$parent) { $parent = $post_id; } $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s', `plink` = '%s', `changed` = '%s', `last-child` = 1, `visible` = 1\n\t\tWHERE `id` = %d", intval($parent), dbesc($parent == $post_id ? $uri : $parent_item['uri']), dbesc($a->get_baseurl() . '/display/' . urlencode($datarray['guid'])), dbesc(datetime_convert()), intval($post_id)); // photo comments turn the corresponding item visible to the profile wall // This way we don't see every picture in your new photo album posted to your wall at once. // They will show up as people comment on them. if (!$parent_item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d", intval($parent_item['id'])); update_thread($parent_item['id']); } // update the commented timestamp on the parent q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($parent)); if ($post_id != $parent) { update_thread($parent); } call_hooks('post_local_end', $datarray); if (strlen($emailcc) && $profile_uid == local_user()) { $erecips = explode(',', $emailcc); if (count($erecips)) { foreach ($erecips as $recip) { $addr = trim($recip); if (!strlen($addr)) { continue; } $disclaimer = '<hr />' . sprintf(t('This message was sent to you by %s, a member of the Friendica social network.'), $a->user['username']) . '<br />'; $disclaimer .= sprintf(t('You may visit them online at %s'), $a->get_baseurl() . '/profile/' . $a->user['nickname']) . EOL; $disclaimer .= t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL; if (!$datarray['title'] == '') { $subject = email_header_encode($datarray['title'], 'UTF-8'); } else { $subject = email_header_encode('[Friendica]' . ' ' . sprintf(t('%s posted an update.'), $a->user['username']), 'UTF-8'); } $link = '<a href="' . $a->get_baseurl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />'; $html = prepare_body($datarray); $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>'; include_once 'include/html2plain.php'; $params = array('fromName' => $a->user['username'], 'fromEmail' => $a->user['email'], 'toEmail' => $addr, 'replyTo' => $a->user['email'], 'messageSubject' => $subject, 'htmlVersion' => $message, 'textVersion' => html2plain($html . $disclaimer)); Emailer::send($params); } } } create_tags_from_item($post_id); create_files_from_item($post_id); if ($post_id == $parent) { add_thread($post_id); } // This is a real juggling act on shared hosting services which kill your processes // e.g. dreamhost. We used to start delivery to our native delivery agents in the background // and then run our plugin delivery from the foreground. We're now doing plugin delivery first, // because as soon as you start loading up a bunch of remote delivey processes, *this* page is // likely to get killed off. If you end up looking at an /item URL and a blank page, // it's very likely the delivery got killed before all your friends could be notified. // Currently the only realistic fixes are to use a reliable server - which precludes shared hosting, // or cut back on plugins which do remote deliveries. proc_run('php', "include/notifier.php", $notify_type, "{$post_id}"); logger('post_complete'); item_post_return($a->get_baseurl(), $api_source, $return_path); // NOTREACHED }
function dfrn_confirm_post(&$a, $handsfree = null) { if (is_array($handsfree)) { /** * We were called directly from dfrn_request due to automatic friend acceptance. * Any $_POST parameters we may require are supplied in the $handsfree array. * */ $node = $handsfree['node']; $a->interactive = false; // notice() becomes a no-op since nobody is there to see it } else { if ($a->argc > 1) { $node = $a->argv[1]; } } /** * * Main entry point. Scenario 1. Our user received a friend request notification (perhaps * from another site) and clicked 'Approve'. * $POST['source_url'] is not set. If it is, it indicates Scenario 2. * * We may also have been called directly from dfrn_request ($handsfree != null) due to * this being a page type which supports automatic friend acceptance. That is also Scenario 1 * since we are operating on behalf of our registered user to approve a friendship. * */ if (!x($_POST, 'source_url')) { $uid = is_array($handsfree) ? $handsfree['uid'] : local_user(); if (!$uid) { notice(t('Permission denied.') . EOL); return; } $user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid)); if (!$user) { notice(t('Profile not found.') . EOL); return; } // These data elements may come from either the friend request notification form or $handsfree array. if (is_array($handsfree)) { logger('Confirm in handsfree mode'); $dfrn_id = $handsfree['dfrn_id']; $intro_id = $handsfree['intro_id']; $duplex = $handsfree['duplex']; $hidden = array_key_exists('hidden', $handsfree) ? intval($handsfree['hidden']) : 0; $activity = array_key_exists('activity', $handsfree) ? intval($handsfree['activity']) : 0; } else { $dfrn_id = x($_POST, 'dfrn_id') ? notags(trim($_POST['dfrn_id'])) : ""; $intro_id = x($_POST, 'intro_id') ? intval($_POST['intro_id']) : 0; $duplex = x($_POST, 'duplex') ? intval($_POST['duplex']) : 0; $cid = x($_POST, 'contact_id') ? intval($_POST['contact_id']) : 0; $hidden = x($_POST, 'hidden') ? intval($_POST['hidden']) : 0; $activity = x($_POST, 'activity') ? intval($_POST['activity']) : 0; } /** * * Ensure that dfrn_id has precedence when we go to find the contact record. * We only want to search based on contact id if there is no dfrn_id, * e.g. for OStatus network followers. * */ if (strlen($dfrn_id)) { $cid = 0; } logger('Confirming request for dfrn_id (issued) ' . $dfrn_id); if ($cid) { logger('Confirming follower with contact_id: ' . $cid); } /** * * The other person will have been issued an ID when they first requested friendship. * Locate their record. At this time, their record will have both pending and blocked set to 1. * There won't be any dfrn_id if this is a network follower, so use the contact_id instead. * */ $r = q("SELECT * FROM `contact` WHERE ( ( `issued-id` != '' AND `issued-id` = '%s' ) OR ( `id` = %d AND `id` != 0 ) ) AND `uid` = %d AND `duplex` = 0 LIMIT 1", dbesc($dfrn_id), intval($cid), intval($uid)); if (!count($r)) { logger('Contact not found in DB.'); notice(t('Contact not found.') . EOL); notice(t('This may occasionally happen if contact was requested by both persons and it has already been approved.') . EOL); return; } $contact = $r[0]; $contact_id = $contact['id']; $relation = $contact['rel']; $site_pubkey = $contact['site-pubkey']; $dfrn_confirm = $contact['confirm']; $aes_allow = $contact['aes_allow']; $network = strlen($contact['issued-id']) ? NETWORK_DFRN : NETWORK_OSTATUS; if ($contact['network']) { $network = $contact['network']; } if ($network === NETWORK_DFRN) { /** * * Generate a key pair for all further communications with this person. * We have a keypair for every contact, and a site key for unknown people. * This provides a means to carry on relationships with other people if * any single key is compromised. It is a robust key. We're much more * worried about key leakage than anybody cracking it. * */ require_once 'include/crypto.php'; $res = new_keypair(4096); $private_key = $res['prvkey']; $public_key = $res['pubkey']; // Save the private key. Send them the public key. $r = q("UPDATE `contact` SET `prvkey` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($private_key), intval($contact_id), intval($uid)); $params = array(); /** * * Per the DFRN protocol, we will verify both ends by encrypting the dfrn_id with our * site private key (person on the other end can decrypt it with our site public key). * Then encrypt our profile URL with the other person's site public key. They can decrypt * it with their site private key. If the decryption on the other end fails for either * item, it indicates tampering or key failure on at least one site and we will not be * able to provide a secure communication pathway. * * If other site is willing to accept full encryption, (aes_allow is 1 AND we have php5.3 * or later) then we encrypt the personal public key we send them using AES-256-CBC and a * random key which is encrypted with their site public key. * */ $src_aes_key = random_string(); $result = ''; openssl_private_encrypt($dfrn_id, $result, $user[0]['prvkey']); $params['dfrn_id'] = bin2hex($result); $params['public_key'] = $public_key; $my_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname']; openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey); $params['source_url'] = bin2hex($params['source_url']); if ($aes_allow && function_exists('openssl_encrypt')) { openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey); $params['aes_key'] = bin2hex($params['aes_key']); $params['public_key'] = bin2hex(openssl_encrypt($public_key, 'AES-256-CBC', $src_aes_key)); } $params['dfrn_version'] = DFRN_PROTOCOL_VERSION; if ($duplex == 1) { $params['duplex'] = 1; } if ($user[0]['page-flags'] == PAGE_COMMUNITY) { $params['page'] = 1; } if ($user[0]['page-flags'] == PAGE_PRVGROUP) { $params['page'] = 2; } logger('Confirm: posting data to ' . $dfrn_confirm . ': ' . print_r($params, true), LOGGER_DATA); /** * * POST all this stuff to the other site. * Temporarily raise the network timeout to 120 seconds because the default 60 * doesn't always give the other side quite enough time to decrypt everything. * */ $a->config['system']['curl_timeout'] = 120; $res = post_url($dfrn_confirm, $params); logger(' Confirm: received data: ' . $res, LOGGER_DATA); // Now figure out what they responded. Try to be robust if the remote site is // having difficulty and throwing up errors of some kind. $leading_junk = substr($res, 0, strpos($res, '<?xml')); $res = substr($res, strpos($res, '<?xml')); if (!strlen($res)) { // No XML at all, this exchange is messed up really bad. // We shouldn't proceed, because the xml parser might choke, // and $status is going to be zero, which indicates success. // We can hardly call this a success. notice(t('Response from remote site was not understood.') . EOL); return; } if (strlen($leading_junk) && get_config('system', 'debugging')) { // This might be more common. Mixed error text and some XML. // If we're configured for debugging, show the text. Proceed in either case. notice(t('Unexpected response from remote site: ') . EOL . $leading_junk . EOL); } if (stristr($res, "<status") === false) { // wrong xml! stop here! notice(t('Unexpected response from remote site: ') . EOL . htmlspecialchars($res) . EOL); return; } $xml = parse_xml_string($res); $status = (int) $xml->status; $message = unxmlify($xml->message); // human readable text of what may have gone wrong. switch ($status) { case 0: info(t("Confirmation completed successfully.") . EOL); if (strlen($message)) { notice(t('Remote site reported: ') . $message . EOL); } break; case 1: // birthday paradox - generate new dfrn-id and fall through. $new_dfrn_id = random_string(); $r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($new_dfrn_id), intval($contact_id), intval($uid)); case 2: notice(t("Temporary failure. Please wait and try again.") . EOL); if (strlen($message)) { notice(t('Remote site reported: ') . $message . EOL); } break; case 3: notice(t("Introduction failed or was revoked.") . EOL); if (strlen($message)) { notice(t('Remote site reported: ') . $message . EOL); } break; } if ($status == 0 && $intro_id) { // Success. Delete the notification. $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d", intval($intro_id), intval($uid)); } if ($status != 0) { return; } } /* * * We have now established a relationship with the other site. * Let's make our own personal copy of their profile photo so we don't have * to always load it from their site. * * We will also update the contact record with the nature and scope of the relationship. * */ require_once 'include/Photo.php'; $photos = import_profile_photo($contact['photo'], $uid, $contact_id); logger('dfrn_confirm: confirm - imported photos'); if ($network === NETWORK_DFRN) { $new_relation = CONTACT_IS_FOLLOWER; if ($relation == CONTACT_IS_SHARING || $duplex) { $new_relation = CONTACT_IS_FRIEND; } if ($relation == CONTACT_IS_SHARING && $duplex) { $duplex = 0; } $r = q("UPDATE `contact` SET\n\t\t\t\t`photo` = '%s',\n\t\t\t\t`thumb` = '%s',\n\t\t\t\t`micro` = '%s',\n\t\t\t\t`rel` = %d,\n\t\t\t\t`name-date` = '%s',\n\t\t\t\t`uri-date` = '%s',\n\t\t\t\t`avatar-date` = '%s',\n\t\t\t\t`blocked` = 0,\n\t\t\t\t`pending` = 0,\n\t\t\t\t`duplex` = %d,\n\t\t\t\t`hidden` = %d,\n\t\t\t\t`network` = '%s' WHERE `id` = %d\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($new_relation), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($duplex), intval($hidden), dbesc(NETWORK_DFRN), intval($contact_id)); } else { // $network !== NETWORK_DFRN $network = $contact['network'] ? $contact['network'] : NETWORK_OSTATUS; $notify = $contact['notify'] ? $contact['notify'] : ''; $poll = $contact['poll'] ? $contact['poll'] : ''; if (!$contact['notify'] || !$contact['poll']) { $arr = lrdd($contact['url']); if (count($arr)) { foreach ($arr as $link) { if ($link['@attributes']['rel'] === 'salmon') { $notify = $link['@attributes']['href']; } if ($link['@attributes']['rel'] === NAMESPACE_FEED) { $poll = $link['@attributes']['href']; } } } } $new_relation = $contact['rel']; $writable = $contact['writable']; if ($network === NETWORK_DIASPORA) { if ($duplex) { $new_relation = CONTACT_IS_FRIEND; } else { $new_relation = CONTACT_IS_FOLLOWER; } if ($new_relation != CONTACT_IS_FOLLOWER) { $writable = 1; } } $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d", intval($intro_id), intval($uid)); $r = q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t\t`thumb` = '%s',\n\t\t\t\t`micro` = '%s',\n\t\t\t\t`name-date` = '%s',\n\t\t\t\t`uri-date` = '%s',\n\t\t\t\t`avatar-date` = '%s',\n\t\t\t\t`notify` = '%s',\n\t\t\t\t`poll` = '%s',\n\t\t\t\t`blocked` = 0,\n\t\t\t\t`pending` = 0,\n\t\t\t\t`network` = '%s',\n\t\t\t\t`writable` = %d,\n\t\t\t\t`hidden` = %d,\n\t\t\t\t`rel` = %d\n\t\t\t\tWHERE `id` = %d\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($notify), dbesc($poll), dbesc($network), intval($writable), intval($hidden), intval($new_relation), intval($contact_id)); } if ($r === false) { notice(t('Unable to set contact photo.') . EOL); } // reload contact info $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($contact_id)); if (count($r)) { $contact = $r[0]; } else { $contact = null; } if (isset($new_relation) && $new_relation == CONTACT_IS_FRIEND) { if ($contact && $contact['network'] === NETWORK_DIASPORA) { require_once 'include/diaspora.php'; $ret = diaspora_share($user[0], $r[0]); logger('mod_follow: diaspora_share returns: ' . $ret); } // Send a new friend post if we are allowed to... $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", intval($uid)); if (count($r) && $r[0]['hide-friends'] == 0 && $activity && !$hidden) { require_once 'include/items.php'; $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($uid)); if (count($self)) { $arr = array(); $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $uid); $arr['uid'] = $uid; $arr['contact-id'] = $self[0]['id']; $arr['wall'] = 1; $arr['type'] = 'wall'; $arr['gravity'] = 0; $arr['origin'] = 1; $arr['author-name'] = $arr['owner-name'] = $self[0]['name']; $arr['author-link'] = $arr['owner-link'] = $self[0]['url']; $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb']; $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]'; $APhoto = '[url=' . $self[0]['url'] . ']' . '[img]' . $self[0]['thumb'] . '[/img][/url]'; $B = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $BPhoto = '[url=' . $contact['url'] . ']' . '[img]' . $contact['thumb'] . '[/img][/url]'; $arr['verb'] = ACTIVITY_FRIEND; $arr['object-type'] = ACTIVITY_OBJ_PERSON; $arr['body'] = sprintf(t('%1$s is now friends with %2$s'), $A, $B) . "\n\n\n" . $BPhoto; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact['name'] . '</title>' . '<id>' . $contact['url'] . '/' . $contact['name'] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact['url'] . '" />' . "\n"); $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact['thumb'] . '" />' . "\n"); $arr['object'] .= '</link></object>' . "\n"; $arr['last-child'] = 1; $arr['allow_cid'] = $user[0]['allow_cid']; $arr['allow_gid'] = $user[0]['allow_gid']; $arr['deny_cid'] = $user[0]['deny_cid']; $arr['deny_gid'] = $user[0]['deny_gid']; $i = item_store($arr); if ($i) { proc_run('php', "include/notifier.php", "activity", "{$i}"); } } } } $g = q("select def_gid from user where uid = %d limit 1", intval($uid)); if ($contact && $g && intval($g[0]['def_gid'])) { require_once 'include/group.php'; group_add_member($uid, '', $contact['id'], $g[0]['def_gid']); } // Let's send our user to the contact editor in case they want to // do anything special with this new friend. if ($handsfree === null) { goaway($a->get_baseurl() . '/contacts/' . intval($contact_id)); } else { return; } //NOTREACHED } /** * * * End of Scenario 1. [Local confirmation of remote friend request]. * * Begin Scenario 2. This is the remote response to the above scenario. * This will take place on the site that originally initiated the friend request. * In the section above where the confirming party makes a POST and * retrieves xml status information, they are communicating with the following code. * */ if (x($_POST, 'source_url')) { // We are processing an external confirmation to an introduction created by our user. $public_key = x($_POST, 'public_key') ? $_POST['public_key'] : ''; $dfrn_id = x($_POST, 'dfrn_id') ? hex2bin($_POST['dfrn_id']) : ''; $source_url = x($_POST, 'source_url') ? hex2bin($_POST['source_url']) : ''; $aes_key = x($_POST, 'aes_key') ? $_POST['aes_key'] : ''; $duplex = x($_POST, 'duplex') ? intval($_POST['duplex']) : 0; $page = x($_POST, 'page') ? intval($_POST['page']) : 0; $version_id = x($_POST, 'dfrn_version') ? (double) $_POST['dfrn_version'] : 2.0; $forum = $page == 1 ? 1 : 0; $prv = $page == 2 ? 1 : 0; logger('dfrn_confirm: requestee contacted: ' . $node); logger('dfrn_confirm: request: POST=' . print_r($_POST, true), LOGGER_DATA); // If $aes_key is set, both of these items require unpacking from the hex transport encoding. if (x($aes_key)) { $aes_key = hex2bin($aes_key); $public_key = hex2bin($public_key); } // Find our user's account $r = q("SELECT * FROM `user` WHERE `nickname` = '%s' LIMIT 1", dbesc($node)); if (!count($r)) { $message = sprintf(t('No user record found for \'%s\' '), $node); xml_status(3, $message); // failure // NOTREACHED } $my_prvkey = $r[0]['prvkey']; $local_uid = $r[0]['uid']; if (!strstr($my_prvkey, 'PRIVATE KEY')) { $message = t('Our site encryption key is apparently messed up.'); xml_status(3, $message); } // verify everything $decrypted_source_url = ""; openssl_private_decrypt($source_url, $decrypted_source_url, $my_prvkey); if (!strlen($decrypted_source_url)) { $message = t('Empty site URL was provided or URL could not be decrypted by us.'); xml_status(3, $message); // NOTREACHED } $ret = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($decrypted_source_url), intval($local_uid)); if (!count($ret)) { if (strstr($decrypted_source_url, 'http:')) { $newurl = str_replace('http:', 'https:', $decrypted_source_url); } else { $newurl = str_replace('https:', 'http:', $decrypted_source_url); } $ret = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($newurl), intval($local_uid)); if (!count($ret)) { // this is either a bogus confirmation (?) or we deleted the original introduction. $message = t('Contact record was not found for you on our site.'); xml_status(3, $message); return; // NOTREACHED } } $relation = $ret[0]['rel']; // Decrypt all this stuff we just received $foreign_pubkey = $ret[0]['site-pubkey']; $dfrn_record = $ret[0]['id']; if (!$foreign_pubkey) { $message = sprintf(t('Site public key not available in contact record for URL %s.'), $newurl); xml_status(3, $message); } $decrypted_dfrn_id = ""; openssl_public_decrypt($dfrn_id, $decrypted_dfrn_id, $foreign_pubkey); if (strlen($aes_key)) { $decrypted_aes_key = ""; openssl_private_decrypt($aes_key, $decrypted_aes_key, $my_prvkey); $dfrn_pubkey = openssl_decrypt($public_key, 'AES-256-CBC', $decrypted_aes_key); } else { $dfrn_pubkey = $public_key; } $r = q("SELECT * FROM `contact` WHERE `dfrn-id` = '%s' LIMIT 1", dbesc($decrypted_dfrn_id)); if (count($r)) { $message = t('The ID provided by your system is a duplicate on our system. It should work if you try again.'); xml_status(1, $message); // Birthday paradox - duplicate dfrn-id // NOTREACHED } $r = q("UPDATE `contact` SET `dfrn-id` = '%s', `pubkey` = '%s' WHERE `id` = %d", dbesc($decrypted_dfrn_id), dbesc($dfrn_pubkey), intval($dfrn_record)); if (!count($r)) { $message = t('Unable to set your contact credentials on our system.'); xml_status(3, $message); } // It's possible that the other person also requested friendship. // If it is a duplex relationship, ditch the issued-id if one exists. if ($duplex) { $r = q("UPDATE `contact` SET `issued-id` = '' WHERE `id` = %d", intval($dfrn_record)); } // We're good but now we have to scrape the profile photo and send notifications. $r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1", intval($dfrn_record)); if (count($r)) { $photo = $r[0]['photo']; } else { $photo = $a->get_baseurl() . '/images/person-175.jpg'; } require_once "include/Photo.php"; $photos = import_profile_photo($photo, $local_uid, $dfrn_record); logger('dfrn_confirm: request - photos imported'); $new_relation = CONTACT_IS_SHARING; if ($relation == CONTACT_IS_FOLLOWER || $duplex) { $new_relation = CONTACT_IS_FRIEND; } if ($relation == CONTACT_IS_FOLLOWER && $duplex) { $duplex = 0; } $r = q("UPDATE `contact` SET\n\t\t\t`photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`rel` = %d,\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s',\n\t\t\t`blocked` = 0,\n\t\t\t`pending` = 0,\n\t\t\t`duplex` = %d,\n\t\t\t`forum` = %d,\n\t\t\t`prv` = %d,\n\t\t\t`network` = '%s' WHERE `id` = %d\n\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($new_relation), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($duplex), intval($forum), intval($prv), dbesc(NETWORK_DFRN), intval($dfrn_record)); if ($r === false) { // indicates schema is messed up or total db failure $message = t('Unable to update your contact profile details on our system'); xml_status(3, $message); } // Otherwise everything seems to have worked and we are almost done. Yay! // Send an email notification logger('dfrn_confirm: request: info updated'); $r = q("SELECT `contact`.*, `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\tWHERE `contact`.`id` = %d LIMIT 1", intval($dfrn_record)); if (count($r)) { $combined = $r[0]; } if (count($r) && $r[0]['notify-flags'] & NOTIFY_CONFIRM) { $mutual = $new_relation == CONTACT_IS_FRIEND; notification(array('type' => NOTIFY_CONFIRM, 'notify_flags' => $r[0]['notify-flags'], 'language' => $r[0]['language'], 'to_name' => $r[0]['username'], 'to_email' => $r[0]['email'], 'uid' => $r[0]['uid'], 'link' => $a->get_baseurl() . '/contacts/' . $dfrn_record, 'source_name' => strlen(stripslashes($r[0]['name'])) ? stripslashes($r[0]['name']) : t('[Name Withheld]'), 'source_link' => $r[0]['url'], 'source_photo' => $r[0]['photo'], 'verb' => $mutual ? ACTIVITY_FRIEND : ACTIVITY_FOLLOW, 'otype' => 'intro')); } // Send a new friend post if we are allowed to... if ($page && intval(get_pconfig($local_uid, 'system', 'post_joingroup'))) { $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", intval($local_uid)); if (count($r) && $r[0]['hide-friends'] == 0) { require_once 'include/items.php'; $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($local_uid)); if (count($self)) { $arr = array(); $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $local_uid); $arr['uid'] = $local_uid; $arr['contact-id'] = $self[0]['id']; $arr['wall'] = 1; $arr['type'] = 'wall'; $arr['gravity'] = 0; $arr['origin'] = 1; $arr['author-name'] = $arr['owner-name'] = $self[0]['name']; $arr['author-link'] = $arr['owner-link'] = $self[0]['url']; $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb']; $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]'; $APhoto = '[url=' . $self[0]['url'] . ']' . '[img]' . $self[0]['thumb'] . '[/img][/url]'; $B = '[url=' . $combined['url'] . ']' . $combined['name'] . '[/url]'; $BPhoto = '[url=' . $combined['url'] . ']' . '[img]' . $combined['thumb'] . '[/img][/url]'; $arr['verb'] = ACTIVITY_JOIN; $arr['object-type'] = ACTIVITY_OBJ_GROUP; $arr['body'] = sprintf(t('%1$s has joined %2$s'), $A, $B) . "\n\n\n" . $BPhoto; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_GROUP . '</type><title>' . $combined['name'] . '</title>' . '<id>' . $combined['url'] . '/' . $combined['name'] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $combined['url'] . '" />' . "\n"); $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $combined['thumb'] . '" />' . "\n"); $arr['object'] .= '</link></object>' . "\n"; $arr['last-child'] = 1; $arr['allow_cid'] = $user[0]['allow_cid']; $arr['allow_gid'] = $user[0]['allow_gid']; $arr['deny_cid'] = $user[0]['deny_cid']; $arr['deny_gid'] = $user[0]['deny_gid']; $i = item_store($arr); if ($i) { proc_run('php', "include/notifier.php", "activity", "{$i}"); } } } } xml_status(0); // Success return; // NOTREACHED ////////////////////// End of this scenario /////////////////////////////////////////////// } // somebody arrived here by mistake or they are fishing. Send them to the homepage. goaway(z_root()); // NOTREACHED }
function item_is_remote_self($contact, &$datarray) { $a = get_app(); if (!$contact['remote_self']) { return false; } // Prevent the forwarding of posts that are forwarded if ($datarray["extid"] == NETWORK_DFRN) { return false; } // Prevent to forward already forwarded posts if ($datarray["app"] == $a->get_hostname()) { return false; } // Only forward posts if ($datarray["verb"] != ACTIVITY_POST) { return false; } if ($contact['network'] != NETWORK_FEED and $datarray['private']) { return false; } $datarray2 = $datarray; logger('remote-self start - Contact ' . $contact['url'] . ' - ' . $contact['remote_self'] . ' Item ' . print_r($datarray, true), LOGGER_DEBUG); if ($contact['remote_self'] == 2) { $r = q("SELECT `id`,`url`,`name`,`thumb` FROM `contact` WHERE `uid` = %d AND `self`", intval($contact['uid'])); if (count($r)) { $datarray['contact-id'] = $r[0]["id"]; $datarray['owner-name'] = $r[0]["name"]; $datarray['owner-link'] = $r[0]["url"]; $datarray['owner-avatar'] = $r[0]["thumb"]; $datarray['author-name'] = $datarray['owner-name']; $datarray['author-link'] = $datarray['owner-link']; $datarray['author-avatar'] = $datarray['owner-avatar']; } if ($contact['network'] != NETWORK_FEED) { $datarray["guid"] = get_guid(32); unset($datarray["plink"]); $datarray["uri"] = item_new_uri($a->get_hostname(), $contact['uid'], $datarray["guid"]); $datarray["parent-uri"] = $datarray["uri"]; $datarray["extid"] = $contact['network']; $urlpart = parse_url($datarray2['author-link']); $datarray["app"] = $urlpart["host"]; } else { $datarray['private'] = 0; } } if ($contact['network'] != NETWORK_FEED) { // Store the original post $r = item_store($datarray2, false, false); logger('remote-self post original item - Contact ' . $contact['url'] . ' return ' . $r . ' Item ' . print_r($datarray2, true), LOGGER_DEBUG); } else { $datarray["app"] = "Feed"; } return true; }
function like_content(&$a) { if (!local_user() && !remote_user()) { return; } $verb = notags(trim($_GET['verb'])); if (!$verb) { $verb = 'like'; } switch ($verb) { case 'like': case 'unlike': $activity = ACTIVITY_LIKE; break; case 'dislike': case 'undislike': $activity = ACTIVITY_DISLIKE; break; default: return; break; } $item_id = $a->argc > 1 ? notags(trim($a->argv[1])) : 0; logger('like: verb ' . $verb . ' item ' . $item_id); $r = q("SELECT * FROM `item` WHERE ( `id` = '%s' OR `uri` = '%s') AND `id` = `parent` LIMIT 1", dbesc($item_id), dbesc($item_id)); if (!$item_id || !count($r)) { logger('like: no item ' . $item_id); return; } $item = $r[0]; $owner_uid = $item['uid']; if (!can_write_wall($a, $owner_uid)) { return; } $remote_owner = null; if (!$item['wall']) { // The top level post may have been written by somebody on another system $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['contact-id']), intval($item['uid'])); if (!count($r)) { return; } if (!$r[0]['self']) { $remote_owner = $r[0]; } } // this represents the post owner on this system. $r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\tWHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1", intval($owner_uid)); if (count($r)) { $owner = $r[0]; } if (!$owner) { logger('like: no owner'); return; } if (!$remote_owner) { $remote_owner = $owner; } // This represents the person posting if (local_user() && local_user() == $owner_uid) { $contact = $owner; } else { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($_SESSION['visitor_id']), intval($owner_uid)); if (count($r)) { $contact = $r[0]; } } if (!$contact) { return; } $r = q("SELECT `id` FROM `item` WHERE `verb` = '%s' AND `deleted` = 0 \n\t\tAND `contact-id` = %d AND ( `parent` = '%s' OR `parent-uri` = '%s') LIMIT 1", dbesc($activity), intval($contact['id']), dbesc($item_id), dbesc($item_id)); if (count($r)) { // Already voted, undo it $r = q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), intval($r[0]['id'])); proc_run('php', "include/notifier.php", "like", "{$post_id}"); return; } $uri = item_new_uri($a->get_hostname(), $owner_uid); $post_type = $item['resource-id'] ? t('photo') : t('status'); $objtype = $item['resource-id'] ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE; $link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n"); $body = $item['body']; $obj = <<<EOT \t<object> \t\t<type>{$objtype}</type> \t\t<local>1</local> \t\t<id>{$item['uri']}</id> \t\t<link>{$link}</link> \t\t<title></title> \t\t<content>{$body}</content> \t</object> EOT; if ($verb === 'like') { $bodyverb = t('%1$s likes %2$s\'s %3$s'); } if ($verb === 'dislike') { $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s'); } if (!isset($bodyverb)) { return; } $arr = array(); $arr['uri'] = $uri; $arr['uid'] = $owner_uid; $arr['contact-id'] = $contact['id']; $arr['type'] = 'activity'; $arr['wall'] = $item['wall']; $arr['origin'] = 1; $arr['gravity'] = GRAVITY_LIKE; $arr['parent'] = $item['id']; $arr['parent-uri'] = $item['uri']; $arr['owner-name'] = $remote_owner['name']; $arr['owner-link'] = $remote_owner['url']; $arr['owner-avatar'] = $remote_owner['thumb']; $arr['author-name'] = $contact['name']; $arr['author-link'] = $contact['url']; $arr['author-avatar'] = $contact['thumb']; $ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]'; $plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]'; $arr['body'] = sprintf($bodyverb, $ulink, $alink, $plink); $arr['verb'] = $activity; $arr['object-type'] = $objtype; $arr['object'] = $obj; $arr['allow_cid'] = $item['allow_cid']; $arr['allow_gid'] = $item['allow_gid']; $arr['deny_cid'] = $item['deny_cid']; $arr['deny_gid'] = $item['deny_gid']; $arr['visible'] = 1; $arr['unseen'] = 1; $arr['last-child'] = 0; $post_id = item_store($arr); if (!$item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['id']), intval($owner_uid)); } $arr['id'] = $post_id; call_hooks('post_local_end', $arr); proc_run('php', "include/notifier.php", "like", "{$post_id}"); killme(); // return; // NOTREACHED }
function like_content(&$a) { if (!local_user() && !remote_user()) { return; } $verb = notags(trim($_GET['verb'])); if (!$verb) { $verb = 'like'; } switch ($verb) { case 'like': case 'unlike': $activity = ACTIVITY_LIKE; break; case 'dislike': case 'undislike': $activity = ACTIVITY_DISLIKE; break; case 'attendyes': case 'unattendyes': $activity = ACTIVITY_ATTEND; break; case 'attendno': case 'unattendno': $activity = ACTIVITY_ATTENDNO; break; case 'attendmaybe': case 'unattendmaybe': $activity = ACTIVITY_ATTENDMAYBE; break; default: return; break; } $item_id = $a->argc > 1 ? notags(trim($a->argv[1])) : 0; logger('like: verb ' . $verb . ' item ' . $item_id); $r = q("SELECT * FROM `item` WHERE `id` = '%s' OR `uri` = '%s' LIMIT 1", dbesc($item_id), dbesc($item_id)); if (!$item_id || !count($r)) { logger('like: no item ' . $item_id); return; } $item = $r[0]; $owner_uid = $item['uid']; if (!can_write_wall($a, $owner_uid)) { return; } $remote_owner = null; if (!$item['wall']) { // The top level post may have been written by somebody on another system $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['contact-id']), intval($item['uid'])); if (!count($r)) { return; } if (!$r[0]['self']) { $remote_owner = $r[0]; } } // this represents the post owner on this system. $r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\tWHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1", intval($owner_uid)); if (count($r)) { $owner = $r[0]; } if (!$owner) { logger('like: no owner'); return; } if (!$remote_owner) { $remote_owner = $owner; } // This represents the person posting if (local_user() && local_user() == $owner_uid) { $contact = $owner; } else { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($_SESSION['visitor_id']), intval($owner_uid)); if (count($r)) { $contact = $r[0]; } } if (!$contact) { return; } // See if we've been passed a return path to redirect to $return_path = x($_REQUEST, 'return') ? $_REQUEST['return'] : ''; $verbs = " '" . dbesc($activity) . "' "; // event participation are essentially radio toggles. If you make a subsequent choice, // we need to eradicate your first choice. if ($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) { $verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' "; } $r = q("SELECT `id`, `guid` FROM `item` WHERE `verb` IN ( {$verbs} ) AND `deleted` = 0\n\t\tAND `contact-id` = %d AND `uid` = %d\n\t\tAND (`parent` = '%s' OR `parent-uri` = '%s' OR `thr-parent` = '%s') LIMIT 1", intval($contact['id']), intval($owner_uid), dbesc($item_id), dbesc($item_id), dbesc($item['uri'])); if (count($r)) { $like_item = $r[0]; // Already voted, undo it $r = q("UPDATE `item` SET `deleted` = 1, `unseen` = 1, `changed` = '%s' WHERE `id` = %d", dbesc(datetime_convert()), intval($like_item['id'])); // Clean up the Diaspora signatures for this like // Go ahead and do it even if Diaspora support is disabled. We still want to clean up // if it had been enabled in the past $r = q("DELETE FROM `sign` WHERE `iid` = %d", intval($like_item['id'])); // Save the author information for the unlike in case we need to relay to Diaspora store_diaspora_like_retract_sig($activity, $item, $like_item, $contact); // proc_run('php',"include/notifier.php","like","$post_id"); // $post_id isn't defined here! $like_item_id = $like_item['id']; proc_run('php', "include/notifier.php", "like", "{$like_item_id}"); like_content_return($a->get_baseurl(), $return_path); return; // NOTREACHED } $uri = item_new_uri($a->get_hostname(), $owner_uid); $post_type = $item['resource-id'] ? t('photo') : t('status'); if ($item['obj_type'] === ACTIVITY_OBJ_EVENT) { $post_type = t('event'); } $objtype = $item['resource-id'] ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE; $link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n"); $body = $item['body']; $obj = <<<EOT \t<object> \t\t<type>{$objtype}</type> \t\t<local>1</local> \t\t<id>{$item['uri']}</id> \t\t<link>{$link}</link> \t\t<title></title> \t\t<content>{$body}</content> \t</object> EOT; if ($verb === 'like') { $bodyverb = t('%1$s likes %2$s\'s %3$s'); } if ($verb === 'dislike') { $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s'); } if ($verb === 'attendyes') { $bodyverb = t('%1$s is attending %2$s\'s %3$s'); } if ($verb === 'attendno') { $bodyverb = t('%1$s is not attending %2$s\'s %3$s'); } if ($verb === 'attendmaybe') { $bodyverb = t('%1$s may attend %2$s\'s %3$s'); } if (!isset($bodyverb)) { return; } $arr = array(); $arr['uri'] = $uri; $arr['uid'] = $owner_uid; $arr['contact-id'] = $contact['id']; $arr['type'] = 'activity'; $arr['wall'] = $item['wall']; $arr['origin'] = 1; $arr['gravity'] = GRAVITY_LIKE; $arr['parent'] = $item['id']; $arr['parent-uri'] = $item['uri']; $arr['thr-parent'] = $item['uri']; $arr['owner-name'] = $remote_owner['name']; $arr['owner-link'] = $remote_owner['url']; $arr['owner-avatar'] = $remote_owner['thumb']; $arr['author-name'] = $contact['name']; $arr['author-link'] = $contact['url']; $arr['author-avatar'] = $contact['thumb']; $ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]'; $plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]'; $arr['body'] = sprintf($bodyverb, $ulink, $alink, $plink); $arr['verb'] = $activity; $arr['object-type'] = $objtype; $arr['object'] = $obj; $arr['allow_cid'] = $item['allow_cid']; $arr['allow_gid'] = $item['allow_gid']; $arr['deny_cid'] = $item['deny_cid']; $arr['deny_gid'] = $item['deny_gid']; $arr['visible'] = 1; $arr['unseen'] = 1; $arr['last-child'] = 0; $post_id = item_store($arr); if (!$item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d", intval($item['id']), intval($owner_uid)); } // Save the author information for the like in case we need to relay to Diaspora store_diaspora_like_sig($activity, $post_type, $contact, $post_id); $arr['id'] = $post_id; call_hooks('post_local_end', $arr); proc_run('php', "include/notifier.php", "like", "{$post_id}"); like_content_return($a->get_baseurl(), $return_path); killme(); // NOTREACHED // return; // NOTREACHED }
function poke_init(&$a) { if (!local_user()) { return; } $uid = local_user(); $verb = notags(trim($_GET['verb'])); if (!$verb) { return; } $verbs = get_poke_verbs(); if (!array_key_exists($verb, $verbs)) { return; } $activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]); $contact_id = intval($_GET['cid']); if (!$contact_id) { return; } $parent = x($_GET, 'parent') ? intval($_GET['parent']) : 0; logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG); $r = q("SELECT * FROM `contact` WHERE `id` = %d and `uid` = %d LIMIT 1", intval($contact_id), intval($uid)); if (!count($r)) { logger('poke: no contact ' . $contact_id); return; } $target = $r[0]; if ($parent) { $r = q("select uri, private, allow_cid, allow_gid, deny_cid, deny_gid \n\t\t\tfrom item where id = %d and parent = %d and uid = %d limit 1", intval($parent), intval($parent), intval($uid)); if (count($r)) { $parent_uri = $r[0]['uri']; $private = $r[0]['private']; $allow_cid = $r[0]['allow_cid']; $allow_gid = $r[0]['allow_gid']; $deny_cid = $r[0]['deny_cid']; $deny_gid = $r[0]['deny_gid']; } } else { $private = x($_GET, 'private') ? intval($_GET['private']) : 0; $allow_cid = $private ? '<' . $target['id'] . '>' : $a->user['allow_cid']; $allow_gid = $private ? '' : $a->user['allow_gid']; $deny_cid = $private ? '' : $a->user['deny_cid']; $deny_gid = $private ? '' : $a->user['deny_gid']; } $poster = $a->contact; $uri = item_new_uri($a->get_hostname(), $uid); $arr = array(); $arr['uid'] = $uid; $arr['uri'] = $uri; $arr['parent-uri'] = $parent_uri ? $parent_uri : $uri; $arr['type'] = 'activity'; $arr['wall'] = 1; $arr['contact-id'] = $poster['id']; $arr['owner-name'] = $poster['name']; $arr['owner-link'] = $poster['url']; $arr['owner-avatar'] = $poster['thumb']; $arr['author-name'] = $poster['name']; $arr['author-link'] = $poster['url']; $arr['author-avatar'] = $poster['thumb']; $arr['title'] = ''; $arr['allow_cid'] = $allow_cid; $arr['allow_gid'] = $allow_gid; $arr['deny_cid'] = $deny_cid; $arr['deny_gid'] = $deny_gid; $arr['last-child'] = 1; $arr['visible'] = 1; $arr['verb'] = $activity; $arr['private'] = $private; $arr['object-type'] = ACTIVITY_OBJ_PERSON; $arr['origin'] = 1; $arr['body'] = '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]' . ' ' . t($verbs[$verb][0]) . ' ' . '[url=' . $target['url'] . ']' . $target['name'] . '[/url]'; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $target['name'] . '</title><id>' . $a->get_baseurl() . '/contact/' . $target['id'] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $target['url'] . '" />' . "\n"); $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $target['photo'] . '" />' . "\n"); $arr['object'] .= '</link></object>' . "\n"; $item_id = item_store($arr); if ($item_id) { q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc($a->get_baseurl() . '/display/' . $poster['nickname'] . '/' . $item_id), intval($uid), intval($item_id)); proc_run('php', "include/notifier.php", "tag", "{$item_id}"); } call_hooks('post_local_end', $arr); proc_run('php', "include/notifier.php", "like", "{$post_id}"); return; }
function diaspora_request($importer, $xml) { $a = get_app(); $sender_handle = unxmlify($xml->sender_handle); $recipient_handle = unxmlify($xml->recipient_handle); if (!$sender_handle || !$recipient_handle) { return; } $contact = diaspora_get_contact_by_handle($importer['uid'], $sender_handle); if ($contact) { // perhaps we were already sharing with this person. Now they're sharing with us. // That makes us friends. if ($contact['rel'] == CONTACT_IS_FOLLOWER && !in_array($importer['page-flags'], array(PAGE_COMMUNITY, PAGE_SOAPBOX))) { q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($contact['id']), intval($importer['uid'])); } // send notification $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", intval($importer['uid'])); if (count($r) && !$r[0]['hide-friends'] && !$contact['hidden'] && intval(get_pconfig($importer['uid'], 'system', 'post_newfriend'))) { require_once 'include/items.php'; $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($importer['uid'])); // they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array if (count($self) && $contact['rel'] == CONTACT_IS_FOLLOWER) { $arr = array(); $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $importer['uid']); $arr['uid'] = $importer['uid']; $arr['contact-id'] = $self[0]['id']; $arr['wall'] = 1; $arr['type'] = 'wall'; $arr['gravity'] = 0; $arr['origin'] = 1; $arr['author-name'] = $arr['owner-name'] = $self[0]['name']; $arr['author-link'] = $arr['owner-link'] = $self[0]['url']; $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb']; $arr['verb'] = ACTIVITY_FRIEND; $arr['object-type'] = ACTIVITY_OBJ_PERSON; $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]'; $B = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $BPhoto = '[url=' . $contact['url'] . ']' . '[img]' . $contact['thumb'] . '[/img][/url]'; $arr['body'] = sprintf(t('%1$s is now friends with %2$s'), $A, $B) . "\n\n\n" . $Bphoto; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact['name'] . '</title>' . '<id>' . $contact['url'] . '/' . $contact['name'] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact['url'] . '" />' . "\n"); $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact['thumb'] . '" />' . "\n"); $arr['object'] .= '</link></object>' . "\n"; $arr['last-child'] = 1; $arr['allow_cid'] = $user[0]['allow_cid']; $arr['allow_gid'] = $user[0]['allow_gid']; $arr['deny_cid'] = $user[0]['deny_cid']; $arr['deny_gid'] = $user[0]['deny_gid']; $i = item_store($arr); if ($i) { proc_run('php', "include/notifier.php", "activity", "{$i}"); } } } return; } $ret = find_diaspora_person_by_handle($sender_handle); if (!count($ret) || $ret['network'] != NETWORK_DIASPORA) { logger('diaspora_request: Cannot resolve diaspora handle ' . $sender_handle . ' for ' . $recipient_handle); return; } $batch = $ret['batch'] ? $ret['batch'] : implode('/', array_slice(explode('/', $ret['url']), 0, 3)) . '/receive/public'; $r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)\n\t\tVALUES ( %d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d) ", intval($importer['uid']), dbesc($ret['network']), dbesc($ret['addr']), datetime_convert(), dbesc($ret['url']), dbesc(normalise_link($ret['url'])), dbesc($batch), dbesc($ret['name']), dbesc($ret['nick']), dbesc($ret['photo']), dbesc($ret['pubkey']), dbesc($ret['notify']), dbesc($ret['poll']), 1, 2); // find the contact record we just created $contact_record = diaspora_get_contact_by_handle($importer['uid'], $sender_handle); if (!$contact_record) { logger('diaspora_request: unable to locate newly created contact record.'); return; } $g = q("select def_gid from user where uid = %d limit 1", intval($importer['uid'])); if ($g && intval($g[0]['def_gid'])) { require_once 'include/group.php'; group_add_member($importer['uid'], '', $contact_record['id'], $g[0]['def_gid']); } if ($importer['page-flags'] == PAGE_NORMAL) { $hash = random_string() . (string) time(); // Generate a confirm_key $ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime` )\n\t\t\tVALUES ( %d, %d, %d, %d, '%s', '%s', '%s' )", intval($importer['uid']), intval($contact_record['id']), 0, 0, dbesc(t('Sharing notification from Diaspora network')), dbesc($hash), dbesc(datetime_convert())); } else { // automatic friend approval require_once 'include/Photo.php'; $photos = import_profile_photo($contact_record['photo'], $importer['uid'], $contact_record['id']); // technically they are sharing with us (CONTACT_IS_SHARING), // but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX // we are going to change the relationship and make them a follower. if ($importer['page-flags'] == PAGE_FREELOVE) { $new_relation = CONTACT_IS_FRIEND; } else { $new_relation = CONTACT_IS_FOLLOWER; } $r = q("UPDATE `contact` SET\n\t\t\t`photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`rel` = %d,\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s',\n\t\t\t`blocked` = 0,\n\t\t\t`pending` = 0,\n\t\t\t`writable` = 1\n\t\t\tWHERE `id` = %d\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($new_relation), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_record['id'])); $u = q("select * from user where uid = %d limit 1", intval($importer['uid'])); if ($u) { $ret = diaspora_share($u[0], $contact_record); } } return; }
function like_content(&$a) { if (!local_user() && !remote_user()) { return; } $verb = notags(trim($_GET['verb'])); if (!$verb) { $verb = 'like'; } switch ($verb) { case 'like': case 'unlike': $activity = ACTIVITY_LIKE; break; case 'dislike': case 'undislike': $activity = ACTIVITY_DISLIKE; break; default: return; break; } $item_id = $a->argc > 1 ? notags(trim($a->argv[1])) : 0; logger('like: verb ' . $verb . ' item ' . $item_id); $r = q("SELECT * FROM `item` WHERE ( `id` = '%s' OR `uri` = '%s') AND `id` = `parent` LIMIT 1", dbesc($item_id), dbesc($item_id)); if (!$item_id || !count($r)) { logger('like: no item ' . $item_id); return; } $item = $r[0]; $owner_uid = $item['uid']; if (!can_write_wall($a, $owner_uid)) { return; } $remote_owner = null; if (!$item['wall']) { // The top level post may have been written by somebody on another system $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['contact-id']), intval($item['uid'])); if (!count($r)) { return; } if (!$r[0]['self']) { $remote_owner = $r[0]; } } // this represents the post owner on this system. $r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\tWHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1", intval($owner_uid)); if (count($r)) { $owner = $r[0]; } if (!$owner) { logger('like: no owner'); return; } if (!$remote_owner) { $remote_owner = $owner; } // This represents the person posting if (local_user() && local_user() == $owner_uid) { $contact = $owner; } else { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($_SESSION['visitor_id']), intval($owner_uid)); if (count($r)) { $contact = $r[0]; } } if (!$contact) { return; } $r = q("SELECT * FROM `item` WHERE `verb` = '%s' AND `deleted` = 0 \n\t\tAND `contact-id` = %d AND ( `parent` = '%s' OR `parent-uri` = '%s') LIMIT 1", dbesc($activity), intval($contact['id']), dbesc($item_id), dbesc($item_id)); if (count($r)) { $like_item = $r[0]; // Already voted, undo it $r = q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), intval($like_item['id'])); // Clean up the `sign` table $r = q("DELETE FROM `sign` WHERE `iid` = %d", intval($like_item['id'])); // Save the author information for the unlike in case we need to relay to Diaspora // Note that we can only create a signature for a user of the local server. We don't have // a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it // means we are the relay, and for relayable_retractions, Diaspora // only checks the parent_author_signature if it doesn't have to relay further // // If $item['resource-id'] exists, it means the item is a photo. Diaspora doesn't support // likes on photos, so don't bother. if ($activity === ACTIVITY_LIKE && !$item['resource-id']) { $signed_text = $like_item['guid'] . ';' . 'Like'; if ($contact['network'] === NETWORK_DIASPORA) { $diaspora_handle = $contact['addr']; } else { // Only works for NETWORK_DFRN $contact_baseurl_start = strpos($contact['url'], '://') + 3; $contact_baseurl_length = strpos($contact['url'], '/profile') - $contact_baseurl_start; $contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length); $diaspora_handle = $contact['nick'] . '@' . $contact_baseurl; // Get contact's private key if he's a user of the local Friendica server $r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1", dbesc($contact['url'])); if ($r) { $contact_uid = $r['uid']; $r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1", intval($contact_uid)); if ($r) { $authorsig = base64_encode(rsa_sign($signed_text, $r['prvkey'], 'sha256')); } } } if (!isset($authorsig)) { $authorsig = ''; } q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($like_item['id']), dbesc($signed_text), dbesc($authorsig), dbesc($diaspora_handle)); } // proc_run('php',"include/notifier.php","like","$post_id"); // $post_id isn't defined here! $like_item_id = $like_item['id']; proc_run('php', "include/notifier.php", "like", "{$like_item_id}"); return; } $uri = item_new_uri($a->get_hostname(), $owner_uid); $post_type = $item['resource-id'] ? t('photo') : t('status'); $objtype = $item['resource-id'] ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE; $link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n"); $body = $item['body']; $obj = <<<EOT \t<object> \t\t<type>{$objtype}</type> \t\t<local>1</local> \t\t<id>{$item['uri']}</id> \t\t<link>{$link}</link> \t\t<title></title> \t\t<content>{$body}</content> \t</object> EOT; if ($verb === 'like') { $bodyverb = t('%1$s likes %2$s\'s %3$s'); } if ($verb === 'dislike') { $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s'); } if (!isset($bodyverb)) { return; } $arr = array(); $arr['uri'] = $uri; $arr['uid'] = $owner_uid; $arr['contact-id'] = $contact['id']; $arr['type'] = 'activity'; $arr['wall'] = $item['wall']; $arr['origin'] = 1; $arr['gravity'] = GRAVITY_LIKE; $arr['parent'] = $item['id']; $arr['parent-uri'] = $item['uri']; $arr['owner-name'] = $remote_owner['name']; $arr['owner-link'] = $remote_owner['url']; $arr['owner-avatar'] = $remote_owner['thumb']; $arr['author-name'] = $contact['name']; $arr['author-link'] = $contact['url']; $arr['author-avatar'] = $contact['thumb']; $ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]'; $plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]'; $arr['body'] = sprintf($bodyverb, $ulink, $alink, $plink); $arr['verb'] = $activity; $arr['object-type'] = $objtype; $arr['object'] = $obj; $arr['allow_cid'] = $item['allow_cid']; $arr['allow_gid'] = $item['allow_gid']; $arr['deny_cid'] = $item['deny_cid']; $arr['deny_gid'] = $item['deny_gid']; $arr['visible'] = 1; $arr['unseen'] = 1; $arr['last-child'] = 0; $post_id = item_store($arr); if (!$item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['id']), intval($owner_uid)); } // Save the author information for the like in case we need to relay to Diaspora // Note that we can only create a signature for a user of the local server. We don't have // a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it // means we are the relay, and for relayable_retractions, Diaspora // only checks the parent_author_signature if it doesn't have to relay further if ($activity === ACTIVITY_LIKE && $post_type === t('status')) { if ($contact['network'] === NETWORK_DIASPORA) { $diaspora_handle = $contact['addr']; } else { // Only works for NETWORK_DFRN $contact_baseurl_start = strpos($contact['url'], '://') + 3; $contact_baseurl_length = strpos($contact['url'], '/profile') - $contact_baseurl_start; $contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length); $diaspora_handle = $contact['nick'] . '@' . $contact_baseurl; // Get contact's private key if he's a user of the local Friendica server $r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1", dbesc($contact['url'])); if ($r) { $contact_uid = $r['uid']; $r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1", intval($contact_uid)); if ($r) { $contact_uprvkey = $r['prvkey']; } } } $r = q("SELECT guid, parent FROM `item` WHERE id = %d LIMIT 1", intval($post_id)); if ($r) { $p = q("SELECT guid FROM `item` WHERE id = %d AND parent = %d LIMIT 1", intval($r[0]['parent']), intval($r[0]['parent'])); if ($p) { $signed_text = $r[0]['guid'] . ';Post;' . $p[0]['guid'] . ';true;' . $diaspora_handle; if (isset($contact_uprvkey)) { $authorsig = base64_encode(rsa_sign($signed_text, $contact_uprvkey, 'sha256')); } else { $authorsig = ''; } q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($post_id), dbesc($signed_text), dbesc($authorsig), dbesc($diaspora_handle)); } } } $arr['id'] = $post_id; call_hooks('post_local_end', $arr); proc_run('php', "include/notifier.php", "like", "{$post_id}"); killme(); // return; // NOTREACHED }