function p_init(&$a) { if (argc() < 2) { http_status_exit(401); } $mid = str_replace('.xml', '', argv(1)); $r = q("select * from item where mid = '%s' and item_wall = 1 and item_private = 0 limit 1", dbesc($mid)); if (!$r || !perm_is_allowed($r[0]['uid'], '', 'view_stream')) { http_status_exit(404); } $c = q("select * from channel where channel_id = %d limit 1", intval($r[0]['uid'])); if (!$c) { http_status_exit(404); } $myaddr = $c[0]['channel_address'] . '@' . App::get_hostname(); $item = $r[0]; $title = $item['title']; $body = bb2diaspora_itembody($item); $created = datetime_convert('UTC', 'UTC', $item['created'], 'Y-m-d H:i:s \\U\\T\\C'); $tpl = get_markup_template('diaspora_post.tpl', 'addon/diaspora'); $msg = replace_macros($tpl, array('$body' => xmlify($body), '$guid' => $item['mid'], '$handle' => xmlify($myaddr), '$public' => 'true', '$created' => $created, '$provider' => $item['app'] ? $item['app'] : t('$projectname'))); header('Content-type: text/xml'); echo $msg; killme(); }
function qcomment_addon_settings_post(&$a, &$b) { if (!local_user()) { return; } if ($_POST['qcomment-submit']) { set_pconfig(local_user(), 'qcomment', 'words', xmlify($_POST['qcomment-words'])); info(t('Quick Comment settings saved.') . EOL); } }
/** * xmlify and put in a document */ public function testXmlifyDocument() { $tag = "<tag>I want to break</tag>"; $xml = xmlify($tag); $text = '<text>' . $xml . '</text>'; $xml_parser = xml_parser_create(); //should be possible to parse it $values = array(); $index = array(); $this->assertEquals(1, xml_parse_into_struct($xml_parser, $text, $values, $index)); $this->assertEquals(array('TEXT' => array(0)), $index); $this->assertEquals(array(array('tag' => 'TEXT', 'type' => 'complete', 'level' => 1, 'value' => $tag)), $values); xml_parser_free($xml_parser); }
function categories_widget($baseurl, $selected = '') { $a = get_app(); $saved = get_pconfig($a->profile['profile_uid'], 'system', 'filetags'); if (!strlen($saved)) { return; } $matches = false; $terms = array(); $cnt = preg_match_all('/<(.*?)>/', $saved, $matches, PREG_SET_ORDER); if ($cnt) { foreach ($matches as $mtch) { $unescaped = xmlify(file_tag_decode($mtch[1])); $terms[] = array('name' => $unescaped, 'selected' => $selected == $unescaped ? 'selected' : ''); } } return replace_macros(get_markup_template('categories_widget.tpl'), array('$title' => t('Categories'), '$desc' => '', '$sel_all' => $selected == '' ? 'selected' : '', '$all' => t('Everything'), '$terms' => $terms, '$base' => $baseurl)); }
function notifier_run($argv, $argc) { global $a, $db; if (is_null($a)) { $a = new App(); } if (is_null($db)) { @(include ".htconfig.php"); require_once "dba.php"; $db = new dba($db_host, $db_user, $db_pass, $db_data); unset($db_host, $db_user, $db_pass, $db_data); } require_once "session.php"; require_once "datetime.php"; require_once 'include/items.php'; require_once 'include/bbcode.php'; load_config('config'); load_config('system'); load_hooks(); if ($argc < 3) { return; } $a->set_baseurl(get_config('system', 'url')); logger('notifier: invoked: ' . print_r($argv, true)); $cmd = $argv[1]; switch ($cmd) { case 'mail': default: $item_id = intval($argv[2]); if (!$item_id) { return; } break; } $expire = false; $mail = false; $fsuggest = false; $top_level = false; $recipients = array(); $url_recipients = array(); $normal_mode = true; if ($cmd === 'mail') { $normal_mode = false; $mail = true; $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1", intval($item_id)); if (!count($message)) { return; } $uid = $message[0]['uid']; $recipients[] = $message[0]['contact-id']; $item = $message[0]; } elseif ($cmd === 'expire') { $normal_mode = false; $expire = true; $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1 \n\t\t\tAND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 10 MINUTE", intval($item_id)); $uid = $item_id; $item_id = 0; if (!count($items)) { return; } } elseif ($cmd === 'suggest') { $normal_mode = false; $fsuggest = true; $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item_id)); if (!count($suggest)) { return; } $uid = $suggest[0]['uid']; $recipients[] = $suggest[0]['cid']; $item = $suggest[0]; } else { // find ancestors $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($item_id)); if (!count($r) || !intval($r[0]['parent'])) { return; } $target_item = $r[0]; $parent_id = intval($r[0]['parent']); $uid = $r[0]['uid']; $updated = $r[0]['edited']; if (!$parent_id) { return; } $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer` \n\t\t\tFROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d ORDER BY `id` ASC", intval($parent_id)); if (!count($items)) { return; } // avoid race condition with deleting entries if ($items[0]['deleted']) { foreach ($items as $item) { $item['deleted'] = 1; } } if (count($items) == 1 && $items[0]['id'] === $target_item['id'] && $items[0]['uri'] === $items[0]['parent-uri']) { logger('notifier: top level post'); $top_level = true; } } $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`, \n\t\t`user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, \n\t\t`user`.`page-flags`, `user`.`prvnets`\n\t\tFROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid` \n\t\tWHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", intval($uid)); if (!count($r)) { return; } $owner = $r[0]; $walltowall = $top_level && $owner['id'] != $items[0]['contact-id'] ? true : false; $hub = get_config('system', 'huburl'); // If this is a public conversation, notify the feed hub $public_message = true; // fill this in with a single salmon slap if applicable $slap = ''; if (!($mail || $fsuggest)) { require_once 'include/group.php'; $parent = $items[0]; // This is IMPORTANT!!!! // We will only send a "notify owner to relay" or followup message if the referenced post // originated on our system by virtue of having our hostname somewhere // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere. // if $parent['wall'] == 1 we will already have the parent message in our array // and we will relay the whole lot. // expire sends an entire group of expire messages and cannot be forwarded. // However the conversation owner will be a part of the conversation and will // be notified during this run. // Other DFRN conversation members will be alerted during polled updates. // Diaspora members currently are not notified of expirations, and other networks have // either limited or no ability to process deletions. We should at least fix Diaspora // by stringing togther an array of retractions and sending them onward. $localhost = $a->get_hostname(); if (strpos($localhost, ':')) { $localhost = substr($localhost, 0, strpos($localhost, ':')); } /** * * Be VERY CAREFUL if you make any changes to the following several lines. Seemingly innocuous changes * have been known to cause runaway conditions which affected several servers, along with * permissions issues. * */ $relay_to_owner = false; if (!$top_level && $parent['wall'] == 0 && !$expire && stristr($target_item['uri'], $localhost)) { $relay_to_owner = true; } if ($cmd === 'uplink' && intval($parent['forum_mode']) && !$top_level) { $relay_to_owner = true; } // until the 'origin' flag has been in use for several months // we will just use it as a fallback test // later we will be able to use it as the primary test of whether or not to relay. if (!$target_item['origin']) { $relay_to_owner = false; } if ($parent['origin']) { $relay_to_owner = false; } if ($relay_to_owner) { logger('notifier: followup', LOGGER_DEBUG); // local followup to remote post $followup = true; $public_message = false; // not public $conversant_str = dbesc($parent['contact-id']); } else { $followup = false; // don't send deletions onward for other people's stuff if ($target_item['deleted'] && !intval($target_item['wall'])) { logger('notifier: ignoring delete notification for non-wall item'); return; } if (strlen($parent['allow_cid']) || strlen($parent['allow_gid']) || strlen($parent['deny_cid']) || strlen($parent['deny_gid'])) { $public_message = false; // private recipients, not public } $allow_people = expand_acl($parent['allow_cid']); $allow_groups = expand_groups(expand_acl($parent['allow_gid'])); $deny_people = expand_acl($parent['deny_cid']); $deny_groups = expand_groups(expand_acl($parent['deny_gid'])); // if our parent is a forum, uplink to the origonal author causing // a delivery fork if (intval($parent['forum_mode']) && !$top_level && $cmd !== 'uplink') { proc_run('php', 'include/notifier', 'uplink', $item_id); } $conversants = array(); foreach ($items as $item) { $recipients[] = $item['contact-id']; $conversants[] = $item['contact-id']; // pull out additional tagged people to notify (if public message) if ($public_message && strlen($item['inform'])) { $people = explode(',', $item['inform']); foreach ($people as $person) { if (substr($person, 0, 4) === 'cid:') { $recipients[] = intval(substr($person, 4)); $conversants[] = intval(substr($person, 4)); } else { $url_recipients[] = substr($person, 4); } } } } logger('notifier: url_recipients' . print_r($url_recipients, true)); $conversants = array_unique($conversants); $recipients = array_unique(array_merge($recipients, $allow_people, $allow_groups)); $deny = array_unique(array_merge($deny_people, $deny_groups)); $recipients = array_diff($recipients, $deny); $conversant_str = dbesc(implode(', ', $conversants)); } $r = q("SELECT * FROM `contact` WHERE `id` IN ( {$conversant_str} ) AND `blocked` = 0 AND `pending` = 0"); if (count($r)) { $contacts = $r; } } $feed_template = get_markup_template('atom_feed.tpl'); $mail_template = get_markup_template('atom_mail.tpl'); $atom = ''; $slaps = array(); $hubxml = feed_hublinks(); $birthday = feed_birthday($owner['uid'], $owner['timezone']); if (strlen($birthday)) { $birthday = '<dfrn:birthday>' . xmlify($birthday) . '</dfrn:birthday>'; } $atom .= replace_macros($feed_template, array('$version' => xmlify(FRIENDICA_VERSION), '$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner['nickname']), '$feed_title' => xmlify($owner['name']), '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', $updated . '+00:00', ATOM_TIME)), '$hub' => $hubxml, '$salmon' => '', '$name' => xmlify($owner['name']), '$profile_page' => xmlify($owner['url']), '$photo' => xmlify($owner['photo']), '$thumb' => xmlify($owner['thumb']), '$picdate' => xmlify(datetime_convert('UTC', 'UTC', $owner['avatar-date'] . '+00:00', ATOM_TIME)), '$uridate' => xmlify(datetime_convert('UTC', 'UTC', $owner['uri-date'] . '+00:00', ATOM_TIME)), '$namdate' => xmlify(datetime_convert('UTC', 'UTC', $owner['name-date'] . '+00:00', ATOM_TIME)), '$birthday' => $birthday)); if ($mail) { $public_message = false; // mail is not public $body = fix_private_photos($item['body'], $owner['uid']); $atom .= replace_macros($mail_template, array('$name' => xmlify($owner['name']), '$profile_page' => xmlify($owner['url']), '$thumb' => xmlify($owner['thumb']), '$item_id' => xmlify($item['uri']), '$subject' => xmlify($item['title']), '$created' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', ATOM_TIME)), '$content' => xmlify($body), '$parent_id' => xmlify($item['parent-uri']))); } elseif ($fsuggest) { $public_message = false; // suggestions are not public $sugg_template = get_markup_template('atom_suggest.tpl'); $atom .= replace_macros($sugg_template, array('$name' => xmlify($item['name']), '$url' => xmlify($item['url']), '$photo' => xmlify($item['photo']), '$request' => xmlify($item['request']), '$note' => xmlify($item['note']))); // We don't need this any more q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id'])); } else { if ($followup) { foreach ($items as $item) { // there is only one item if (!$item['parent']) { continue; } if ($item['id'] == $item_id) { logger('notifier: followup: item: ' . print_r($item, true), LOGGER_DATA); $slap = atom_entry($item, 'html', $owner, $owner, false); $atom .= atom_entry($item, 'text', $owner, $owner, false); } } } else { foreach ($items as $item) { if (!$item['parent']) { continue; } // private emails may be in included in public conversations. Filter them. if ($public_message && $item['private']) { continue; } $contact = get_item_contact($item, $contacts); if (!$contact) { continue; } if ($normal_mode) { // we only need the current item, but include the parent because without it // older sites without a corresponding dfrn_notify change may do the wrong thing. if ($item_id == $item['id'] || $item['id'] == $item['parent']) { $atom .= atom_entry($item, 'text', $contact, $owner, true); } } else { $atom .= atom_entry($item, 'text', $contact, $owner, true); } if ($top_level && $public_message && $item['author-link'] === $item['owner-link'] && !$expire) { $slaps[] = atom_entry($item, 'html', $contact, $owner, true); } } } } $atom .= '</feed>' . "\r\n"; logger('notifier: ' . $atom, LOGGER_DATA); logger('notifier: slaps: ' . print_r($slaps, true), LOGGER_DATA); // If this is a public message and pubmail is set on the parent, include all your email contacts $mail_disabled = function_exists('imap_open') && !get_config('system', 'imap_disabled') ? 0 : 1; if (!$mail_disabled) { if (!strlen($target_item['allow_cid']) && !strlen($target_item['allow_gid']) && !strlen($target_item['deny_cid']) && !strlen($target_item['deny_gid']) && intval($target_item['pubmail'])) { $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `network` = '%s'", intval($uid), dbesc(NETWORK_MAIL)); if (count($r)) { foreach ($r as $rr) { $recipients[] = $rr['id']; } } } } if ($followup) { $recip_str = $parent['contact-id']; } else { $recip_str = implode(', ', $recipients); } $r = q("SELECT * FROM `contact` WHERE `id` IN ( %s ) AND `blocked` = 0 AND `pending` = 0 ", dbesc($recip_str)); require_once 'include/salmon.php'; $interval = get_config('system', 'delivery_interval') === false ? 2 : intval(get_config('system', 'delivery_interval')); // delivery loop if (count($r)) { foreach ($r as $contact) { if (!$mail && !$fsuggest && !$followup && !$contact['self']) { if ($contact['network'] === NETWORK_DIASPORA && $public_message) { continue; } q("insert into deliverq ( `cmd`,`item`,`contact` ) values ('%s', %d, %d )", dbesc($cmd), intval($item_id), intval($contact['id'])); } } foreach ($r as $contact) { if ($contact['self']) { continue; } // potentially more than one recipient. Start a new process and space them out a bit. // we will deliver single recipient types of message and email receipients here. if (!$mail && !$fsuggest && !$followup) { proc_run('php', 'include/delivery.php', $cmd, $item_id, $contact['id']); if ($interval) { @time_sleep_until(microtime(true) + (double) $interval); } continue; } $deliver_status = 0; logger("main delivery by notifier: followup={$followup} mail={$mail} fsuggest={$fsuggest}"); switch ($contact['network']) { case NETWORK_DFRN: // perform local delivery if we are on the same site $basepath = implode('/', array_slice(explode('/', $contact['url']), 0, 3)); if (link_compare($basepath, $a->get_baseurl())) { $nickname = basename($contact['url']); if ($contact['issued-id']) { $sql_extra = sprintf(" AND `dfrn-id` = '%s' ", dbesc($contact['issued-id'])); } else { $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($contact['dfrn-id'])); } $x = q("SELECT\t`contact`.*, `contact`.`uid` AS `importer_uid`, \n\t\t\t\t\t\t\t`contact`.`pubkey` AS `cpubkey`, \n\t\t\t\t\t\t\t`contact`.`prvkey` AS `cprvkey`, \n\t\t\t\t\t\t\t`contact`.`thumb` AS `thumb`, \n\t\t\t\t\t\t\t`contact`.`url` as `url`,\n\t\t\t\t\t\t\t`contact`.`name` as `senderName`,\n\t\t\t\t\t\t\t`user`.* \n\t\t\t\t\t\t\tFROM `contact` \n\t\t\t\t\t\t\tLEFT JOIN `user` ON `contact`.`uid` = `user`.`uid` \n\t\t\t\t\t\t\tWHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0\n\t\t\t\t\t\t\tAND `contact`.`network` = '%s' AND `user`.`nickname` = '%s'\n\t\t\t\t\t\t\t{$sql_extra}\n\t\t\t\t\t\t\tAND `user`.`account_expired` = 0 LIMIT 1", dbesc(NETWORK_DFRN), dbesc($nickname)); if (count($x)) { require_once 'library/simplepie/simplepie.inc'; logger('mod-delivery: local delivery'); local_delivery($x[0], $atom); break; } } logger('notifier: dfrndelivery: ' . $contact['name']); $deliver_status = dfrn_deliver($owner, $contact, $atom); logger('notifier: dfrn_delivery returns ' . $deliver_status); if ($deliver_status == -1) { logger('notifier: delivery failed: queuing message'); // queue message for redelivery add_to_queue($contact['id'], NETWORK_DFRN, $atom); } break; case NETWORK_OSTATUS: // Do not send to otatus if we are not configured to send to public networks if ($owner['prvnets']) { break; } if (get_config('system', 'ostatus_disabled') || get_config('system', 'dfrn_only')) { break; } if ($followup && $contact['notify']) { logger('notifier: slapdelivery: ' . $contact['name']); $deliver_status = slapper($owner, $contact['notify'], $slap); if ($deliver_status == -1) { // queue message for redelivery add_to_queue($contact['id'], NETWORK_OSTATUS, $slap); } } else { // only send salmon if public - e.g. if it's ok to notify // a public hub, it's ok to send a salmon if (count($slaps) && $public_message && !$expire) { logger('notifier: slapdelivery: ' . $contact['name']); foreach ($slaps as $slappy) { if ($contact['notify']) { $deliver_status = slapper($owner, $contact['notify'], $slappy); if ($deliver_status == -1) { // queue message for redelivery add_to_queue($contact['id'], NETWORK_OSTATUS, $slappy); } } } } } break; case NETWORK_MAIL: if (get_config('system', 'dfrn_only')) { break; } // WARNING: does not currently convert to RFC2047 header encodings, etc. $addr = $contact['addr']; if (!strlen($addr)) { break; } if ($cmd === 'wall-new' || $cmd === 'comment-new') { $it = null; if ($cmd === 'wall-new') { $it = $items[0]; } else { $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($argv[2]), intval($uid)); if (count($r)) { $it = $r[0]; } } if (!$it) { break; } $local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid)); if (!count($local_user)) { break; } $reply_to = ''; $r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1", intval($uid)); if ($r1 && $r1[0]['reply_to']) { $reply_to = $r1[0]['reply_to']; } $subject = $it['title'] ? $it['title'] : t("(no subject)"); $headers = 'From: ' . $local_user[0]['username'] . ' <' . $local_user[0]['email'] . '>' . "\n"; if ($reply_to) { $headers .= 'Reply-to: ' . $reply_to . "\n"; } $headers .= 'Message-id: <' . $it['uri'] . '>' . "\n"; if ($it['uri'] !== $it['parent-uri']) { $header .= 'References: <' . $it['parent-uri'] . '>' . "\n"; if (!strlen($it['title'])) { $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' LIMIT 1", dbesc($it['parent-uri'])); if (count($r)) { $subtitle = $r[0]['title']; if ($subtitle) { if (strncasecmp($subtitle, 'RE:', 3)) { $subject = $subtitle; } else { $subject = 'Re: ' . $subtitle; } } } } } $headers .= 'MIME-Version: 1.0' . "\n"; $headers .= 'Content-Type: text/html; charset=UTF-8' . "\n"; $headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; $html = prepare_body($it); $message = '<html><body>' . $html . '</body></html>'; logger('notifier: email delivery to ' . $addr); mail($addr, $subject, $message, $headers); } break; case NETWORK_DIASPORA: require_once 'include/diaspora.php'; if (get_config('system', 'dfrn_only') || !get_config('system', 'diaspora_enabled')) { break; } if ($mail) { diaspora_send_mail($item, $owner, $contact); break; } if (!$normal_mode) { break; } // special handling for followup to public post // all other public posts processed as public batches further below if ($public_message) { if ($followup) { diaspora_send_followup($target_item, $owner, $contact, true); } break; } if (!$contact['pubkey']) { break; } if ($target_item['verb'] === ACTIVITY_DISLIKE) { // unsupported break; } elseif ($target_item['deleted'] && $target_item['verb'] !== ACTIVITY_LIKE) { // diaspora delete, diaspora_send_retraction($target_item, $owner, $contact); break; } elseif ($followup) { // send comments, likes and retractions of likes to owner to relay diaspora_send_followup($target_item, $owner, $contact); break; } elseif ($target_item['parent'] != $target_item['id']) { // we are the relay - send comments, likes and unlikes to our conversants diaspora_send_relay($target_item, $owner, $contact); break; } elseif ($top_level && !$walltowall) { // currently no workable solution for sending walltowall diaspora_send_status($target_item, $owner, $contact); break; } break; case NETWORK_FEED: case NETWORK_FACEBOOK: if (get_config('system', 'dfrn_only')) { break; } default: break; } } } // send additional slaps to mentioned remote tags (@foo@example.com) if ($slap && count($url_recipients) && ($followup || $top_level) && $public_message && !$expire) { if (!get_config('system', 'dfrn_only')) { foreach ($url_recipients as $url) { if ($url) { logger('notifier: urldelivery: ' . $url); $deliver_status = slapper($owner, $url, $slap); // TODO: redeliver/queue these items on failure, though there is no contact record } } } } if ($public_message) { $r1 = q("SELECT DISTINCT(`batch`), `id`, `name`,`network` FROM `contact` WHERE `network` = '%s' \n\t\t\tAND `uid` = %d AND `rel` != %d group by `batch` ORDER BY rand() ", dbesc(NETWORK_DIASPORA), intval($owner['uid']), intval(CONTACT_IS_SHARING)); $r2 = q("SELECT `id`, `name`,`network` FROM `contact` \n\t\t\tWHERE `network` = '%s' AND `uid` = %d AND `blocked` = 0 AND `pending` = 0\n\t\t\tAND `rel` != %d order by rand() ", dbesc(NETWORK_DFRN), intval($owner['uid']), intval(CONTACT_IS_SHARING)); $r = array_merge($r2, $r1); if (count($r)) { logger('pubdeliver: ' . print_r($r, true), LOGGER_DEBUG); // throw everything into the queue in case we get killed foreach ($r as $rr) { if (!$mail && !$fsuggest && !$followup) { q("insert into deliverq ( `cmd`,`item`,`contact` ) values ('%s', %d, %d )", dbesc($cmd), intval($item_id), intval($rr['id'])); } } foreach ($r as $rr) { // except for Diaspora batch jobs // Don't deliver to folks who have already been delivered to if ($rr['network'] !== NETWORK_DIASPORA && in_array($rr['id'], $conversants)) { logger('notifier: already delivered id=' . $rr['id']); continue; } if (!$mail && !$fsuggest && !$followup) { logger('notifier: delivery agent: ' . $rr['name'] . ' ' . $rr['id']); proc_run('php', 'include/delivery.php', $cmd, $item_id, $rr['id']); if ($interval) { @time_sleep_until(microtime(true) + (double) $interval); } } } } if (strlen($hub)) { $hubs = explode(',', $hub); if (count($hubs)) { foreach ($hubs as $h) { $h = trim($h); if (!strlen($h)) { continue; } $params = 'hub.mode=publish&hub.url=' . urlencode($a->get_baseurl() . '/dfrn_poll/' . $owner['nickname']); post_url($h, $params); logger('pubsub: publish: ' . $h . ' ' . $params . ' returned ' . $a->get_curl_code()); if (count($hubs) > 1) { sleep(7); } // try and avoid multiple hubs responding at precisely the same time } } } } if ($normal_mode) { call_hooks('notifier_normal', $target_item); } call_hooks('notifier_end', $target_item); return; }
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 diaspora_post($importer, $xml, $msg) { $guid = notags(unxmlify($xml['guid'])); $diaspora_handle = notags(diaspora_get_author($xml)); $app = notags(xmlify($xml['provider_display_name'])); if ($diaspora_handle != $msg['author']) { logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.'); return 202; } $xchan = find_diaspora_person_by_handle($diaspora_handle); if (!$xchan || !strstr($xchan['xchan_network'], 'diaspora')) { logger('Cannot resolve diaspora handle ' . $diaspora_handle); return; } $contact = diaspora_get_contact_by_handle($importer['channel_id'], $diaspora_handle); if (!$app) { if (strstr($xchan['xchan_network'], 'friendica')) { $app = 'Friendica'; } else { $app = 'Diaspora'; } } $search_guid = strlen($guid) == 64 ? $guid . '%' : $guid; $r = q("SELECT id FROM item WHERE uid = %d AND mid like '%s' LIMIT 1", intval($importer['channel_id']), dbesc($search_guid)); if ($r) { // check dates if post editing is implemented logger('diaspora_post: message exists: ' . $guid); return; } $created = unxmlify($xml['created_at']); $private = unxmlify($xml['public']) == 'false' ? 1 : 0; $body = diaspora2bb($xml['raw_message']); if ($xml['photo']) { $body = '[img]' . $xml['photo']['remote_photo_path'] . $xml['photo']['remote_photo_name'] . '[/img]' . "\n\n" . $body; $body = scale_external_images($body); } $maxlen = get_max_import_size(); if ($maxlen && mb_strlen($body) > $maxlen) { $body = mb_substr($body, 0, $maxlen, 'UTF-8'); logger('message length exceeds max_import_size: truncated'); } $datarray = array(); // Look for tags and linkify them $results = linkify_tags(get_app(), $body, $importer['channel_id'], true); $datarray['term'] = array(); if ($results) { foreach ($results as $result) { $success = $result['success']; if ($success['replaced']) { $datarray['term'][] = array('uid' => $importer['channel_id'], 'ttype' => $success['termtype'], 'otype' => TERM_OBJ_POST, 'term' => $success['term'], 'url' => $success['url']); } } } $found_tags = false; $followed_tags = get_pconfig($importer['channel_id'], 'diaspora', 'followed_tags'); if ($followed_tags && $datarray['term']) { foreach ($datarray['term'] as $t) { if (in_array($t['term'], $followed_tags)) { $found_tags = true; break; } } } if (!$found_tags && !$contact) { logger('Author is not a connection and no followed tags.'); return; } $cnt = preg_match_all('/@\\[url=(.*?)\\](.*?)\\[\\/url\\]/ism', $body, $matches, PREG_SET_ORDER); if ($cnt) { foreach ($matches as $mtch) { $datarray['term'][] = array('uid' => $importer['channel_id'], 'ttype' => TERM_MENTION, 'otype' => TERM_OBJ_POST, 'term' => $mtch[2], 'url' => $mtch[1]); } } $cnt = preg_match_all('/@\\[zrl=(.*?)\\](.*?)\\[\\/zrl\\]/ism', $body, $matches, PREG_SET_ORDER); if ($cnt) { foreach ($matches as $mtch) { // don't include plustags in the term $term = substr($mtch[2], -1, 1) === '+' ? substr($mtch[2], 0, -1) : $mtch[2]; $datarray['term'][] = array('uid' => $importer['channel_id'], 'ttype' => TERM_MENTION, 'otype' => TERM_OBJ_POST, 'term' => $term, 'url' => $mtch[1]); } } $plink = service_plink($xchan, $guid); $datarray['aid'] = $importer['channel_account_id']; $datarray['uid'] = $importer['channel_id']; $datarray['verb'] = ACTIVITY_POST; $datarray['mid'] = $datarray['parent_mid'] = $guid; $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC', 'UTC', $created); $datarray['item_private'] = $private; $datarray['plink'] = $plink; $datarray['author_xchan'] = $xchan['xchan_hash']; $datarray['owner_xchan'] = $xchan['xchan_hash']; $datarray['body'] = $body; $datarray['app'] = $app; $datarray['item_unseen'] = 1; $datarray['item_thread_top'] = 1; $tgroup = tgroup_check($importer['channel_id'], $datarray); if (!$importer['system'] && !perm_is_allowed($importer['channel_id'], $xchan['xchan_hash'], 'send_stream') && !$tgroup && !$found_tags) { logger('diaspora_post: Ignoring this author.'); return 202; } if ($importer['system']) { $datarray['comment_policy'] = 'network: diaspora'; } if ($contact && !post_is_importable($datarray, $contact)) { logger('diaspora_post: filtering this author.'); return 202; } $result = item_store($datarray); if ($result['success']) { sync_an_item($importer['channel_id'], $result['item_id']); } return; }
function item_getfeedattach($item) { $ret = ''; $arr = explode(',', $item['attach']); if (count($arr)) { foreach ($arr as $r) { $matches = false; $cnt = preg_match('|\\[attach\\]href=\\"(.*?)\\" length=\\"(.*?)\\" type=\\"(.*?)\\" title=\\"(.*?)\\"\\[\\/attach\\]|', $r, $matches); if ($cnt) { $ret .= '<link rel="enclosure" href="' . xmlify($matches[1]) . '" type="' . xmlify($matches[3]) . '" '; if (intval($matches[2])) { $ret .= 'length="' . intval($matches[2]) . '" '; } if ($matches[4] !== ' ') { $ret .= 'title="' . xmlify(trim($matches[4])) . '" '; } $ret .= ' />' . "\r\n"; } } } return $ret; }
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 ljpost_send(&$a, &$b) { if ($b['deleted'] || $b['private'] || $b['created'] !== $b['edited']) { return; } if (!strstr($b['postopts'], 'ljpost')) { return; } if ($b['parent'] != $b['id']) { return; } // LiveJournal post in the LJ user's timezone. // Hopefully the person's Friendica account // will be set to the same thing. $tz = 'UTC'; $x = q("select timezone from user where uid = %d limit 1", intval($b['uid'])); if ($x && strlen($x[0]['timezone'])) { $tz = $x[0]['timezone']; } $lj_username = xmlify(get_pconfig($b['uid'], 'ljpost', 'lj_username')); $lj_password = xmlify(get_pconfig($b['uid'], 'ljpost', 'lj_password')); $lj_journal = xmlify(get_pconfig($b['uid'], 'ljpost', 'lj_journal')); // if(! $lj_journal) // $lj_journal = $lj_username; $lj_blog = xmlify(get_pconfig($b['uid'], 'ljpost', 'lj_blog')); if (!strlen($lj_blog)) { $lj_blog = xmlify('http://www.livejournal.com/interface/xmlrpc'); } if ($lj_username && $lj_password && $lj_blog) { require_once 'include/bbcode.php'; require_once 'include/datetime.php'; $title = xmlify($b['title']); $post = bbcode($b['body']); $post = xmlify($post); $tags = ljpost_get_tags($b['tag']); $date = datetime_convert('UTC', $tz, $b['created'], 'Y-m-d H:i:s'); $year = intval(substr($date, 0, 4)); $mon = intval(substr($date, 5, 2)); $day = intval(substr($date, 8, 2)); $hour = intval(substr($date, 11, 2)); $min = intval(substr($date, 14, 2)); $xml = <<<EOT <?xml version="1.0" encoding="utf-8"?> <methodCall> <methodName>LJ.XMLRPC.postevent</methodName> <params> <param><value> <struct> <member><name>username</name><value><string>{$lj_username}</string></value></member> <member><name>password</name><value><string>{$lj_password}</string></value></member> <member><name>event</name><value><string>{$post}</string></value></member> <member><name>subject</name><value><string>{$title}</string></value></member> <member><name>lineendings</name><value><string>unix</string></value></member> <member><name>year</name><value><int>{$year}</int></value></member> <member><name>mon</name><value><int>{$mon}</int></value></member> <member><name>day</name><value><int>{$day}</int></value></member> <member><name>hour</name><value><int>{$hour}</int></value></member> <member><name>min</name><value><int>{$min}</int></value></member> \t\t<member><name>usejournal</name><value><string>{$lj_username}</string></value></member> \t\t<member> \t\t\t<name>props</name> \t\t\t<value> \t\t\t\t<struct> \t\t\t\t\t<member> \t\t\t\t\t\t<name>useragent</name> \t\t\t\t\t\t<value><string>Friendica</string></value> \t\t\t\t\t</member> \t\t\t\t\t<member> \t\t\t\t\t\t<name>taglist</name> \t\t\t\t\t\t<value><string>{$tags}</string></value> \t\t\t\t\t</member> \t\t\t\t</struct> \t\t\t</value> \t\t</member> </struct> </value></param> </params> </methodCall> EOT; logger('ljpost: data: ' . $xml, LOGGER_DATA); if ($lj_blog !== 'test') { $x = post_url($lj_blog, $xml, array("Content-Type: text/xml")); } logger('posted to livejournal: ' . $x ? $x : '', LOGGER_DEBUG); } }
function xmlize($href, $name, $url, $photo, $date, $message) { $notsxml = '<note href="%s" name="%s" url="%s" photo="%s" date="%s">%s</note>'; return sprintf($notsxml, xmlify($href), xmlify($name), xmlify($url), xmlify($photo), xmlify($date), xmlify($message)); }
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 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 xmlize($href, $name, $url, $photo, $date, $seen, $message) { require_once "mod/proxy.php"; $photo = proxy_url($photo); $data = array('href' => &$href, 'name' => &$name, 'url' => &$url, 'photo' => &$photo, 'date' => &$date, 'seen' => &$seen, 'messsage' => &$message); call_hooks('ping_xmlize', $data); $notsxml = '<note href="%s" name="%s" url="%s" photo="%s" date="%s" seen="%s" >%s</note>'; return sprintf($notsxml, xmlify($href), xmlify($name), xmlify($url), xmlify($photo), xmlify($date), xmlify($seen), xmlify($message)); }
function diaspora_send_mail($item, $owner, $contact) { $a = get_app(); $myaddr = $owner['channel_address'] . '@' . get_app()->get_hostname(); $r = q("select * from conv where id = %d and uid = %d limit 1", intval($item['convid']), intval($item['channel_id'])); if (!count($r)) { logger('diaspora_send_mail: conversation not found.'); return; } $cnv = $r[0]; $conv = array('guid' => xmlify($cnv['guid']), 'subject' => xmlify($cnv['subject']), 'created_at' => xmlify(datetime_convert('UTC', 'UTC', $cnv['created'], 'Y-m-d H:i:s \\U\\T\\C')), 'diaspora_handle' => xmlify($cnv['creator']), 'participant_handles' => xmlify($cnv['recips'])); if (array_key_exists('mail_flags', $item) && $item['mail_flags'] & MAIL_OBSCURED) { $key = get_config('system', 'prvkey'); // if($item['title']) // $item['title'] = crypto_unencapsulate(json_decode_plus($item['title']),$key); if ($item['body']) { $item['body'] = crypto_unencapsulate(json_decode_plus($item['body']), $key); } } $body = bb2diaspora($item['body']); $created = datetime_convert('UTC', 'UTC', $item['created'], 'Y-m-d H:i:s \\U\\T\\C'); $signed_text = $item['mid'] . ';' . $cnv['guid'] . ';' . $body . ';' . $created . ';' . $myaddr . ';' . $cnv['guid']; $sig = base64_encode(rsa_sign($signed_text, $owner['channel_prvkey'], 'sha256')); $msg = array('guid' => xmlify($item['mid']), 'parent_guid' => xmlify($cnv['guid']), 'parent_author_signature' => $item['reply'] ? null : xmlify($sig), 'author_signature' => xmlify($sig), 'text' => xmlify($body), 'created_at' => xmlify($created), 'diaspora_handle' => xmlify($myaddr), 'conversation_guid' => xmlify($cnv['guid'])); if ($item['reply']) { $tpl = get_markup_template('diaspora_message.tpl'); $xmsg = replace_macros($tpl, array('$msg' => $msg)); } else { $conv['messages'] = array($msg); $tpl = get_markup_template('diaspora_conversation.tpl'); $xmsg = replace_macros($tpl, array('$conv' => $conv)); } logger('diaspora_conversation: ' . print_r($xmsg, true), LOGGER_DATA); $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($xmsg, $owner, $contact, $owner['channel_prvkey'], $contact['xchan_pubkey'], false))); return diaspora_transmit($owner, $contact, $slap, false); }
function diaspora_profile_change($channel, $recip, $public_batch = false) { $channel_id = $channel['channel_id']; $r = q("SELECT profile.uid AS profile_uid, profile.* , channel.* FROM profile\n\t\tleft join channel on profile.uid = channel.channel_id\n\t\tWHERE channel.channel_id = %d and profile.is_default = 1 ", intval($channel_id)); $profile_visible = perm_is_allowed($channel_id, '', 'view_profile'); if (!$r) { return; } $profile = $r[0]; $handle = xmlify($channel['channel_address'] . '@' . App::get_hostname()); $first = xmlify(strpos($profile['channel_name'], ' ') ? trim(substr($profile['channel_name'], 0, strpos($profile['channel_name'], ' '))) : $profile['channel_name']); $last = xmlify($first === $profile['channel_name'] ? '' : trim(substr($profile['channel_name'], strlen($first)))); $large = xmlify(z_root() . '/photo/profile/300/' . $profile['profile_uid'] . '.jpg'); $medium = xmlify(z_root() . '/photo/profile/100/' . $profile['profile_uid'] . '.jpg'); $small = xmlify(z_root() . '/photo/profile/50/' . $profile['profile_uid'] . '.jpg'); $searchable = xmlify($profile_visible ? 'true' : 'false'); $nsfw = $channel['channel_pageflags'] & (PAGE_ADULT | PAGE_CENSORED) ? 'true' : 'false'; if ($searchable === 'true') { $dob = '1000-00-00'; if ($profile['dob'] && $profile['dob'] != '0000-00-00') { $dob = (intval($profile['dob']) ? intval($profile['dob']) : '1000') . '-' . datetime_convert('UTC', 'UTC', $profile['dob'], 'm-d'); } if ($dob === '1000-00-00') { $dob = ''; } $gender = xmlify($profile['gender']); $about = $profile['about']; require_once 'include/bbcode.php'; $about = xmlify(strip_tags(bbcode($about))); $location = ''; if ($profile['locality']) { $location .= $profile['locality']; } if ($profile['region']) { if ($location) { $location .= ', '; } $location .= $profile['region']; } if ($profile['country_name']) { if ($location) { $location .= ', '; } $location .= $profile['country_name']; } $location = xmlify($location); $tags = ''; if ($profile['keywords']) { $kw = str_replace(',', ' ', $profile['keywords']); $kw = str_replace(' ', ' ', $kw); $arr = explode(' ', $profile['keywords']); if (count($arr)) { for ($x = 0; $x < 5; $x++) { if (trim($arr[$x])) { $tags .= '#' . trim($arr[$x]) . ' '; } } } } $tags = xmlify(trim($tags)); } $tpl = get_markup_template('diaspora_profile.tpl', 'addon/diaspora'); $msg = replace_macros($tpl, array('$handle' => $handle, '$first' => $first, '$last' => $last, '$large' => $large, '$medium' => $medium, '$small' => $small, '$dob' => $dob, '$gender' => $gender, '$about' => $about, '$location' => $location, '$searchable' => $searchable, '$nsfw' => $nsfw, '$tags' => $tags)); logger('profile_change: ' . $msg, LOGGER_ALL, LOG_DEBUG); $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg, $channel, $recip, $channel['channel_prvkey'], $recip['xchan_pubkey'], $public_batch))); return diaspora_queue($channel, $recip, $slap, $public_batch); }
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}"); } }
/** * apply xmlify() to all values of array $val, recursively */ function array_xmlify($val) { if (is_bool($val)) { return $val ? "true" : "false"; } if (is_array($val)) { return array_map('array_xmlify', $val); } return xmlify((string) $val); }
function xml_status($st, $message = '') { $xml_message = strlen($message) ? "\t<message>" . xmlify($message) . "</message>\r\n" : ''; if ($st) { logger('xml_status returning non_zero: ' . $st . " message=" . $message); } header("Content-type: text/xml"); echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n"; echo "<result>\r\n\t<status>{$st}</status>\r\n{$xml_message}</result>\r\n"; killme(); }
function diaspora_build_status($item, $owner) { $myaddr = channel_reddress($owner); if (intval($item['id']) != intval($item['parent'])) { logger('attempted to send a comment as a top-level post'); return; } $images = array(); $title = $item['title']; $body = bb2diaspora_itembody($item, true); $poll = ''; $public = $item['item_private'] ? 'false' : 'true'; $created = datetime_convert('UTC', 'UTC', $item['created'], 'Y-m-d H:i:s \\U\\T\\C'); // Detect a share element and do a reshare if (!$item['item_private'] && ($ret = diaspora_is_reshare($item['body']))) { $msg = replace_macros(get_markup_template('diaspora_reshare.tpl', 'addon/diaspora'), ['$root_handle' => xmlify($ret['root_handle']), '$root_guid' => $ret['root_guid'], '$guid' => $item['mid'], '$handle' => xmlify($myaddr), '$public' => $public, '$created' => $created, '$provider' => $item['app'] ? $item['app'] : t('$projectname')]); } else { $msg = replace_macros(get_markup_template('diaspora_post.tpl', 'addon/diaspora'), ['$body' => xmlify($body), '$guid' => $item['mid'], '$poll' => $poll, '$handle' => xmlify($myaddr), '$public' => $public, '$created' => $created, '$provider' => $item['app'] ? $item['app'] : t('$projectname')]); } return $msg; }
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 tagger_content(&$a) { if (!local_channel() && !remote_channel()) { return; } $observer_hash = get_observer_hash(); //strip html-tags $term = notags(trim($_GET['term'])); //check if empty if (!$term) { return; } $item_id = argc() > 1 ? notags(trim(argv(1))) : 0; logger('tagger: tag ' . $term . ' item ' . $item_id); $r = q("SELECT * FROM item left join xchan on xchan_hash = author_xchan WHERE id = '%s' and uid = %d LIMIT 1", dbesc($item_id), intval(local_channel())); if (!$item_id || !$r) { logger('tagger: no item ' . $item_id); return; } $item = $r[0]; $owner_uid = $item['uid']; switch ($item['resource_type']) { case 'photo': $targettype = ACTIVITY_OBJ_PHOTO; $post_type = t('photo'); break; case 'event': $targgettype = ACTIVITY_OBJ_EVENT; $post_type = t('event'); break; default: $targettype = ACTIVITY_OBJ_NOTE; $post_type = t('post'); if ($item['mid'] != $item['parent_mid']) { $post_type = t('comment'); } break; } $links = array(array('rel' => 'alternate', 'type' => 'text/html', 'href' => z_root() . '/display/' . $item['mid'])); $target = json_encode(array('type' => $targettype, 'id' => $item['mid'], 'link' => $links, 'title' => $item['title'], 'content' => $item['body'], 'created' => $item['created'], 'edited' => $item['edited'], 'author' => array('name' => $item['xchan_name'], 'address' => $item['xchan_addr'], 'guid' => $item['xchan_guid'], 'guid_sig' => $item['xchan_guid_sig'], 'link' => array(array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item['xchan_url']), array('rel' => 'photo', 'type' => $item['xchan_photo_mimetype'], 'href' => $item['xchan_photo_m']))))); $link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n"); $tagid = $a->get_baseurl() . '/search?tag=' . $term; $objtype = ACTIVITY_OBJ_TAGTERM; $obj = json_encode(array('type' => $objtype, 'id' => $tagid, 'link' => array(array('rel' => 'alternate', 'type' => 'text/html', 'href' => $tagid)), 'title' => $term, 'content' => $term)); $bodyverb = t('%1$s tagged %2$s\'s %3$s with %4$s'); // saving here for reference // also check out x22d5 and x2317 and x0d6b and x0db8 and x24d0 and xff20 !!! $termlink = html_entity_decode('⋕') . '[zrl=' . $a->get_baseurl() . '/search?tag=' . urlencode($term) . ']' . $term . '[/zrl]'; $channel = $a->get_channel(); $arr = array(); $arr['owner_xchan'] = $item['owner_xchan']; $arr['author_xchan'] = $channel['channel_hash']; $arr['item_flags'] = ITEM_ORIGIN; if ($item['item_flags'] & ITEM_WALL) { $arr['item_flags'] |= ITEM_WALL; } $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]'; $alink = '[zrl=' . $item['xchan_url'] . ']' . $item['xchan_name'] . '[/zrl]'; $plink = '[zrl=' . $item['plink'] . ']' . $post_type . '[/zrl]'; $arr['body'] = sprintf($bodyverb, $ulink, $alink, $plink, $termlink); $arr['verb'] = ACTIVITY_TAG; $arr['tgt_type'] = $targettype; $arr['target'] = $target; $arr['obj_type'] = $objtype; $arr['object'] = $obj; $arr['parent_mid'] = $item['mid']; store_item_tag($item['uid'], $item['id'], TERM_OBJ_POST, TERM_HASHTAG, $term, $tagid); $ret = post_activity_item($arr); if ($ret['success']) { proc_run('php', 'include/notifier.php', 'tag', $ret['activity']['id']); } killme(); }
function get_feed_for(&$a, $dfrn_id, $owner_id, $last_update) { require_once 'bbcode.php'; // default permissions - anonymous user $sql_extra = " \n\t\tAND `allow_cid` = '' \n\t\tAND `allow_gid` = '' \n\t\tAND `deny_cid` = '' \n\t\tAND `deny_gid` = '' \n\t"; if (strlen($owner_id) && !intval($owner_id)) { $r = q("SELECT `uid` FROM `user` WHERE `nickname` = '%s' LIMIT 1", dbesc($owner_id)); if (count($r)) { $owner_id = $r[0]['uid']; $owner_nick = $r[0]['nickname']; } } $r = q("SELECT * FROM `contact` WHERE `self` = 1 LIMIT 1"); if (count($r)) { $owner = $r[0]; } else { killme(); } if ($dfrn_id != '*') { $r = q("SELECT * FROM `contact` WHERE ( `issued-id` = '%s' OR ( `duplex` = 1 AND `dfrn-id` = '%s' )) LIMIT 1", dbesc($dfrn_id), dbesc($dfrn_id)); if (!count($r)) { return false; } $contact = $r[0]; $groups = init_groups_visitor($contact['id']); if (count($groups)) { for ($x = 0; $x < count($groups); $x++) { $groups[$x] = '<' . intval($groups[$x]) . '>'; } $gs = implode('|', $groups); } else { $gs = '<<>>'; } // Impossible to match $sql_extra = sprintf(" \n\t\t\tAND ( `allow_cid` = '' OR `allow_cid` REGEXP '<%d>' ) \n\t\t\tAND ( `deny_cid` = '' OR NOT `deny_cid` REGEXP '<%d>' ) \n\t\t\tAND ( `allow_gid` = '' OR `allow_gid` REGEXP '%s' )\n\t\t\tAND ( `deny_gid` = '' OR NOT `deny_gid` REGEXP '%s') \n\t\t", intval($contact['id']), intval($contact['id']), dbesc($gs), dbesc($gs)); } if ($dfrn_id == '' || $dfrn_id == '*') { $sort = 'DESC'; } else { $sort = 'ASC'; } if (!strlen($last_update)) { $last_update = 'now - 30 days'; } $check_date = datetime_convert('UTC', 'UTC', $last_update, 'Y-m-d H:i:s'); $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, \n\t\t`contact`.`name`, `contact`.`photo`, `contact`.`url`, \n\t\t`contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`,\n\t\t`contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, \n\t\t`contact`.`id` AS `contact-id`\n\t\tFROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`\n\t\tWHERE `item`.`visible` = 1 \n\t\tAND NOT `item`.`type` IN ( 'remote', 'net-comment' ) AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0\n\t\tAND ( `item`.`edited` > '%s' OR `item`.`changed` > '%s' )\n\t\t{$sql_extra}\n\t\tORDER BY `parent` %s, `created` ASC LIMIT 0, 300", dbesc($check_date), dbesc($check_date), dbesc($sort)); if (!count($r)) { killme(); } $items = $r; $feed_template = file_get_contents('view/atom_feed.tpl'); $tomb_template = file_get_contents('view/atom_tomb.tpl'); $item_template = file_get_contents('view/atom_item.tpl'); $cmnt_template = file_get_contents('view/atom_cmnt.tpl'); $atom = ''; $atom .= replace_macros($feed_template, array('$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner_nick), '$feed_title' => xmlify($owner['name']), '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', $updated . '+00:00', 'Y-m-d\\TH:i:s\\Z')), '$name' => xmlify($owner['name']), '$profile_page' => xmlify($owner['url']), '$photo' => xmlify($owner['photo']), '$thumb' => xmlify($owner['thumb']), '$picdate' => xmlify(datetime_convert('UTC', 'UTC', $owner['avatar-date'] . '+00:00', 'Y-m-d\\TH:i:s\\Z')), '$uridate' => xmlify(datetime_convert('UTC', 'UTC', $owner['uri-date'] . '+00:00', 'Y-m-d\\TH:i:s\\Z')), '$namdate' => xmlify(datetime_convert('UTC', 'UTC', $owner['name-date'] . '+00:00', 'Y-m-d\\TH:i:s\\Z')))); foreach ($items as $item) { // public feeds get html, our own nodes use bbcode if ($dfrn_id == '*') { $item['body'] = bbcode($item['body']); $type = 'html'; } else { $type = 'text'; } if ($item['deleted']) { $atom .= replace_macros($tomb_template, array('$id' => xmlify($item['uri']), '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', 'Y-m-d\\TH:i:s\\Z')))); } else { $verb = construct_verb($item); $actobj = construct_activity($item); if ($item['parent'] == $item['id']) { $atom .= replace_macros($item_template, array('$name' => xmlify($item['name']), '$profile_page' => xmlify($item['url']), '$thumb' => xmlify($item['thumb']), '$owner_name' => xmlify($item['owner-name']), '$owner_profile_page' => xmlify($item['owner-link']), '$owner_thumb' => xmlify($item['owner-avatar']), '$item_id' => xmlify($item['uri']), '$title' => xmlify($item['title']), '$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', 'Y-m-d\\TH:i:s\\Z')), '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', 'Y-m-d\\TH:i:s\\Z')), '$location' => xmlify($item['location']), '$type' => $type, '$content' => xmlify($item['body']), '$verb' => xmlify($verb), '$actobj' => $actobj, '$comment_allow' => $item['last-child'] && strlen($contact['dfrn-id']) ? 1 : 0)); } else { $atom .= replace_macros($cmnt_template, array('$name' => xmlify($item['name']), '$profile_page' => xmlify($item['url']), '$thumb' => xmlify($item['thumb']), '$item_id' => xmlify($item['uri']), '$title' => xmlify($item['title']), '$published' => xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', 'Y-m-d\\TH:i:s\\Z')), '$updated' => xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', 'Y-m-d\\TH:i:s\\Z')), '$type' => $type, '$content' => xmlify($item['body']), '$verb' => xmlify($verb), '$actobj' => $actobj, '$parent_id' => xmlify($item['parent-uri']), '$comment_allow' => $item['last-child'] ? 1 : 0)); } } } $atom .= '</feed>' . "\r\n"; return $atom; }
function delivery_run(&$argv, &$argc) { global $a, $db; if (is_null($a)) { $a = new App(); } if (is_null($db)) { @(include ".htconfig.php"); require_once "include/dba.php"; $db = new dba($db_host, $db_user, $db_pass, $db_data); unset($db_host, $db_user, $db_pass, $db_data); } require_once "include/session.php"; require_once "include/datetime.php"; require_once 'include/items.php'; require_once 'include/bbcode.php'; require_once 'include/diaspora.php'; require_once 'include/email.php'; load_config('config'); load_config('system'); load_hooks(); if ($argc < 3) { return; } $a->set_baseurl(get_config('system', 'url')); logger('delivery: invoked: ' . print_r($argv, true), LOGGER_DEBUG); $cmd = $argv[1]; $item_id = intval($argv[2]); for ($x = 3; $x < $argc; $x++) { $contact_id = intval($argv[$x]); // Some other process may have delivered this item already. $r = q("select * from deliverq where cmd = '%s' and item = %d and contact = %d limit 1", dbesc($cmd), dbesc($item_id), dbesc($contact_id)); if (!count($r)) { continue; } $maxsysload = intval(get_config('system', 'maxloadavg')); if ($maxsysload < 1) { $maxsysload = 50; } if (function_exists('sys_getloadavg')) { $load = sys_getloadavg(); if (intval($load[0]) > $maxsysload) { logger('system: load ' . $load . ' too high. Delivery deferred to next queue run.'); return; } } // It's ours to deliver. Remove it from the queue. q("delete from deliverq where cmd = '%s' and item = %d and contact = %d", dbesc($cmd), dbesc($item_id), dbesc($contact_id)); if (!$item_id || !$contact_id) { continue; } $expire = false; $top_level = false; $recipients = array(); $url_recipients = array(); $normal_mode = true; $recipients[] = $contact_id; if ($cmd === 'expire') { $normal_mode = false; $expire = true; $items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1 \n\t\t\t\tAND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 30 MINUTE", intval($item_id)); $uid = $item_id; $item_id = 0; if (!count($items)) { continue; } } else { // find ancestors $r = q("SELECT * FROM `item` WHERE `id` = %d and visible = 1 and moderated = 0 LIMIT 1", intval($item_id)); if (!count($r) || !intval($r[0]['parent'])) { continue; } $target_item = $r[0]; $parent_id = intval($r[0]['parent']); $uid = $r[0]['uid']; $updated = $r[0]['edited']; // POSSIBLE CLEANUP --> The following seems superfluous. We've already checked for "if (! intval($r[0]['parent']))" a few lines up if (!$parent_id) { continue; } $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer` \n\t\t\t\tFROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d and visible = 1 and moderated = 0 ORDER BY `id` ASC", intval($parent_id)); if (!count($items)) { continue; } $icontacts = null; $contacts_arr = array(); foreach ($items as $item) { if (!in_array($item['contact-id'], $contacts_arr)) { $contacts_arr[] = intval($item['contact-id']); } } if (count($contacts_arr)) { $str_contacts = implode(',', $contacts_arr); $icontacts = q("SELECT * FROM `contact` \n\t\t\t\t\tWHERE `id` IN ( {$str_contacts} ) "); } if (!($icontacts && count($icontacts))) { continue; } // avoid race condition with deleting entries if ($items[0]['deleted']) { foreach ($items as $item) { $item['deleted'] = 1; } } if (count($items) == 1 && $items[0]['uri'] === $items[0]['parent-uri']) { logger('delivery: top level post'); $top_level = true; } } $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`, \n\t\t\t`user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, \n\t\t\t`user`.`page-flags`, `user`.`prvnets`\n\t\t\tFROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` \n\t\t\tWHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", intval($uid)); if (!count($r)) { continue; } $owner = $r[0]; $walltowall = $top_level && $owner['id'] != $items[0]['contact-id'] ? true : false; $public_message = true; // fill this in with a single salmon slap if applicable $slap = ''; require_once 'include/group.php'; $parent = $items[0]; // This is IMPORTANT!!!! // We will only send a "notify owner to relay" or followup message if the referenced post // originated on our system by virtue of having our hostname somewhere // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere. // if $parent['wall'] == 1 we will already have the parent message in our array // and we will relay the whole lot. // expire sends an entire group of expire messages and cannot be forwarded. // However the conversation owner will be a part of the conversation and will // be notified during this run. // Other DFRN conversation members will be alerted during polled updates. // Diaspora members currently are not notified of expirations, and other networks have // either limited or no ability to process deletions. We should at least fix Diaspora // by stringing togther an array of retractions and sending them onward. $localhost = $a->get_hostname(); if (strpos($localhost, ':')) { $localhost = substr($localhost, 0, strpos($localhost, ':')); } /** * * Be VERY CAREFUL if you make any changes to the following line. Seemingly innocuous changes * have been known to cause runaway conditions which affected several servers, along with * permissions issues. * */ if (!$top_level && $parent['wall'] == 0 && !$expire && stristr($target_item['uri'], $localhost)) { logger('relay denied for delivery agent.'); /* no relay allowed for direct contact delivery */ continue; } if (strlen($parent['allow_cid']) || strlen($parent['allow_gid']) || strlen($parent['deny_cid']) || strlen($parent['deny_gid'])) { $public_message = false; // private recipients, not public } $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `blocked` = 0 AND `pending` = 0", intval($contact_id)); if (count($r)) { $contact = $r[0]; } $hubxml = feed_hublinks(); logger('notifier: slaps: ' . print_r($slaps, true), LOGGER_DATA); require_once 'include/salmon.php'; if ($contact['self']) { continue; } $deliver_status = 0; switch ($contact['network']) { case NETWORK_DFRN: logger('notifier: dfrndelivery: ' . $contact['name']); $feed_template = get_markup_template('atom_feed.tpl'); $mail_template = get_markup_template('atom_mail.tpl'); $atom = ''; $birthday = feed_birthday($owner['uid'], $owner['timezone']); if (strlen($birthday)) { $birthday = '<dfrn:birthday>' . xmlify($birthday) . '</dfrn:birthday>'; } $atom .= replace_macros($feed_template, array('$version' => xmlify(FRIENDICA_VERSION), '$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner['nickname']), '$feed_title' => xmlify($owner['name']), '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', $updated . '+00:00', ATOM_TIME)), '$hub' => $hubxml, '$salmon' => '', '$name' => xmlify($owner['name']), '$profile_page' => xmlify($owner['url']), '$photo' => xmlify($owner['photo']), '$thumb' => xmlify($owner['thumb']), '$picdate' => xmlify(datetime_convert('UTC', 'UTC', $owner['avatar-date'] . '+00:00', ATOM_TIME)), '$uridate' => xmlify(datetime_convert('UTC', 'UTC', $owner['uri-date'] . '+00:00', ATOM_TIME)), '$namdate' => xmlify(datetime_convert('UTC', 'UTC', $owner['name-date'] . '+00:00', ATOM_TIME)), '$birthday' => $birthday, '$community' => $owner['page-flags'] == PAGE_COMMUNITY ? '<dfrn:community>1</dfrn:community>' : '')); foreach ($items as $item) { if (!$item['parent']) { continue; } // private emails may be in included in public conversations. Filter them. if ($public_message && $item['private'] == 1) { continue; } $item_contact = get_item_contact($item, $icontacts); if (!$item_contact) { continue; } if ($normal_mode) { if ($item_id == $item['id'] || $item['id'] == $item['parent']) { $atom .= atom_entry($item, 'text', null, $owner, true, $top_level ? $contact['id'] : 0); } } else { $atom .= atom_entry($item, 'text', null, $owner, true); } } $atom .= '</feed>' . "\r\n"; logger('notifier: ' . $atom, LOGGER_DATA); $basepath = implode('/', array_slice(explode('/', $contact['url']), 0, 3)); // perform local delivery if we are on the same site if (link_compare($basepath, $a->get_baseurl())) { $nickname = basename($contact['url']); if ($contact['issued-id']) { $sql_extra = sprintf(" AND `dfrn-id` = '%s' ", dbesc($contact['issued-id'])); } else { $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($contact['dfrn-id'])); } $x = q("SELECT\t`contact`.*, `contact`.`uid` AS `importer_uid`,\n\t\t\t\t\t\t`contact`.`pubkey` AS `cpubkey`,\n\t\t\t\t\t\t`contact`.`prvkey` AS `cprvkey`,\n\t\t\t\t\t\t`contact`.`thumb` AS `thumb`,\n\t\t\t\t\t\t`contact`.`url` as `url`,\n\t\t\t\t\t\t`contact`.`name` as `senderName`,\n\t\t\t\t\t\t`user`.*\n\t\t\t\t\t\tFROM `contact`\n\t\t\t\t\t\tINNER JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\t\t\t\tWHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0\n\t\t\t\t\t\tAND `contact`.`network` = '%s' AND `user`.`nickname` = '%s'\n\t\t\t\t\t\t{$sql_extra}\n\t\t\t\t\t\tAND `user`.`account_expired` = 0 AND `user`.`account_removed` = 0 LIMIT 1", dbesc(NETWORK_DFRN), dbesc($nickname)); if ($x && count($x)) { $write_flag = $x[0]['rel'] && $x[0]['rel'] != CONTACT_IS_SHARING ? true : false; if (($owner['page-flags'] == PAGE_COMMUNITY || $write_flag) && !$x[0]['writable']) { q("update contact set writable = 1 where id = %d", intval($x[0]['id'])); $x[0]['writable'] = 1; } $ssl_policy = get_config('system', 'ssl_policy'); fix_contact_ssl_policy($x[0], $ssl_policy); // If we are setup as a soapbox we aren't accepting input from this person if ($x[0]['page-flags'] == PAGE_SOAPBOX) { break; } require_once 'library/simplepie/simplepie.inc'; logger('mod-delivery: local delivery'); local_delivery($x[0], $atom); break; } } if (!was_recently_delayed($contact['id'])) { $deliver_status = dfrn_deliver($owner, $contact, $atom); } else { $deliver_status = -1; } logger('notifier: dfrn_delivery returns ' . $deliver_status); if ($deliver_status == -1) { logger('notifier: delivery failed: queuing message'); add_to_queue($contact['id'], NETWORK_DFRN, $atom); } break; case NETWORK_OSTATUS: // Do not send to otatus if we are not configured to send to public networks if ($owner['prvnets']) { break; } if (get_config('system', 'ostatus_disabled') || get_config('system', 'dfrn_only')) { break; } // only send salmon if public - e.g. if it's ok to notify // a public hub, it's ok to send a salmon if ($public_message && !$expire) { $slaps = array(); foreach ($items as $item) { if (!$item['parent']) { continue; } // private emails may be in included in public conversations. Filter them. if ($public_message && $item['private'] == 1) { continue; } $item_contact = get_item_contact($item, $icontacts); if (!$item_contact) { continue; } if ($top_level && $public_message && $item['author-link'] === $item['owner-link'] && !$expire) { $slaps[] = atom_entry($item, 'html', null, $owner, true); } } logger('notifier: slapdelivery: ' . $contact['name']); foreach ($slaps as $slappy) { if ($contact['notify']) { if (!was_recently_delayed($contact['id'])) { $deliver_status = slapper($owner, $contact['notify'], $slappy); } else { $deliver_status = -1; } if ($deliver_status == -1) { // queue message for redelivery add_to_queue($contact['id'], NETWORK_OSTATUS, $slappy); } } } } break; case NETWORK_MAIL: case NETWORK_MAIL2: if (get_config('system', 'dfrn_only')) { break; } // WARNING: does not currently convert to RFC2047 header encodings, etc. $addr = $contact['addr']; if (!strlen($addr)) { break; } if ($cmd === 'wall-new' || $cmd === 'comment-new') { $it = null; if ($cmd === 'wall-new') { $it = $items[0]; } else { $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($argv[2]), intval($uid)); if (count($r)) { $it = $r[0]; } } if (!$it) { break; } $local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid)); if (!count($local_user)) { break; } $reply_to = ''; $r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1", intval($uid)); if ($r1 && $r1[0]['reply_to']) { $reply_to = $r1[0]['reply_to']; } $subject = $it['title'] ? email_header_encode($it['title'], 'UTF-8') : t("(no subject)"); // only expose our real email address to true friends if ($contact['rel'] == CONTACT_IS_FRIEND && !$contact['blocked']) { if ($reply_to) { $headers = 'From: ' . email_header_encode($local_user[0]['username'], 'UTF-8') . ' <' . $reply_to . '>' . "\n"; $headers .= 'Sender: ' . $local_user[0]['email'] . "\n"; } else { $headers = 'From: ' . email_header_encode($local_user[0]['username'], 'UTF-8') . ' <' . $local_user[0]['email'] . '>' . "\n"; } } else { $headers = 'From: ' . email_header_encode($local_user[0]['username'], 'UTF-8') . ' <' . t('noreply') . '@' . $a->get_hostname() . '>' . "\n"; } //if($reply_to) // $headers .= 'Reply-to: ' . $reply_to . "\n"; $headers .= 'Message-Id: <' . iri2msgid($it['uri']) . '>' . "\n"; //logger("Mail: uri: ".$it['uri']." parent-uri ".$it['parent-uri'], LOGGER_DEBUG); //logger("Mail: Data: ".print_r($it, true), LOGGER_DEBUG); //logger("Mail: Data: ".print_r($it, true), LOGGER_DATA); if ($it['uri'] !== $it['parent-uri']) { $headers .= "References: <" . iri2msgid($it["parent-uri"]) . ">"; // If Threading is enabled, write down the correct parent if ($it["thr-parent"] != "" and $it["thr-parent"] != $it["parent-uri"]) { $headers .= " <" . iri2msgid($it["thr-parent"]) . ">"; } $headers .= "\n"; if (!$it['title']) { $r = q("SELECT `title` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($it['parent-uri']), intval($uid)); if (count($r) and $r[0]['title'] != '') { $subject = $r[0]['title']; } else { $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($it['parent-uri']), intval($uid)); if (count($r) and $r[0]['title'] != '') { $subject = $r[0]['title']; } } } if (strncasecmp($subject, 'RE:', 3)) { $subject = 'Re: ' . $subject; } } email_send($addr, $subject, $headers, $it); } break; case NETWORK_DIASPORA: if ($public_message) { $loc = 'public batch ' . $contact['batch']; } else { $loc = $contact['name']; } logger('delivery: diaspora batch deliver: ' . $loc); if (get_config('system', 'dfrn_only') || !get_config('system', 'diaspora_enabled') || !$normal_mode) { break; } if (!$contact['pubkey'] && !$public_message) { break; } if ($target_item['verb'] === ACTIVITY_DISLIKE) { // unsupported break; } elseif ($target_item['deleted'] && $target_item['uri'] === $target_item['parent-uri']) { // top-level retraction logger('delivery: diaspora retract: ' . $loc); diaspora_send_retraction($target_item, $owner, $contact, $public_message); break; } elseif ($target_item['uri'] !== $target_item['parent-uri']) { // we are the relay - send comments, likes and relayable_retractions to our conversants logger('delivery: diaspora relay: ' . $loc); diaspora_send_relay($target_item, $owner, $contact, $public_message); break; } elseif ($top_level && !$walltowall) { // currently no workable solution for sending walltowall logger('delivery: diaspora status: ' . $loc); diaspora_send_status($target_item, $owner, $contact, $public_message); break; } logger('delivery: diaspora unknown mode: ' . $contact['name']); break; case NETWORK_FEED: case NETWORK_FACEBOOK: if (get_config('system', 'dfrn_only')) { break; } case NETWORK_PUMPIO: if (get_config('system', 'dfrn_only')) { break; } default: break; } } return; }
function profile_content(&$a, $update = 0) { $category = $datequery = $datequery2 = ''; if ($a->argc > 2) { for ($x = 2; $x < $a->argc; $x++) { if (is_a_date_arg($a->argv[$x])) { if ($datequery) { $datequery2 = escape_tags($a->argv[$x]); } else { $datequery = escape_tags($a->argv[$x]); } } else { $category = $a->argv[$x]; } } } if (!x($category)) { $category = x($_GET, 'category') ? $_GET['category'] : ''; } if (get_config('system', 'block_public') && !local_user() && !remote_user()) { return login(); } require_once "include/bbcode.php"; require_once 'include/security.php'; require_once 'include/conversation.php'; require_once 'include/acl_selectors.php'; require_once 'include/items.php'; $groups = array(); $tab = 'posts'; $o = ''; if ($update) { // Ensure we've got a profile owner if updating. $a->profile['profile_uid'] = $update; } else { if ($a->profile['profile_uid'] == local_user()) { nav_set_selected('home'); } } $contact = null; $remote_contact = false; $contact_id = 0; if (is_array($_SESSION['remote'])) { foreach ($_SESSION['remote'] as $v) { if ($v['uid'] == $a->profile['profile_uid']) { $contact_id = $v['cid']; break; } } } if ($contact_id) { $groups = init_groups_visitor($contact_id); $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($contact_id), intval($a->profile['profile_uid'])); if (count($r)) { $contact = $r[0]; $remote_contact = true; } } if (!$remote_contact) { if (local_user()) { $contact_id = $_SESSION['cid']; $contact = $a->contact; } } $is_owner = local_user() && local_user() == $a->profile['profile_uid'] ? true : false; if ($a->profile['hidewall'] && !$is_owner && !$remote_contact) { notice(t('Access to this profile has been restricted.') . EOL); return; } if (!$update) { if (x($_GET, 'tab')) { $tab = notags(trim($_GET['tab'])); } $o .= profile_tabs($a, $is_owner, $a->profile['nickname']); if ($tab === 'profile') { $o .= advanced_profile($a); call_hooks('profile_advanced', $o); return $o; } $o .= common_friends_visitor_widget($a->profile['profile_uid']); if (x($_SESSION, 'new_member') && $_SESSION['new_member'] && $is_owner) { $o .= '<a href="newmember" id="newmember-tips" style="font-size: 1.2em;"><b>' . t('Tips for New Members') . '</b></a>' . EOL; } $commpage = $a->profile['page-flags'] == PAGE_COMMUNITY ? true : false; $commvisitor = $commpage && $remote_contact == true ? true : false; $a->page['aside'] .= posted_date_widget($a->get_baseurl(true) . '/profile/' . $a->profile['nickname'], $a->profile['profile_uid'], true); $a->page['aside'] .= categories_widget($a->get_baseurl(true) . '/profile/' . $a->profile['nickname'], x($category) ? xmlify($category) : ''); if (can_write_wall($a, $a->profile['profile_uid'])) { $x = array('is_owner' => $is_owner, 'allow_location' => ($is_owner || $commvisitor) && $a->profile['allow_location'] ? true : false, 'default_location' => $is_owner ? $a->user['default-location'] : '', 'nickname' => $a->profile['nickname'], 'lockstate' => is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock', 'acl' => $is_owner ? populate_acl($a->user, true) : '', 'bang' => '', 'visitor' => $is_owner || $commvisitor ? 'block' : 'none', 'profile_uid' => $a->profile['profile_uid'], 'acl_data' => $is_owner ? construct_acl_data($a, $a->user) : ''); $o .= status_editor($a, $x); } } /** * Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups */ $sql_extra = item_permissions_sql($a->profile['profile_uid'], $remote_contact, $groups); if ($update) { $r = q("SELECT distinct(parent) AS `item_id`, `item`.`network` AS `item_network`,\n\t\t\t`contact`.`uid` AS `contact-uid`\n\t\t\tFROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`\n\t\t\tAND `contact`.`blocked` = 0 AND `contact`.`pending` = 0\n\t\t\tWHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND\n\t\t\t(`item`.`deleted` = 0 OR item.verb = '" . ACTIVITY_LIKE . "' OR item.verb = '" . ACTIVITY_DISLIKE . "')\n\t\t\tand `item`.`moderated` = 0 and `item`.`unseen` = 1\n\t\t\tAND `item`.`wall` = 1\n\t\t\t{$sql_extra}\n\t\t\tORDER BY `item`.`created` DESC", intval($a->profile['profile_uid'])); } else { $sql_post_table = ""; if (x($category)) { $sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ", dbesc(protect_sprintf($category)), intval(TERM_OBJ_POST), intval(TERM_CATEGORY), intval($a->profile['profile_uid'])); //$sql_extra .= protect_sprintf(file_tag_file_query('item',$category,'category')); } if ($datequery) { $sql_extra2 .= protect_sprintf(sprintf(" AND `thread`.`created` <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery)))); } if ($datequery2) { $sql_extra2 .= protect_sprintf(sprintf(" AND `thread`.`created` >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery2)))); } if (get_config('system', 'old_pager')) { $r = q("SELECT COUNT(*) AS `total`\n\t\t\t FROM `thread` INNER JOIN `item` ON `item`.`id` = `thread`.`iid`\n\t\t\t {$sql_post_table} INNER JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`\n\t\t\t AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0\n\t\t\t WHERE `thread`.`uid` = %d AND `thread`.`visible` = 1 AND `thread`.`deleted` = 0\n\t\t\t and `thread`.`moderated` = 0\n\t\t\t AND `thread`.`wall` = 1\n\t\t\t {$sql_extra} {$sql_extra2} ", intval($a->profile['profile_uid'])); if (count($r)) { $a->set_pager_total($r[0]['total']); } } // check if we serve a mobile device and get the user settings // accordingly if ($a->is_mobile) { $itemspage_network = get_pconfig(local_user(), 'system', 'itemspage_mobile_network'); $itemspage_network = intval($itemspage_network) ? $itemspage_network : 20; } else { $itemspage_network = get_pconfig(local_user(), 'system', 'itemspage_network'); $itemspage_network = intval($itemspage_network) ? $itemspage_network : 40; } // now that we have the user settings, see if the theme forces // a maximum item number which is lower then the user choice if ($a->force_max_items > 0 && $a->force_max_items < $itemspage_network) { $itemspage_network = $a->force_max_items; } $a->set_pager_itemspage($itemspage_network); $pager_sql = sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage'])); $r = q("SELECT `thread`.`iid` AS `item_id`, `thread`.`network` AS `item_network`,\n\t\t\t`thread`.`uid` AS `contact-uid`\n\t\t\tFROM `thread` INNER JOIN `item` ON `item`.`id` = `thread`.`iid`\n\t\t\t{$sql_post_table} INNER JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`\n\t\t\tAND `contact`.`blocked` = 0 AND `contact`.`pending` = 0\n\t\t\tWHERE `thread`.`uid` = %d AND `thread`.`visible` = 1 AND `thread`.`deleted` = 0\n\t\t\tand `thread`.`moderated` = 0\n\t\t\tAND `thread`.`wall` = 1\n\t\t\t{$sql_extra} {$sql_extra2}\n\t\t\tORDER BY `thread`.`created` DESC {$pager_sql} ", intval($a->profile['profile_uid'])); } $parents_arr = array(); $parents_str = ''; if (count($r)) { foreach ($r as $rr) { $parents_arr[] = $rr['item_id']; } $parents_str = implode(', ', $parents_arr); $items = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,\n\t\t\t`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`network`, `contact`.`rel`,\n\t\t\t`contact`.`thumb`, `contact`.`self`, `contact`.`writable`,\n\t\t\t`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`\n\t\t\tFROM `item`, `contact`\n\t\t\tWHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0\n\t\t\tand `item`.`moderated` = 0\n\t\t\tAND `contact`.`id` = `item`.`contact-id`\n\t\t\tAND `contact`.`blocked` = 0 AND `contact`.`pending` = 0\n\t\t\tAND `item`.`parent` IN ( %s )\n\t\t\t{$sql_extra} ", intval($a->profile['profile_uid']), dbesc($parents_str)); $items = conv_sort($items, 'created'); } else { $items = array(); } if ($is_owner && !$update && !get_config('theme', 'hide_eventlist')) { $o .= get_birthdays(); $o .= get_events(); } if ($is_owner) { $r = q("UPDATE `item` SET `unseen` = 0\n\t\t\tWHERE `wall` = 1 AND `unseen` = 1 AND `uid` = %d", intval(local_user())); } $o .= conversation($a, $items, 'profile', $update); if (!$update) { if (!get_config('system', 'old_pager')) { $o .= alt_pager($a, count($items)); } else { $o .= paginate($a); } } return $o; }
function diaspora_send_mail($item, $owner, $contact) { $a = get_app(); $myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3); $r = q("select * from conv where id = %d and uid = %d limit 1", intval($item['convid']), intval($item['uid'])); if (!count($r)) { logger('diaspora_send_mail: conversation not found.'); return; } $cnv = $r[0]; $conv = array('guid' => xmlify($cnv['guid']), 'subject' => xmlify($cnv['subject']), 'created_at' => xmlify(datetime_convert('UTC', 'UTC', $cnv['created'], 'Y-m-d H:i:s \\U\\T\\C')), 'diaspora_handle' => xmlify($cnv['creator']), 'participant_handles' => xmlify($cnv['recips'])); $body = bb2diaspora($item['body']); $created = datetime_convert('UTC', 'UTC', $item['created'], 'Y-m-d H:i:s \\U\\T\\C'); $signed_text = $item['guid'] . ';' . $cnv['guid'] . ';' . $body . ';' . $created . ';' . $myaddr . ';' . $cnv['guid']; $sig = base64_encode(rsa_sign($signed_text, $owner['uprvkey'], 'sha256')); $msg = array('guid' => xmlify($item['guid']), 'parent_guid' => xmlify($cnv['guid']), 'parent_author_signature' => xmlify($sig), 'author_signature' => xmlify($sig), 'text' => xmlify($body), 'created_at' => xmlify($created), 'diaspora_handle' => xmlify($myaddr), 'conversation_guid' => xmlify($cnv['guid'])); if ($item['reply']) { $tpl = get_markup_template('diaspora_message.tpl'); $xmsg = replace_macros($tpl, array('$msg' => $msg)); } else { $conv['messages'] = array($msg); $tpl = get_markup_template('diaspora_conversation.tpl'); $xmsg = replace_macros($tpl, array('$conv' => $conv)); } logger('diaspora_conversation: ' . print_r($xmsg, true), LOGGER_DATA); $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($xmsg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], false))); //$slap = 'xml=' . urlencode(diaspora_msg_build($xmsg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],false)); return diaspora_transmit($owner, $contact, $slap, false); }
function dwpost_send(&$a, &$b) { if (!is_item_normal($b) || $b['item_private'] || $b['created'] !== $b['edited']) { return; } if (!perm_is_allowed($b['uid'], '', 'view_stream')) { return; } if (!strstr($b['postopts'], 'dwpost')) { return; } if ($b['parent'] != $b['id']) { return; } // dreamwidth post in the LJ user's timezone. // Hopefully the person's Friendica account // will be set to the same thing. $tz = 'UTC'; $x = q("select channel_timezone from channel where channel_id = %d limit 1", intval($b['uid'])); if ($x && strlen($x[0]['channel_timezone'])) { $tz = $x[0]['channel_timezone']; } $dw_username = get_pconfig($b['uid'], 'dwpost', 'dw_username'); $dw_password = z_unobscure(get_pconfig($b['uid'], 'dwpost', 'dw_password')); $dw_blog = 'http://www.dreamwidth.org/interface/xmlrpc'; if ($dw_username && $dw_password && $dw_blog) { require_once 'include/bbcode.php'; require_once 'include/datetime.php'; $title = $b['title']; $post = bbcode($b['body']); $post = xmlify($post); $tags = dwpost_get_tags($b['tag']); $date = datetime_convert('UTC', $tz, $b['created'], 'Y-m-d H:i:s'); $year = intval(substr($date, 0, 4)); $mon = intval(substr($date, 5, 2)); $day = intval(substr($date, 8, 2)); $hour = intval(substr($date, 11, 2)); $min = intval(substr($date, 14, 2)); $xml = <<<EOT <?xml version="1.0" encoding="utf-8"?> <methodCall><methodName>LJ.XMLRPC.postevent</methodName> <params><param> <value><struct> <member><name>year</name><value><int>{$year}</int></value></member> <member><name>mon</name><value><int>{$mon}</int></value></member> <member><name>day</name><value><int>{$day}</int></value></member> <member><name>hour</name><value><int>{$hour}</int></value></member> <member><name>min</name><value><int>{$min}</int></value></member> <member><name>event</name><value><string>{$post}</string></value></member> <member><name>username</name><value><string>{$dw_username}</string></value></member> <member><name>password</name><value><string>{$dw_password}</string></value></member> <member><name>subject</name><value><string>{$title}</string></value></member> <member><name>lineendings</name><value><string>unix</string></value></member> <member><name>ver</name><value><int>1</int></value></member> <member><name>props</name> <value><struct> <member><name>useragent</name><value><string>Friendica</string></value></member> <member><name>taglist</name><value><string>{$tags}</string></value></member> </struct></value></member> </struct></value> </param></params> </methodCall> EOT; logger('dwpost: data: ' . $xml, LOGGER_DATA); if ($dw_blog !== 'test') { $x = z_post_url($dw_blog, $xml, array('headers' => array("Content-Type: text/xml"))); } logger('posted to dreamwidth: ' . print_r($x, true), LOGGER_DEBUG); } }
function profile_change() { $a = get_app(); if (!local_user()) { return; } // $url = $a->get_baseurl() . '/profile/' . $a->user['nickname']; // if($url && strlen(get_config('system','directory_submit_url'))) // proc_run('php',"include/directory.php","$url"); $recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s'\n\t\tAND `uid` = %d AND `rel` != %d ", dbesc(NETWORK_DIASPORA), intval(local_user()), intval(CONTACT_IS_SHARING)); if (!count($recips)) { return; } $r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.* FROM `profile`\n\t\tINNER JOIN `user` ON `profile`.`uid` = `user`.`uid`\n\t\tWHERE `user`.`uid` = %d AND `profile`.`is-default` = 1 LIMIT 1", intval(local_user())); if (!count($r)) { return; } $profile = $r[0]; $handle = xmlify($a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3)); $first = xmlify(strpos($profile['name'], ' ') ? trim(substr($profile['name'], 0, strpos($profile['name'], ' '))) : $profile['name']); $last = xmlify($first === $profile['name'] ? '' : trim(substr($profile['name'], strlen($first)))); $large = xmlify($a->get_baseurl() . '/photo/custom/300/' . $profile['uid'] . '.jpg'); $medium = xmlify($a->get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg'); $small = xmlify($a->get_baseurl() . '/photo/custom/50/' . $profile['uid'] . '.jpg'); $searchable = xmlify($profile['publish'] && $profile['net-publish'] ? 'true' : 'false'); // $searchable = 'true'; if ($searchable === 'true') { $dob = '1000-00-00'; if ($profile['dob'] && $profile['dob'] != '0000-00-00') { $dob = (intval($profile['dob']) ? intval($profile['dob']) : '1000') . '-' . datetime_convert('UTC', 'UTC', $profile['dob'], 'm-d'); } $gender = xmlify($profile['gender']); $about = xmlify($profile['about']); require_once 'include/bbcode.php'; $about = xmlify(strip_tags(bbcode($about))); $location = ''; if ($profile['locality']) { $location .= $profile['locality']; } if ($profile['region']) { if ($location) { $location .= ', '; } $location .= $profile['region']; } if ($profile['country-name']) { if ($location) { $location .= ', '; } $location .= $profile['country-name']; } $location = xmlify($location); $tags = ''; if ($profile['pub_keywords']) { $kw = str_replace(',', ' ', $profile['pub_keywords']); $kw = str_replace(' ', ' ', $kw); $arr = explode(' ', $profile['pub_keywords']); if (count($arr)) { for ($x = 0; $x < 5; $x++) { if (trim($arr[$x])) { $tags .= '#' . trim($arr[$x]) . ' '; } } } } $tags = xmlify(trim($tags)); } $tpl = get_markup_template('diaspora_profile.tpl'); $msg = replace_macros($tpl, array('$handle' => $handle, '$first' => $first, '$last' => $last, '$large' => $large, '$medium' => $medium, '$small' => $small, '$dob' => $dob, '$gender' => $gender, '$about' => $about, '$location' => $location, '$searchable' => $searchable, '$tags' => $tags)); logger('profile_change: ' . $msg, LOGGER_ALL); foreach ($recips as $recip) { $msgtosend = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg, $a->user, $recip, $a->user['prvkey'], $recip['pubkey'], false))); add_to_queue($recip['id'], NETWORK_DIASPORA, $msgtosend, false); } }
function gnusoc_remote_follow($channel, $xchan) { $slap = replace_macros(get_markup_template('follow_slap.tpl', 'addon/gnusoc/'), array('$name' => xmlify($channel['channel_name']), '$nick' => xmlify($channel['channel_address']), '$profile_page' => xmlify(z_root() . '/channel/' . $channel['channel_address']), '$thumb' => xmlify($channel['xchan_photo_l']), '$item_id' => z_root() . '/display/' . xmlify(random_string()), '$title' => xmlify(t('Follow')), '$published' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME), '$type' => 'html', '$content' => xmlify(sprintf(t('%1$s is now following %2$s'), $channel['channel_name'], $xchan['xchan_name'])), '$remote_profile' => xmlify($xchan['xchan_url']), '$remote_photo' => xmlify($xchan['xchan_photo_l']), '$remote_thumb' => xmlify($xchan['xchan_photo_m']), '$remote_nick' => xmlify(substr($xchan['xchan_addr'], 0, strpos($xchan['xchan_addr'], '@'))), '$remote_name' => xmlify($xchan['xchan_name']), '$verb' => xmlify(ACTIVITY_FOLLOW), '$ostat_follow' => '')); logger('follow xml: ' . $slap, LOGGER_DATA); $deliver = ''; $y = q("select * from hubloc where hubloc_hash = '%s'", dbesc($xchan['xchan_hash'])); if ($y) { $deliver = slapper($channel, $y[0]['hubloc_callback'], $slap); } return $deliver; }
function atom_entry($item, $type, $author, $owner, $comment = false, $cid = 0) { if (!$item['parent']) { return; } if ($item['deleted']) { return '<at:deleted-entry ref="' . xmlify($item['mid']) . '" when="' . xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', ATOM_TIME)) . '" />' . "\r\n"; } create_export_photo_body($item); if ($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) { $body = fix_private_photos($item['body'], $owner['uid'], $item, $cid); } else { $body = $item['body']; } $o = "\r\n\r\n<entry>\r\n"; if (is_array($author)) { $o .= atom_author('author', $author['xchan_name'], $author['xchan_url'], 80, 80, $author['xchan_photo_mimetype'], $author['xchan_photo_m']); } else { $o .= atom_author('author', $item['author']['xchan_name'], $item['author']['xchan_url'], 80, 80, $item['author']['xchan_photo_mimetype'], $item['author']['xchan_photo_m']); } $o .= atom_author('zot:owner', $item['owner']['xchan_name'], $item['owner']['xchan_url'], 80, 80, $item['owner']['xchan_photo_mimetype'], $item['owner']['xchan_photo_m']); if ($item['parent'] != $item['id'] || $item['parent_mid'] !== $item['mid'] || $item['thr_parent'] !== '' && $item['thr_parent'] !== $item['mid']) { $parent_item = $item['thr_parent'] ? $item['thr_parent'] : $item['parent_mid']; $o .= '<thr:in-reply-to ref="' . z_root() . '/display/' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n"; } if (activity_match($item['obj_type'], ACTIVITY_OBJ_EVENT) && activity_match($item['verb'], ACTIVITY_POST)) { $obj = is_array($item['obj']) ? $item['obj'] : json_decode($item['obj'], true); $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n"; $o .= '<summary xmlns="urn:ietf:params:xml:ns:xcal">' . xmlify(bbcode($obj['title'])) . '</summary>' . "\r\n"; $o .= '<dtstart xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC', 'UTC', $obj['dtstart'], 'Ymd\\THis' . ($obj['adjust'] ? '\\Z' : '')) . '</dtstart>' . "\r\n"; $o .= '<dtend xmlns="urn:ietf:params:xml:ns:xcal">' . datetime_convert('UTC', 'UTC', $obj['dtend'], 'Ymd\\THis' . ($obj['adjust'] ? '\\Z' : '')) . '</dtend>' . "\r\n"; $o .= '<location xmlns="urn:ietf:params:xml:ns:xcal">' . xmlify(bbcode($obj['location'])) . '</location>' . "\r\n"; $o .= '<content type="' . $type . '" >' . xmlify(bbcode($obj['description'])) . '</content>' . "\r\n"; } else { $o .= '<title>' . xmlify($item['title']) . '</title>' . "\r\n"; $o .= '<content type="' . $type . '" >' . xmlify(prepare_text($body, $item['mimetype'])) . '</content>' . "\r\n"; } $o .= '<id>' . z_root() . '/display/' . xmlify($item['mid']) . '</id>' . "\r\n"; $o .= '<published>' . xmlify(datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', ATOM_TIME)) . '</published>' . "\r\n"; $o .= '<updated>' . xmlify(datetime_convert('UTC', 'UTC', $item['edited'] . '+00:00', ATOM_TIME)) . '</updated>' . "\r\n"; $o .= '<link rel="alternate" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n"; if ($item['location']) { $o .= '<zot:location>' . xmlify($item['location']) . '</zot:location>' . "\r\n"; $o .= '<poco:address><poco:formatted>' . xmlify($item['location']) . '</poco:formatted></poco:address>' . "\r\n"; } if ($item['coord']) { $o .= '<georss:point>' . xmlify($item['coord']) . '</georss:point>' . "\r\n"; } if ($item['item_private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) { $o .= '<zot:private>' . ($item['item_private'] ? $item['item_private'] : 1) . '</zot:private>' . "\r\n"; } if ($item['app']) { $o .= '<statusnet:notice_info local_id="' . $item['id'] . '" source="' . xmlify($item['app']) . '" ></statusnet:notice_info>' . "\r\n"; } $verb = construct_verb($item); $o .= '<as:verb>' . xmlify($verb) . '</as:verb>' . "\r\n"; $actobj = construct_activity_object($item); if (strlen($actobj)) { $o .= $actobj; } $actarg = construct_activity_target($item); if (strlen($actarg)) { $o .= $actarg; } // FIXME // $tags = item_getfeedtags($item); // if(count($tags)) { // foreach($tags as $t) { // $o .= '<category scheme="X-DFRN:' . xmlify($t[0]) . ':' . xmlify($t[1]) . '" term="' . xmlify($t[2]) . '" />' . "\r\n"; // } // } // FIXME // $o .= item_getfeedattach($item); // $mentioned = get_mentions($item,$tags); // if($mentioned) // $o .= $mentioned; call_hooks('atom_entry', $o); $o .= '</entry>' . "\r\n"; return $o; }