function gprobe_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 'include/session.php'; require_once 'include/datetime.php'; load_config('config'); load_config('system'); $a->set_baseurl(get_config('system', 'url')); load_hooks(); if ($argc != 2) { return; } $url = hex2bin($argv[1]); $r = q("select * from gcontact where nurl = '%s' limit 1", dbesc(normalise_link($url))); if (!count($r)) { $arr = probe_url($url); if (count($arr) && x($arr, 'network') && $arr['network'] === NETWORK_DFRN) { q("insert into `gcontact` (`name`,`url`,`nurl`,`photo`)\n\t\t\t\tvalues ( '%s', '%s', '%s', '%s') ", dbesc($arr['name']), dbesc($arr['url']), dbesc(normalise_link($arr['url'])), dbesc($arr['photo'])); } $r = q("select * from gcontact where nurl = '%s' limit 1", dbesc(normalise_link($url))); } if (count($r)) { poco_load(0, 0, $r[0]['id'], str_replace('/profile/', '/poco/', $r[0]['url'])); } return; }
function create_user($arr) { // Required: { username, nickname, email } or { openid_url } $a = get_app(); $result = array('success' => false, 'user' => null, 'password' => '', 'message' => ''); $using_invites = get_config('system', 'invitation_only'); $num_invites = get_config('system', 'number_invites'); $invite_id = x($arr, 'invite_id') ? notags(trim($arr['invite_id'])) : ''; $username = x($arr, 'username') ? notags(trim($arr['username'])) : ''; $nickname = x($arr, 'nickname') ? notags(trim($arr['nickname'])) : ''; $email = x($arr, 'email') ? notags(trim($arr['email'])) : ''; $openid_url = x($arr, 'openid_url') ? notags(trim($arr['openid_url'])) : ''; $photo = x($arr, 'photo') ? notags(trim($arr['photo'])) : ''; $password = x($arr, 'password') ? trim($arr['password']) : ''; $blocked = x($arr, 'blocked') ? intval($arr['blocked']) : 0; $verified = x($arr, 'verified') ? intval($arr['verified']) : 0; $publish = x($arr, 'profile_publish_reg') && intval($arr['profile_publish_reg']) ? 1 : 0; $netpublish = strlen(get_config('system', 'directory_submit_url')) ? $publish : 0; $tmp_str = $openid_url; if ($using_invites) { if (!$invite_id) { $result['message'] .= t('An invitation is required.') . EOL; return $result; } $r = q("select * from register where `hash` = '%s' limit 1", dbesc($invite_id)); if (!results($r)) { $result['message'] .= t('Invitation could not be verified.') . EOL; return $result; } } if (!x($username) || !x($email) || !x($nickname)) { if ($openid_url) { if (!validate_url($tmp_str)) { $result['message'] .= t('Invalid OpenID url') . EOL; return $result; } $_SESSION['register'] = 1; $_SESSION['openid'] = $openid_url; require_once 'library/openid.php'; $openid = new LightOpenID(); $openid->identity = $openid_url; $openid->returnUrl = $a->get_baseurl() . '/openid'; $openid->required = array('namePerson/friendly', 'contact/email', 'namePerson'); $openid->optional = array('namePerson/first', 'media/image/aspect11', 'media/image/default'); try { $authurl = $openid->authUrl(); } catch (Exception $e) { $result['message'] .= t("We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.") . EOL . EOL . t("The error message was:") . $e->getMessage() . EOL; return $result; } goaway($authurl); // NOTREACHED } notice(t('Please enter the required information.') . EOL); return; } if (!validate_url($tmp_str)) { $openid_url = ''; } $err = ''; // collapse multiple spaces in name $username = preg_replace('/ +/', ' ', $username); if (mb_strlen($username) > 48) { $result['message'] .= t('Please use a shorter name.') . EOL; } if (mb_strlen($username) < 3) { $result['message'] .= t('Name too short.') . EOL; } // I don't really like having this rule, but it cuts down // on the number of auto-registrations by Russian spammers // Using preg_match was completely unreliable, due to mixed UTF-8 regex support // $no_utf = get_config('system','no_utf'); // $pat = (($no_utf) ? '/^[a-zA-Z]* [a-zA-Z]*$/' : '/^\p{L}* \p{L}*$/u' ); // So now we are just looking for a space in the full name. $loose_reg = get_config('system', 'no_regfullname'); if (!$loose_reg) { $username = mb_convert_case($username, MB_CASE_TITLE, 'UTF-8'); if (!strpos($username, ' ')) { $result['message'] .= t("That doesn't appear to be your full (First Last) name.") . EOL; } } if (!allowed_email($email)) { $result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL; } if (!valid_email($email) || !validate_email($email)) { $result['message'] .= t('Not a valid email address.') . EOL; } // Disallow somebody creating an account using openid that uses the admin email address, // since openid bypasses email verification. We'll allow it if there is not yet an admin account. $adminlist = explode(",", str_replace(" ", "", strtolower($a->config['admin_email']))); //if((x($a->config,'admin_email')) && (strcasecmp($email,$a->config['admin_email']) == 0) && strlen($openid_url)) { if (x($a->config, 'admin_email') && in_array(strtolower($email), $adminlist) && strlen($openid_url)) { $r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1", dbesc($email)); if (count($r)) { $result['message'] .= t('Cannot use that email.') . EOL; } } $nickname = $arr['nickname'] = strtolower($nickname); if (!preg_match("/^[a-z][a-z0-9\\-\\_]*\$/", $nickname)) { $result['message'] .= t('Your "nickname" can only contain "a-z", "0-9", "-", and "_", and must also begin with a letter.') . EOL; } $r = q("SELECT `uid` FROM `user`\n \tWHERE `nickname` = '%s' LIMIT 1", dbesc($nickname)); if (count($r)) { $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL; } // Check deleted accounts that had this nickname. Doesn't matter to us, // but could be a security issue for federated platforms. $r = q("SELECT * FROM `userd`\n \tWHERE `username` = '%s' LIMIT 1", dbesc($nickname)); if (count($r)) { $result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL; } if (strlen($result['message'])) { return $result; } $new_password = strlen($password) ? $password : autoname(6) . mt_rand(100, 9999); $new_password_encoded = hash('whirlpool', $new_password); $result['password'] = $new_password; require_once 'include/crypto.php'; $keys = new_keypair(4096); if ($keys === false) { $result['message'] .= t('SERIOUS ERROR: Generation of security keys failed.') . EOL; return $result; } $default_service_class = get_config('system', 'default_service_class'); if (!$default_service_class) { $default_service_class = ''; } $prvkey = $keys['prvkey']; $pubkey = $keys['pubkey']; /** * * Create another keypair for signing/verifying * salmon protocol messages. We have to use a slightly * less robust key because this won't be using openssl * but the phpseclib. Since it is PHP interpreted code * it is not nearly as efficient, and the larger keys * will take several minutes each to process. * */ $sres = new_keypair(512); $sprvkey = $sres['prvkey']; $spubkey = $sres['pubkey']; $r = q("INSERT INTO `user` ( `guid`, `username`, `password`, `email`, `openid`, `nickname`,\n\t\t`pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked`, `timezone`, `service_class`, `default-location` )\n\t\tVALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, 'UTC', '%s', '' )", dbesc(generate_user_guid()), dbesc($username), dbesc($new_password_encoded), dbesc($email), dbesc($openid_url), dbesc($nickname), dbesc($pubkey), dbesc($prvkey), dbesc($spubkey), dbesc($sprvkey), dbesc(datetime_convert()), intval($verified), intval($blocked), dbesc($default_service_class)); if ($r) { $r = q("SELECT * FROM `user`\n\t\t\tWHERE `username` = '%s' AND `password` = '%s' LIMIT 1", dbesc($username), dbesc($new_password_encoded)); if ($r !== false && count($r)) { $u = $r[0]; $newuid = intval($r[0]['uid']); } } else { $result['message'] .= t('An error occurred during registration. Please try again.') . EOL; return $result; } /** * if somebody clicked submit twice very quickly, they could end up with two accounts * due to race condition. Remove this one. */ $r = q("SELECT `uid` FROM `user`\n \tWHERE `nickname` = '%s' ", dbesc($nickname)); if (count($r) > 1 && $newuid) { $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL; q("DELETE FROM `user` WHERE `uid` = %d", intval($newuid)); return $result; } if (x($newuid) !== false) { $r = q("INSERT INTO `profile` ( `uid`, `profile-name`, `is-default`, `name`, `photo`, `thumb`, `publish`, `net-publish` )\n\t\t\tVALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, %d ) ", intval($newuid), t('default'), 1, dbesc($username), dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"), dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"), intval($publish), intval($netpublish)); if ($r === false) { $result['message'] .= t('An error occurred creating your default profile. Please try again.') . EOL; // Start fresh next time. $r = q("DELETE FROM `user` WHERE `uid` = %d", intval($newuid)); return $result; } $r = q("INSERT INTO `contact` ( `uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,\n\t\t\t`request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness` )\n\t\t\tVALUES ( %d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0 ) ", intval($newuid), datetime_convert(), dbesc($username), dbesc($nickname), dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"), dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"), dbesc($a->get_baseurl() . "/photo/micro/{$newuid}.jpg"), dbesc($a->get_baseurl() . "/profile/{$nickname}"), dbesc(normalise_link($a->get_baseurl() . "/profile/{$nickname}")), dbesc($a->get_baseurl() . "/dfrn_request/{$nickname}"), dbesc($a->get_baseurl() . "/dfrn_notify/{$nickname}"), dbesc($a->get_baseurl() . "/dfrn_poll/{$nickname}"), dbesc($a->get_baseurl() . "/dfrn_confirm/{$nickname}"), dbesc($a->get_baseurl() . "/poco/{$nickname}"), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert())); // Create a group with no members. This allows somebody to use it // right away as a default group for new contacts. require_once 'include/group.php'; group_add($newuid, t('Friends')); $r = q("SELECT id FROM `group` WHERE uid = %d AND name = '%s'", intval($newuid), dbesc(t('Friends'))); if ($r && count($r)) { $def_gid = $r[0]['id']; q("UPDATE user SET def_gid = %d WHERE uid = %d", intval($r[0]['id']), intval($newuid)); } if (get_config('system', 'newuser_private') && $def_gid) { q("UPDATE user SET allow_gid = '%s' WHERE uid = %d", dbesc("<" . $def_gid . ">"), intval($newuid)); } } // if we have no OpenID photo try to look up an avatar if (!strlen($photo)) { $photo = avatar_img($email); } // unless there is no avatar-plugin loaded if (strlen($photo)) { require_once 'include/Photo.php'; $photo_failure = false; $filename = basename($photo); $img_str = fetch_url($photo, true); // guess mimetype from headers or filename $type = guess_image_type($photo, true); $img = new Photo($img_str, $type); if ($img->is_valid()) { $img->scaleImageSquare(175); $hash = photo_new_resource(); $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4); if ($r === false) { $photo_failure = true; } $img->scaleImage(80); $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5); if ($r === false) { $photo_failure = true; } $img->scaleImage(48); $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6); if ($r === false) { $photo_failure = true; } if (!$photo_failure) { q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ", dbesc($hash)); } } } call_hooks('register_account', $newuid); $result['success'] = true; $result['user'] = $u; return $result; }
function follow_content(&$a) { if (!local_user()) { notice(t('Permission denied.') . EOL); goaway($_SESSION['return_url']); // NOTREACHED } $uid = local_user(); $url = notags(trim($_REQUEST['url'])); $r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND\n\t\t(`nurl` = '%s' OR `alias` = '%s' OR `alias` = '%s') AND\n\t\t`network` != '%s' LIMIT 1", intval(local_user()), dbesc(normalise_link($url)), dbesc(normalise_link($url)), dbesc($url), dbesc(NETWORK_STATUSNET)); if ($r) { notice(t('You already added this contact.') . EOL); goaway($_SESSION['return_url']); // NOTREACHED } $ret = probe_url($url); if ($ret['network'] === NETWORK_DFRN) { $request = $ret["request"]; $tpl = get_markup_template('dfrn_request.tpl'); } else { $request = $a->get_baseurl() . "/follow"; $tpl = get_markup_template('auto_request.tpl'); } $r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($uid)); if (!$r) { notice(t('Permission denied.') . EOL); goaway($_SESSION['return_url']); // NOTREACHED } $myaddr = $r[0]["url"]; // Makes the connection request for friendica contacts easier $_SESSION["fastlane"] = $ret["url"]; $o = replace_macros($tpl, array('$header' => $ret["name"] . " (" . $ret["addr"] . ")", '$photo' => $ret["photo"], '$desc' => "", '$pls_answer' => t('Please answer the following:'), '$does_know_you' => array('knowyou', sprintf(t('Does %s know you?'), $ret["name"]), false, '', array(t('No'), t('Yes'))), '$add_note' => t('Add a personal note:'), '$page_desc' => "", '$friendica' => "", '$statusnet' => "", '$diaspora' => "", '$diasnote' => "", '$your_address' => t('Your Identity Address:'), '$invite_desc' => "", '$emailnet' => "", '$submit' => t('Submit Request'), '$cancel' => t('Cancel'), '$nickname' => "", '$name' => $ret["name"], '$url' => $ret["url"], '$myaddr' => $myaddr, '$request' => $request)); return $o; }
/** * @brief Controller for /match. * * It takes keywords from your profile and queries the directory server for * matching keywords from other profiles. * * @param App &$a * @return void|string */ function match_content(&$a) { $o = ''; if (!local_user()) { return; } $a->page['aside'] .= findpeople_widget(); $a->page['aside'] .= follow_widget(); $_SESSION['return_url'] = $a->get_baseurl() . '/' . $a->cmd; $r = q("SELECT `pub_keywords`, `prv_keywords` FROM `profile` WHERE `is-default` = 1 AND `uid` = %d LIMIT 1", intval(local_user())); if (!count($r)) { return; } if (!$r[0]['pub_keywords'] && !$r[0]['prv_keywords']) { notice(t('No keywords to match. Please add keywords to your default profile.') . EOL); return; } $params = array(); $tags = trim($r[0]['pub_keywords'] . ' ' . $r[0]['prv_keywords']); if ($tags) { $params['s'] = $tags; if ($a->pager['page'] != 1) { $params['p'] = $a->pager['page']; } if (strlen(get_config('system', 'directory'))) { $x = post_url(get_server() . '/msearch', $params); } else { $x = post_url($a->get_baseurl() . '/msearch', $params); } $j = json_decode($x); if ($j->total) { $a->set_pager_total($j->total); $a->set_pager_itemspage($j->items_page); } if (count($j->results)) { $id = 0; foreach ($j->results as $jj) { $match_nurl = normalise_link($jj->url); $match = q("SELECT `nurl` FROM `contact` WHERE `uid` = '%d' AND nurl='%s' LIMIT 1", intval(local_user()), dbesc($match_nurl)); if (!count($match)) { $jj->photo = str_replace("http:///photo/", get_server() . "/photo/", $jj->photo); $connlnk = $a->get_baseurl() . '/follow/?url=' . $jj->url; $photo_menu = array(array(t("View Profile"), zrl($jj->url))); $photo_menu[] = array(t("Connect/Follow"), $connlnk); $contact_details = get_contact_details_by_url($jj->url, local_user()); $entry = array('url' => zrl($jj->url), 'itemurl' => $contact_details['addr'] != "" ? $contact_details['addr'] : $jj->url, 'name' => $jj->name, 'details' => $contact_details['location'], 'tags' => $contact_details['keywords'], 'about' => $contact_details['about'], 'account_type' => $contact_details['community'] ? t('Forum') : '', 'thumb' => proxy_url($jj->photo, false, PROXY_SIZE_THUMB), 'inttxt' => ' ' . t('is interested in:'), 'conntxt' => t('Connect'), 'connlnk' => $connlnk, 'img_hover' => $jj->tags, 'photo_menu' => $photo_menu, 'id' => ++$id); $entries[] = $entry; } } $tpl = get_markup_template('viewcontact_template.tpl'); $o .= replace_macros($tpl, array('$title' => t('Profile Match'), '$contacts' => $entries, '$paginate' => paginate($a))); } else { info(t('No matches') . EOL); } } return $o; }
function auto_redir(&$a, $contact_nick) { // prevent looping if (x($_REQUEST, 'redir') && intval($_REQUEST['redir'])) { return; } if (!$contact_nick || $contact_nick === $a->user['nickname']) { return; } if (local_user()) { // We need to find out if $contact_nick is a user on this hub, and if so, if I // am a contact of that user. However, that user may have other contacts with the // same nickname as me on other hubs or other networks. Exclude these by requiring // that the contact have a local URL. I will be the only person with my nickname at // this URL, so if a result is found, then I am a contact of the $contact_nick user. // // We also have to make sure that I'm a legitimate contact--I'm not blocked or pending. $baseurl = $a->get_baseurl(); $domain_st = strpos($baseurl, "://"); if ($domain_st === false) { return; } $baseurl = substr($baseurl, $domain_st + 3); $nurl = normalise_link($baseurl); $r = q("SELECT id FROM contact WHERE uid = ( SELECT uid FROM user WHERE nickname = '%s' LIMIT 1 )\n\t\t AND nick = '%s' AND self = 0 AND ( url LIKE '%%%s%%' or nurl LIKE '%%%s%%' ) AND blocked = 0 AND pending = 0 LIMIT 1", dbesc($contact_nick), dbesc($a->user['nickname']), dbesc($baseurl), dbesc($nurl)); if (!$r || !count($r) || $r[0]['id'] == remote_user()) { return; } $r = q("SELECT * FROM contact WHERE nick = '%s'\n\t\t AND network = '%s' AND uid = %d AND url LIKE '%%%s%%' LIMIT 1", dbesc($contact_nick), dbesc(NETWORK_DFRN), intval(local_user()), dbesc($baseurl)); if (!($r && count($r))) { return; } $cid = $r[0]['id']; $dfrn_id = $orig_id = $r[0]['issued-id'] ? $r[0]['issued-id'] : $r[0]['dfrn-id']; if ($r[0]['duplex'] && $r[0]['issued-id']) { $orig_id = $r[0]['issued-id']; $dfrn_id = '1:' . $orig_id; } if ($r[0]['duplex'] && $r[0]['dfrn-id']) { $orig_id = $r[0]['dfrn-id']; $dfrn_id = '0:' . $orig_id; } // ensure that we've got a valid ID. There may be some edge cases with forums and non-duplex mode // that may have triggered some of the "went to {profile/intro} and got an RSS feed" issues if (strlen($dfrn_id) < 3) { return; } $sec = random_string(); q("INSERT INTO `profile_check` ( `uid`, `cid`, `dfrn_id`, `sec`, `expire`)\n\t\t\tVALUES( %d, %s, '%s', '%s', %d )", intval(local_user()), intval($cid), dbesc($dfrn_id), dbesc($sec), intval(time() + 45)); $url = curPageURL(); logger('auto_redir: ' . $r[0]['name'] . ' ' . $sec, LOGGER_DEBUG); $dest = $url ? '&destination_url=' . $url : ''; goaway($r[0]['poll'] . '?dfrn_id=' . $dfrn_id . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . '&type=profile&sec=' . $sec . $dest); } return; }
/** * @param $url string * @return boolean */ function privacy_image_cache_is_local_image($url) { if ($url[0] == '/') { return true; } // links normalised - bug #431 $baseurl = normalise_link(get_app()->get_baseurl()); $url = normalise_link($url); return substr($url, 0, strlen($baseurl)) == $baseurl; }
function match_content(&$a) { $o = ''; if (!local_user()) { return; } $a->page['aside'] .= follow_widget(); $a->page['aside'] .= findpeople_widget(); $_SESSION['return_url'] = $a->get_baseurl() . '/' . $a->cmd; $o .= replace_macros(get_markup_template("section_title.tpl"), array('$title' => t('Profile Match'))); $r = q("SELECT `pub_keywords`, `prv_keywords` FROM `profile` WHERE `is-default` = 1 AND `uid` = %d LIMIT 1", intval(local_user())); if (!count($r)) { return; } if (!$r[0]['pub_keywords'] && !$r[0]['prv_keywords']) { notice(t('No keywords to match. Please add keywords to your default profile.') . EOL); return; } $params = array(); $tags = trim($r[0]['pub_keywords'] . ' ' . $r[0]['prv_keywords']); if ($tags) { $params['s'] = $tags; if ($a->pager['page'] != 1) { $params['p'] = $a->pager['page']; } if (strlen(get_config('system', 'directory'))) { $x = post_url(get_server() . '/msearch', $params); } else { $x = post_url($a->get_baseurl() . '/msearch', $params); } $j = json_decode($x); if ($j->total) { $a->set_pager_total($j->total); $a->set_pager_itemspage($j->items_page); } if (count($j->results)) { $tpl = get_markup_template('match.tpl'); foreach ($j->results as $jj) { $match_nurl = normalise_link($jj->url); $match = q("SELECT `nurl` FROM `contact` WHERE `uid` = '%d' AND nurl='%s' LIMIT 1", intval(local_user()), dbesc($match_nurl)); if (!count($match)) { $jj->photo = str_replace("http:///photo/", get_server() . "/photo/", $jj->photo); $connlnk = $a->get_baseurl() . '/follow/?url=' . $jj->url; $o .= replace_macros($tpl, array('$url' => zrl($jj->url), '$name' => $jj->name, '$photo' => proxy_url($jj->photo), '$inttxt' => ' ' . t('is interested in:'), '$conntxt' => t('Connect'), '$connlnk' => $connlnk, '$tags' => $jj->tags)); } } } else { info(t('No matches') . EOL); } } $o .= cleardiv(); $o .= paginate($a); return $o; }
function update_threads_mention() { $a = get_app(); $users = q("SELECT `uid`, `nickname` FROM `user` ORDER BY `uid`"); foreach ($users as $user) { $self = normalise_link($a->get_baseurl() . '/profile/' . $user['nickname']); $selfhttps = str_replace("http://", "https://", $self); $parents = q("SELECT DISTINCT(`parent`) FROM `item` WHERE `uid` = %d AND\n\t\t\t\t((`owner-link` IN ('%s', '%s')) OR (`author-link` IN ('%s', '%s')))", $user["uid"], $self, $selfhttps, $self, $selfhttps); foreach ($parents as $parent) { q("UPDATE `thread` SET `mention` = 1 WHERE `iid` = %d", $parent["parent"]); } } }
function gprobe_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'; load_config('config'); load_config('system'); $a->set_baseurl(get_config('system', 'url')); load_hooks(); if ($argc != 2) { return; } $url = hex2bin($argv[1]); $r = q("select * from gcontact where nurl = '%s' limit 1", dbesc(normalise_link($url))); logger("gprobe start for " . normalise_link($url), LOGGER_DEBUG); if (!count($r)) { // Is it a DDoS attempt? $urlparts = parse_url($url); $result = Cache::get("gprobe:" . $urlparts["host"]); if (!is_null($result)) { $result = unserialize($result); if ($result["network"] == NETWORK_FEED) { logger("DDoS attempt detected for " . $urlparts["host"] . " by " . $_SERVER["REMOTE_ADDR"] . ". server data: " . print_r($_SERVER, true), LOGGER_DEBUG); return; } } $arr = probe_url($url); if (is_null($result)) { Cache::set("gprobe:" . $urlparts["host"], serialize($arr)); } if (count($arr) && x($arr, 'network') && $arr['network'] === NETWORK_DFRN) { q("insert into `gcontact` (`name`,`url`,`nurl`,`photo`)\n\t\t\t\tvalues ( '%s', '%s', '%s', '%s') ", dbesc($arr['name']), dbesc($arr['url']), dbesc(normalise_link($arr['url'])), dbesc($arr['photo'])); } $r = q("select * from gcontact where nurl = '%s' limit 1", dbesc(normalise_link($url))); } if (count($r)) { poco_load(0, 0, $r[0]['id'], str_replace('/profile/', '/poco/', $r[0]['url'])); } logger("gprobe end for " . normalise_link($url), LOGGER_DEBUG); return; }
function bookmarklet_content(&$a) { if (!local_user()) { $o = '<h2>' . t('Login') . '</h2>'; $o .= login($a->config['register_policy'] == REGISTER_CLOSED ? false : true); return $o; } $referer = normalise_link($_SERVER["HTTP_REFERER"]); $page = normalise_link($a->get_baseurl() . "/bookmarklet"); if (!strstr($referer, $page)) { $content = add_page_info($_REQUEST["url"]); $x = array('is_owner' => true, 'allow_location' => $a->user['allow_location'], 'default_location' => $a->user['default-location'], 'nickname' => $a->user['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', 'default_perms' => get_acl_permissions($a->user), 'acl' => populate_acl($a->user, true), 'bang' => '', 'visitor' => 'block', 'profile_uid' => local_user(), 'acl_data' => construct_acl_data($a, $a->user), 'title' => trim($_REQUEST["title"], "*"), 'content' => $content); $o = status_editor($a, $x, 0, false); $o .= "<script>window.resizeTo(800,550);</script>"; } else { $o = '<h2>' . t('The post was created') . '</h2>'; $o .= "<script>window.close()</script>"; } return $o; }
function crepair_post(&$a) { if (!local_user()) { return; } $cid = $a->argc > 1 ? intval($a->argv[1]) : 0; if ($cid) { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($cid), intval(local_user())); } if (!count($r)) { return; } $contact = $r[0]; $name = x($_POST, 'name') ? $_POST['name'] : $contact['name']; $nick = x($_POST, 'nick') ? $_POST['nick'] : ''; $url = x($_POST, 'url') ? $_POST['url'] : ''; $request = x($_POST, 'request') ? $_POST['request'] : ''; $confirm = x($_POST, 'confirm') ? $_POST['confirm'] : ''; $notify = x($_POST, 'notify') ? $_POST['notify'] : ''; $poll = x($_POST, 'poll') ? $_POST['poll'] : ''; $attag = x($_POST, 'attag') ? $_POST['attag'] : ''; $photo = x($_POST, 'photo') ? $_POST['photo'] : ''; $remote_self = x($_POST, 'remote_self') ? $_POST['remote_self'] : false; $nurl = normalise_link($url); $r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `url` = '%s', `nurl` = '%s', `request` = '%s', `confirm` = '%s', `notify` = '%s', `poll` = '%s', `attag` = '%s' , `remote_self` = %d\n\t\tWHERE `id` = %d AND `uid` = %d", dbesc($name), dbesc($nick), dbesc($url), dbesc($nurl), dbesc($request), dbesc($confirm), dbesc($notify), dbesc($poll), dbesc($attag), intval($remote_self), intval($contact['id']), local_user()); if ($photo) { logger('mod-crepair: updating photo from ' . $photo); require_once "include/Photo.php"; $photos = import_profile_photo($photo, local_user(), $contact['id']); $x = q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s'\n\t\t\tWHERE `id` = %d\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact['id'])); } if ($r) { info(t('Contact settings applied.') . EOL); } else { notice(t('Contact update failed.') . EOL); } return; }
function bb_ShareAttributes($share, $simplehtml) { $attributes = $share[2]; $author = ""; preg_match("/author='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") { $author = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'); } preg_match('/author="(.*?)"/ism', $attributes, $matches); if ($matches[1] != "") { $author = $matches[1]; } $profile = ""; preg_match("/profile='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") { $profile = $matches[1]; } preg_match('/profile="(.*?)"/ism', $attributes, $matches); if ($matches[1] != "") { $profile = $matches[1]; } $avatar = ""; preg_match("/avatar='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") { $avatar = $matches[1]; } preg_match('/avatar="(.*?)"/ism', $attributes, $matches); if ($matches[1] != "") { $avatar = $matches[1]; } $link = ""; preg_match("/link='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") { $link = $matches[1]; } preg_match('/link="(.*?)"/ism', $attributes, $matches); if ($matches[1] != "") { $link = $matches[1]; } $posted = ""; $itemcache = get_itemcachepath(); // relative dates only make sense when they aren't cached if ($itemcache == "") { preg_match("/posted='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") { $posted = $matches[1]; } preg_match('/posted="(.*?)"/ism', $attributes, $matches); if ($matches[1] != "") { $posted = $matches[1]; } $reldate = $posted ? " " . relative_date($posted) : ''; } $userid = GetProfileUsername($profile, $author, false); $userid_compact = GetProfileUsername($profile, $author, true); $preshare = trim($share[1]); if ($preshare != "") { $preshare .= "<br /><br />"; } switch ($simplehtml) { case 1: $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' <a href="' . $profile . '">' . $userid . "</a>: <br />»" . $share[3] . "«"; break; case 2: $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' ' . $userid_compact . ": <br />" . $share[3]; break; case 3: // Diaspora $headline .= '<b>' . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . $userid . ':</b><br />'; $text = trim($share[1]); if ($text != "") { $text .= "<hr />"; } if (substr(normalise_link($link), 0, 19) != "http://twitter.com/") { $text .= $headline . '<blockquote>' . trim($share[3]) . "</blockquote><br />"; if ($link != "") { $text .= '<br /><a href="' . $link . '">[l]</a>'; } } else { $text .= '<br /><a href="' . $link . '">' . $link . '</a>'; } break; case 4: $headline = '<div class="shared_header">'; $headline .= '<span><b>' . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8'); $headline .= sprintf(t('<a href="%1$s" target="_blank">%2$s</a> %3$s'), $link, $userid, $posted); $headline .= ":</b></span></div>"; $text = trim($share[1]); if ($text != "") { $text .= "<hr />"; } $text .= $headline . '<blockquote class="shared_content">' . trim($share[3]) . "</blockquote><br />"; break; case 5: $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' ' . $userid_compact . ": <br />" . $share[3]; break; case 6: // app.net $text = $preshare . ">> @" . $userid_compact . ": <br />" . $share[3]; break; case 7: // statusnet/GNU Social $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . " @" . $userid_compact . ": " . $share[3]; break; case 8: // twitter $text = $preshare . "RT @" . $userid_compact . ": " . $share[3]; break; case 9: // Google+/Facebook $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' ' . $userid_compact . ": <br />" . $share[3]; if ($link != "") { $text .= "<br /><br />" . $link; } break; default: $headline = trim($share[1]) . '<div class="shared_header">'; if ($avatar != "") { $headline .= '<img src="' . proxy_url($avatar, false, PROXY_SIZE_MICRO) . '" height="32" width="32" >'; } $headline .= sprintf(t('<span><a href="%s" target="_blank">%s</a> wrote the following <a href="%s" target="_blank">post</a>' . $reldate . ':</span>'), $profile, $author, $link); $headline .= "</div>"; $text = $headline . '<blockquote class="shared_content">' . trim($share[3]) . "</blockquote>"; break; } return $text; }
function api_get_nick($profile) { /* To-Do: - remove trailing jung from profile url - pump.io check has to check the website */ $nick = ""; $friendica = preg_replace("=https?://(.*)/profile/(.*)=ism", "\$2", $profile); if ($friendica != $profile) { $nick = $friendica; } if (!$nick == "") { $diaspora = preg_replace("=https?://(.*)/u/(.*)=ism", "\$2", $profile); if ($diaspora != $profile) { $nick = $diaspora; } } if (!$nick == "") { $twitter = preg_replace("=https?://twitter.com/(.*)=ism", "\$1", $profile); if ($twitter != $profile) { $nick = $twitter; } } if (!$nick == "") { $StatusnetHost = preg_replace("=https?://(.*)/user/(.*)=ism", "\$1", $profile); if ($StatusnetHost != $profile) { $StatusnetUser = preg_replace("=https?://(.*)/user/(.*)=ism", "\$2", $profile); if ($StatusnetUser != $profile) { $UserData = fetch_url("http://" . $StatusnetHost . "/api/users/show.json?user_id=" . $StatusnetUser); $user = json_decode($UserData); if ($user) { $nick = $user->screen_name; } } } } // To-Do: look at the page if its really a pumpio site //if (!$nick == "") { // $pumpio = preg_replace("=https?://(.*)/(.*)/=ism", "$2", $profile."/"); // if ($pumpio != $profile) // $nick = $pumpio; // <div class="media" id="profile-block" data-profile-id="acct:kabniel@microca.st"> //} if ($nick != "") { q("UPDATE unique_contacts SET nick = '%s' WHERE url = '%s'", dbesc($nick), dbesc(normalise_link($profile))); return $nick; } return false; }
function best_link_url($item, &$sparkle) { $a = get_app(); $best_url = ''; $sparkle = false; $clean_url = normalise_link($item['author-link']); if (local_user() && local_user() == $item['uid']) { if (isset($a->contacts) && x($a->contacts, $clean_url)) { if ($a->contacts[$clean_url]['network'] === NETWORK_DFRN) { $best_url = $a->get_baseurl() . '/redir/' . $a->contacts[$clean_url]['id']; $sparkle = true; } else { $best_url = $a->contacts[$clean_url]['url']; } } } if (!$best_url) { if (strlen($item['author-link'])) { $best_url = $item['author-link']; } else { $best_url = $item['url']; } } return $best_url; }
function check_htaccess(&$checks) { $a = get_app(); $status = true; $help = ""; if (function_exists('curl_init')) { $test = fetch_url($a->get_baseurl() . "/install/testrewrite"); if ($test != "ok") { $test = fetch_url(normalise_link($a->get_baseurl() . "/install/testrewrite")); } if ($test != "ok") { $status = false; $help = t('Url rewrite in .htaccess is not working. Check your server configuration.'); } check_add($checks, t('Url rewrite is working'), $status, true, $help); } else { // cannot check modrewrite if libcurl is not installed } }
/** * @brief Compare two URLs to see if they are the same. * * But ignore slight but hopefully insignificant differences such as if one * is https and the other isn't, or if one is www.something and the other * isn't - and also ignore case differences. * * @see normalis_link() * * @param string $a * @param string $b * @return true if the URLs match, otherwise false */ function link_compare($a, $b) { if (strcasecmp(normalise_link($a), normalise_link($b)) === 0) { return true; } return false; }
/** * @brief This function is called pre-deliver to see if a post matches the criteria to be tag delivered. * * We don't actually do anything except check that it matches the criteria. * This is so that the channel with tag_delivery enabled can receive the post even if they turn off * permissions for the sender to send their stream. tag_deliver() can't be called until the post is actually stored. * By then it would be too late to reject it. */ function tgroup_check($uid, $item) { $mention = false; // check that the message originated elsewhere and is a top-level post // or is a followup and we have already accepted the top level post as an uplink if ($item['mid'] != $item['parent_mid']) { $r = q("select id from item where mid = '%s' and uid = %d and ( item_flags & %d )>0 limit 1", dbesc($item['parent_mid']), intval($uid), intval(ITEM_UPLINK)); if ($r) { return true; } return false; } if (!perm_is_allowed($uid, $item['author_xchan'], 'tag_deliver')) { return false; } $u = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1", intval($uid)); if (!$u) { return false; } $terms = get_terms_oftype($item['term'], TERM_MENTION); if ($terms) { logger('tgroup_check: post mentions: ' . print_r($terms, true), LOGGER_DATA); } $link = normalise_link($u[0]['xchan_url']); if ($terms) { foreach ($terms as $term) { if (link_compare($term['url'], $link)) { $mention = true; break; } } } if ($mention) { logger('tgroup_check: mention found for ' . $u[0]['channel_name']); } else { return false; } // At this point we've determined that the person receiving this post was mentioned in it. // Now let's check if this mention was inside a reshare so we don't spam a forum // note: $term has been set to the matching term $body = $item['body']; if (array_key_exists('item_flags', $item) && $item['item_flags'] & ITEM_OBSCURED && $body) { $key = get_config('system', 'prvkey'); $body = crypto_unencapsulate(json_decode($body, true), $key); } $body = preg_replace('/\\[share(.*?)\\[\\/share\\]/', '', $body); // $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'] . '+','/') . '\[\/zrl\]/'; $pattern = '/@\\!?\\[zrl\\=([^\\]]*?)\\]((?:.(?!\\[zrl\\=))*?)\\+\\[\\/zrl\\]/'; $found = false; $matches = array(); if (preg_match_all($pattern, $body, $matches, PREG_SET_ORDER)) { $max_forums = get_config('system', 'max_tagged_forums'); if (!$max_forums) { $max_forums = 2; } $matched_forums = 0; foreach ($matches as $match) { $matched_forums++; if ($term['url'] === $match[1] && $term['term'] === $match[2]) { if ($matched_forums <= $max_forums) { $found = true; break; } logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); } } } if (!$found) { logger('tgroup_check: mention was in a reshare or exceeded max_tagged_forums - ignoring'); return false; } return true; }
function atom_author($tag, $name, $uri, $h, $w, $photo, $geo) { $o = ''; if (!$tag) { return $o; } $name = xmlify($name); $uri = xmlify($uri); $h = intval($h); $w = intval($w); $photo = xmlify($photo); $o .= "<{$tag}>\r\n"; $o .= "\t<name>{$name}</name>\r\n"; $o .= "\t<uri>{$uri}</uri>\r\n"; $o .= "\t" . '<link rel="photo" type="image/jpeg" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n"; $o .= "\t" . '<link rel="avatar" type="image/jpeg" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n"; if ($tag == "author") { if ($geo) { $o .= '<georss:point>' . xmlify($geo) . '</georss:point>' . "\r\n"; } $r = q("SELECT `profile`.`locality`, `profile`.`region`, `profile`.`country-name`,\n\t\t\t\t`profile`.`name`, `profile`.`pub_keywords`, `profile`.`about`,\n\t\t\t\t`profile`.`homepage`,`contact`.`nick` FROM `profile`\n\t\t\t\tINNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid`\n\t\t\t\tINNER JOIN `user` ON `user`.`uid` = `profile`.`uid`\n\t\t\t\tWHERE `profile`.`is-default` AND `contact`.`self` AND\n\t\t\t\t\tNOT `user`.`hidewall` AND `contact`.`nurl`='%s'", dbesc(normalise_link($uri))); if ($r) { $location = ''; if ($r[0]['locality']) { $location .= $r[0]['locality']; } if ($r[0]['region']) { if ($location) { $location .= ', '; } $location .= $r[0]['region']; } if ($r[0]['country-name']) { if ($location) { $location .= ', '; } $location .= $r[0]['country-name']; } $o .= "\t<poco:preferredUsername>" . xmlify($r[0]["nick"]) . "</poco:preferredUsername>\r\n"; $o .= "\t<poco:displayName>" . xmlify($r[0]["name"]) . "</poco:displayName>\r\n"; $o .= "\t<poco:note>" . xmlify(bbcode($r[0]["about"])) . "</poco:note>\r\n"; $o .= "\t<poco:address>\r\n"; $o .= "\t\t<poco:formatted>" . xmlify($location) . "</poco:formatted>\r\n"; $o .= "\t</poco:address>\r\n"; $o .= "\t<poco:urls>\r\n"; $o .= "\t<poco:type>homepage</poco:type>\r\n"; $o .= "\t\t<poco:value>" . xmlify($r[0]["homepage"]) . "</poco:value>\r\n"; $o .= "\t\t<poco:primary>true</poco:primary>\r\n"; $o .= "\t</poco:urls>\r\n"; } } call_hooks('atom_author', $o); $o .= "</{$tag}>\r\n"; return $o; }
function diaspora_fetch_relay() { $serverdata = get_config("system", "relay_server"); if ($serverdata == "") { return array(); } $relay = array(); $servers = explode(",", $serverdata); foreach ($servers as $server) { $server = trim($server); $batch = $server . "/receive/public"; $relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch)); if (!$relais) { $addr = "relay@" . str_replace("http://", "", normalise_link($server)); $r = q("INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`)\n\t\t\t\tVALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')", datetime_convert(), dbesc($addr), dbesc($addr), dbesc($server), dbesc(normalise_link($server)), dbesc($batch), dbesc(NETWORK_DIASPORA), intval(CONTACT_IS_FOLLOWER), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert())); $relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch)); if ($relais) { $relay[] = $relais[0]; } } else { $relay[] = $relais[0]; } } return $relay; }
function update_1100() { q("ALTER TABLE `contact` ADD `nurl` CHAR( 255 ) NOT NULL AFTER `url` "); q("alter table contact add index (`nurl`) "); require_once 'include/text.php'; $r = q("select id, url from contact where url != '' and nurl = '' "); if (count($r)) { foreach ($r as $rr) { q("update contact set nurl = '%s' where id = %d limit 1", dbesc(normalise_link($rr['url'])), intval($rr['id'])); } } }
function delegate_content(&$a) { if (!local_user()) { notice(t('Permission denied.') . EOL); return; } if ($a->argc > 2 && $a->argv[1] === 'add' && intval($a->argv[2])) { // delegated admins can view but not change delegation permissions if (x($_SESSION, 'submanage') && intval($_SESSION['submanage'])) { goaway($a->get_baseurl() . '/delegate'); } $id = $a->argv[2]; $r = q("select `nickname` from user where uid = %d limit 1", intval($id)); if (count($r)) { $r = q("select id from contact where uid = %d and nurl = '%s' limit 1", intval(local_user()), dbesc(normalise_link($a->get_baseurl() . '/profile/' . $r[0]['nickname']))); if (count($r)) { q("insert into manage ( uid, mid ) values ( %d , %d ) ", intval($a->argv[2]), intval(local_user())); } } goaway($a->get_baseurl() . '/delegate'); } if ($a->argc > 2 && $a->argv[1] === 'remove' && intval($a->argv[2])) { // delegated admins can view but not change delegation permissions if (x($_SESSION, 'submanage') && intval($_SESSION['submanage'])) { goaway($a->get_baseurl() . '/delegate'); } q("delete from manage where uid = %d and mid = %d limit 1", intval($a->argv[2]), intval(local_user())); goaway($a->get_baseurl() . '/delegate'); } $full_managers = array(); // These people can manage this account/page with full privilege $r = q("SELECT * FROM `user` WHERE `email` = '%s' AND `password` = '%s' ", dbesc($a->user['email']), dbesc($a->user['password'])); if (count($r)) { $full_managers = $r; } $delegates = array(); // find everybody that currently has delegated management to this account/page $r = q("select * from user where uid in ( select uid from manage where mid = %d ) ", intval(local_user())); if (count($r)) { $delegates = $r; } $uids = array(); if (count($full_managers)) { foreach ($full_managers as $rr) { $uids[] = $rr['uid']; } } if (count($delegates)) { foreach ($delegates as $rr) { $uids[] = $rr['uid']; } } // find every contact who might be a candidate for delegation $r = q("select nurl from contact where substring_index(contact.nurl,'/',3) = '%s' \n\t\tand contact.uid = %d and contact.self = 0 and network = '%s' ", dbesc(normalise_link($a->get_baseurl())), intval(local_user()), dbesc(NETWORK_DFRN)); if (!count($r)) { notice(t('No potential page delegates located.') . EOL); return; } $nicknames = array(); if (count($r)) { foreach ($r as $rr) { $nicknames[] = "'" . dbesc(basename($rr['nurl'])) . "'"; } } $potentials = array(); $nicks = implode(',', $nicknames); // get user records for all potential page delegates who are not already delegates or managers $r = q("select `uid`, `username`, `nickname` from user where nickname in ( {$nicks} )"); if (count($r)) { foreach ($r as $rr) { if (!in_array($rr['uid'], $uids)) { $potentials[] = $rr; } } } require_once "mod/settings.php"; settings_init($a); $o = replace_macros(get_markup_template('delegate.tpl'), array('$header' => t('Delegate Page Management'), '$base' => $a->get_baseurl(), '$desc' => t('Delegates are able to manage all aspects of this account/page except for basic account settings. Please do not delegate your personal account to anybody that you do not trust completely.'), '$head_managers' => t('Existing Page Managers'), '$managers' => $full_managers, '$head_delegates' => t('Existing Page Delegates'), '$delegates' => $delegates, '$head_potentials' => t('Potential Delegates'), '$potentials' => $potentials, '$remove' => t('Remove'), '$add' => t('Add'), '$none' => t('No entries.'))); return $o; }
function item_post(&$a) { if (!local_user() && !remote_user() && !x($_REQUEST, 'commenter')) { return; } require_once 'include/security.php'; $uid = local_user(); if (x($_REQUEST, 'dropitems')) { $arr_drop = explode(',', $_REQUEST['dropitems']); drop_items($arr_drop); $json = array('success' => 1); echo json_encode($json); killme(); } call_hooks('post_local_start', $_REQUEST); // logger('postinput ' . file_get_contents('php://input')); logger('postvars ' . print_r($_REQUEST, true), LOGGER_DATA); $api_source = x($_REQUEST, 'api_source') && $_REQUEST['api_source'] ? true : false; $message_id = x($_REQUEST, 'message_id') && $api_source ? strip_tags($_REQUEST['message_id']) : ''; $return_path = x($_REQUEST, 'return') ? $_REQUEST['return'] : ''; $preview = x($_REQUEST, 'preview') ? intval($_REQUEST['preview']) : 0; // Check for doubly-submitted posts, and reject duplicates // Note that we have to ignore previews, otherwise nothing will post // after it's been previewed if (!$preview && x($_REQUEST['post_id_random'])) { if (x($_SESSION['post-random']) && $_SESSION['post-random'] == $_REQUEST['post_id_random']) { logger("item post: duplicate post", LOGGER_DEBUG); item_post_return($a->get_baseurl(), $api_source, $return_path); } else { $_SESSION['post-random'] = $_REQUEST['post_id_random']; } } /** * Is this a reply to something? */ $parent = x($_REQUEST, 'parent') ? intval($_REQUEST['parent']) : 0; $parent_uri = x($_REQUEST, 'parent_uri') ? trim($_REQUEST['parent_uri']) : ''; $parent_item = null; $parent_contact = null; $thr_parent = ''; $parid = 0; $r = false; $objecttype = null; if ($parent || $parent_uri) { $objecttype = ACTIVITY_OBJ_COMMENT; if (!x($_REQUEST, 'type')) { $_REQUEST['type'] = 'net-comment'; } if ($parent) { $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent)); } elseif ($parent_uri && local_user()) { // This is coming from an API source, and we are logged in $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_uri), intval(local_user())); } // if this isn't the real parent of the conversation, find it if ($r !== false && count($r)) { $parid = $r[0]['parent']; $parent_uri = $r[0]['uri']; if ($r[0]['id'] != $r[0]['parent']) { $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1", intval($parid)); } } if ($r === false || !count($r)) { notice(t('Unable to locate original post.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } $parent_item = $r[0]; $parent = $r[0]['id']; // multi-level threading - preserve the info but re-parent to our single level threading //if(($parid) && ($parid != $parent)) $thr_parent = $parent_uri; if ($parent_item['contact-id'] && $uid) { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($parent_item['contact-id']), intval($uid)); if (count($r)) { $parent_contact = $r[0]; // If the contact id doesn't fit with the contact, then set the contact to null $thrparent = q("SELECT `author-link`, `network` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($thr_parent)); if (count($thrparent) and $thrparent[0]["network"] === NETWORK_OSTATUS and normalise_link($parent_contact["url"]) != normalise_link($thrparent[0]["author-link"])) { $parent_contact = null; require_once "include/Scrape.php"; $probed_contact = probe_url($thrparent[0]["author-link"]); if ($probed_contact["network"] != NETWORK_FEED) { $parent_contact = $probed_contact; $parent_contact["nurl"] = normalise_link($probed_contact["url"]); $parent_contact["thumb"] = $probed_contact["photo"]; $parent_contact["micro"] = $probed_contact["photo"]; } logger('parent contact: ' . print_r($parent_contact, true), LOGGER_DEBUG); } else { logger('no contact found: ' . print_r($thrparent, true), LOGGER_DEBUG); } } } } if ($parent) { logger('mod_item: item_post parent=' . $parent); } $profile_uid = x($_REQUEST, 'profile_uid') ? intval($_REQUEST['profile_uid']) : 0; $post_id = x($_REQUEST, 'post_id') ? intval($_REQUEST['post_id']) : 0; $app = x($_REQUEST, 'source') ? strip_tags($_REQUEST['source']) : ''; $extid = x($_REQUEST, 'extid') ? strip_tags($_REQUEST['extid']) : ''; $allow_moderated = false; // here is where we are going to check for permission to post a moderated comment. // First check that the parent exists and it is a wall item. if (x($_REQUEST, 'commenter') && (!$parent || !$parent_item['wall'])) { notice(t('Permission denied.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } // Now check that it is a page_type of PAGE_BLOG, and that valid personal details // have been provided, and run any anti-spam plugins // TODO if (!can_write_wall($a, $profile_uid) && !$allow_moderated) { notice(t('Permission denied.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } // is this an edited post? $orig_post = null; if ($post_id) { $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($post_id)); if (!count($i)) { killme(); } $orig_post = $i[0]; } $user = null; $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($profile_uid)); if (count($r)) { $user = $r[0]; } if ($orig_post) { $str_group_allow = $orig_post['allow_gid']; $str_contact_allow = $orig_post['allow_cid']; $str_group_deny = $orig_post['deny_gid']; $str_contact_deny = $orig_post['deny_cid']; $location = $orig_post['location']; $coord = $orig_post['coord']; $verb = $orig_post['verb']; $objecttype = $orig_post['object-type']; $emailcc = $orig_post['emailcc']; $app = $orig_post['app']; $categories = $orig_post['file']; $title = notags(trim($_REQUEST['title'])); $body = escape_tags(trim($_REQUEST['body'])); $private = $orig_post['private']; $pubmail_enable = $orig_post['pubmail']; $network = $orig_post['network']; $guid = $orig_post['guid']; $extid = $orig_post['extid']; } else { // if coming from the API and no privacy settings are set, // use the user default permissions - as they won't have // been supplied via a form. if ($api_source && !array_key_exists('contact_allow', $_REQUEST) && !array_key_exists('group_allow', $_REQUEST) && !array_key_exists('contact_deny', $_REQUEST) && !array_key_exists('group_deny', $_REQUEST)) { $str_group_allow = $user['allow_gid']; $str_contact_allow = $user['allow_cid']; $str_group_deny = $user['deny_gid']; $str_contact_deny = $user['deny_cid']; } else { // use the posted permissions $str_group_allow = perms2str($_REQUEST['group_allow']); $str_contact_allow = perms2str($_REQUEST['contact_allow']); $str_group_deny = perms2str($_REQUEST['group_deny']); $str_contact_deny = perms2str($_REQUEST['contact_deny']); } $title = notags(trim($_REQUEST['title'])); $location = notags(trim($_REQUEST['location'])); $coord = notags(trim($_REQUEST['coord'])); $verb = notags(trim($_REQUEST['verb'])); $emailcc = notags(trim($_REQUEST['emailcc'])); $body = escape_tags(trim($_REQUEST['body'])); $network = notags(trim($_REQUEST['network'])); $guid = get_guid(32); $naked_body = preg_replace('/\\[(.+?)\\]/', '', $body); if (version_compare(PHP_VERSION, '5.3.0', '>=')) { $l = new Text_LanguageDetect(); //$lng = $l->detectConfidence($naked_body); //$postopts = (($lng['language']) ? 'lang=' . $lng['language'] . ';' . $lng['confidence'] : ''); $lng = $l->detect($naked_body, 3); if (sizeof($lng) > 0) { $postopts = ""; foreach ($lng as $language => $score) { if ($postopts == "") { $postopts = "lang="; } else { $postopts .= ":"; } $postopts .= $language . ";" . $score; } } logger('mod_item: detect language' . print_r($lng, true) . $naked_body, LOGGER_DATA); } else { $postopts = ''; } $private = strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) ? 1 : 0; if ($user['hidewall']) { $private = 2; } // If this is a comment, set the permissions from the parent. if ($parent_item) { $private = 0; // for non native networks use the network of the original post as network of the item if ($parent_item['network'] != NETWORK_DIASPORA and $parent_item['network'] != NETWORK_OSTATUS and $network == "") { $network = $parent_item['network']; } if ($parent_item['private'] || strlen($parent_item['allow_cid']) || strlen($parent_item['allow_gid']) || strlen($parent_item['deny_cid']) || strlen($parent_item['deny_gid'])) { $private = $parent_item['private'] ? $parent_item['private'] : 1; } $str_contact_allow = $parent_item['allow_cid']; $str_group_allow = $parent_item['allow_gid']; $str_contact_deny = $parent_item['deny_cid']; $str_group_deny = $parent_item['deny_gid']; } $pubmail_enable = x($_REQUEST, 'pubmail_enable') && intval($_REQUEST['pubmail_enable']) && !$private ? 1 : 0; // if using the API, we won't see pubmail_enable - figure out if it should be set if ($api_source && $profile_uid && $profile_uid == local_user() && !$private) { $mail_disabled = function_exists('imap_open') && !get_config('system', 'imap_disabled') ? 0 : 1; if (!$mail_disabled) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user())); if (count($r) && intval($r[0]['pubmail'])) { $pubmail_enabled = true; } } } if (!strlen($body)) { if ($preview) { killme(); } info(t('Empty post discarded.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } } if (strlen($categories)) { // get the "fileas" tags for this post $filedas = file_tag_file_to_list($categories, 'file'); } // save old and new categories, so we can determine what needs to be deleted from pconfig $categories_old = $categories; $categories = file_tag_list_to_file(trim($_REQUEST['category']), 'category'); $categories_new = $categories; if (strlen($filedas)) { // append the fileas stuff to the new categories list $categories .= file_tag_list_to_file($filedas, 'file'); } // Work around doubled linefeeds in Tinymce 3.5b2 // First figure out if it's a status post that would've been // created using tinymce. Otherwise leave it alone. /* $plaintext = (local_user() ? intval(get_pconfig(local_user(),'system','plaintext')) || !feature_enabled($profile_uid,'richtext') : 0); if((! $parent) && (! $api_source) && (! $plaintext)) { $body = fix_mce_lf($body); }*/ $plaintext = local_user() ? !feature_enabled($profile_uid, 'richtext') : 0; if (!$parent && !$api_source && !$plaintext) { $body = fix_mce_lf($body); } // get contact info for poster $author = null; $self = false; $contact_id = 0; if (local_user() && local_user() == $profile_uid) { $self = true; $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($_SESSION['uid'])); } elseif (remote_user()) { if (is_array($_SESSION['remote'])) { foreach ($_SESSION['remote'] as $v) { if ($v['uid'] == $profile_uid) { $contact_id = $v['cid']; break; } } } if ($contact_id) { $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($contact_id)); } } if (count($r)) { $author = $r[0]; $contact_id = $author['id']; } // get contact info for owner if ($profile_uid == local_user()) { $contact_record = $author; } else { $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($profile_uid)); if (count($r)) { $contact_record = $r[0]; } } $post_type = notags(trim($_REQUEST['type'])); if ($post_type === 'net-comment') { if ($parent_item !== null) { if ($parent_item['wall'] == 1) { $post_type = 'wall-comment'; } else { $post_type = 'remote-comment'; } } } /** * * When a photo was uploaded into the message using the (profile wall) ajax * uploader, The permissions are initially set to disallow anybody but the * owner from seeing it. This is because the permissions may not yet have been * set for the post. If it's private, the photo permissions should be set * appropriately. But we didn't know the final permissions on the post until * now. So now we'll look for links of uploaded messages that are in the * post and set them to the same permissions as the post itself. * */ $match = null; if (!$preview && preg_match_all("/\\[img([\\=0-9x]*?)\\](.*?)\\[\\/img\\]/", $body, $match)) { $images = $match[2]; if (count($images)) { $objecttype = ACTIVITY_OBJ_IMAGE; foreach ($images as $image) { if (!stristr($image, $a->get_baseurl() . '/photo/')) { continue; } $image_uri = substr($image, strrpos($image, '/') + 1); $image_uri = substr($image_uri, 0, strpos($image_uri, '-')); if (!strlen($image_uri)) { continue; } $srch = '<' . intval($contact_id) . '>'; $r = q("SELECT `id` FROM `photo` WHERE `allow_cid` = '%s' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = ''\n\t\t\t\t\tAND `resource-id` = '%s' AND `uid` = %d LIMIT 1", dbesc($srch), dbesc($image_uri), intval($profile_uid)); if (!count($r)) { continue; } $r = q("UPDATE `photo` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\tWHERE `resource-id` = '%s' AND `uid` = %d AND `album` = '%s' ", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), dbesc($image_uri), intval($profile_uid), dbesc(t('Wall Photos'))); } } } /** * Next link in any attachment references we find in the post. */ $match = false; if (!$preview && preg_match_all("/\\[attachment\\](.*?)\\[\\/attachment\\]/", $body, $match)) { $attaches = $match[1]; if (count($attaches)) { foreach ($attaches as $attach) { $r = q("SELECT * FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($attach)); if (count($r)) { $r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\t\tWHERE `uid` = %d AND `id` = %d", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), intval($profile_uid), intval($attach)); } } } } // embedded bookmark in post? set bookmark flag $bookmark = 0; if (preg_match_all("/\\[bookmark\\=([^\\]]*)\\](.*?)\\[\\/bookmark\\]/ism", $body, $match, PREG_SET_ORDER)) { $objecttype = ACTIVITY_OBJ_BOOKMARK; $bookmark = 1; } $body = bb_translate_video($body); /** * Fold multi-line [code] sequences */ $body = preg_replace('/\\[\\/code\\]\\s*\\[code\\]/ism', "\n", $body); $body = scale_external_images($body, false); // Setting the object type if not defined before if (!$objecttype) { $objecttype = ACTIVITY_OBJ_NOTE; // Default value require_once "include/plaintext.php"; $objectdata = get_attached_data($body); if ($post["type"] == "link") { $objecttype = ACTIVITY_OBJ_BOOKMARK; } elseif ($post["type"] == "video") { $objecttype = ACTIVITY_OBJ_VIDEO; } elseif ($post["type"] == "photo") { $objecttype = ACTIVITY_OBJ_IMAGE; } } /** * Look for any tags and linkify them */ $str_tags = ''; $inform = ''; $tags = get_tags($body); /** * add a statusnet style reply tag if the original post was from there * and we are replying, and there isn't one already */ if ($parent_contact && $parent_contact['network'] === NETWORK_OSTATUS && $parent_contact['nick'] && !in_array('@' . $parent_contact['nick'], $tags)) { $body = '@' . $parent_contact['nick'] . ' ' . $body; $tags[] = '@' . $parent_contact['nick']; } $tagged = array(); $private_forum = false; if (count($tags)) { foreach ($tags as $tag) { if (strpos($tag, '#') === 0) { continue; } // If we already tagged 'Robert Johnson', don't try and tag 'Robert'. // Robert Johnson should be first in the $tags array $fullnametagged = false; for ($x = 0; $x < count($tagged); $x++) { if (stristr($tagged[$x], $tag . ' ')) { $fullnametagged = true; break; } } if ($fullnametagged) { continue; } $success = handle_tag($a, $body, $inform, $str_tags, local_user() ? local_user() : $profile_uid, $tag, $network); if ($success['replaced']) { $tagged[] = $tag; } if (is_array($success['contact']) && intval($success['contact']['prv'])) { $private_forum = true; $private_id = $success['contact']['id']; } } } if ($private_forum && !$parent && !$private) { // we tagged a private forum in a top level post and the message was public. // Restrict it. $private = 1; $str_contact_allow = '<' . $private_id . '>'; } $attachments = ''; $match = false; if (preg_match_all('/(\\[attachment\\]([0-9]+)\\[\\/attachment\\])/', $body, $match)) { foreach ($match[2] as $mtch) { $r = q("SELECT `id`,`filename`,`filesize`,`filetype` FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($mtch)); if (count($r)) { if (strlen($attachments)) { $attachments .= ','; } $attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" length="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . ($r[0]['filename'] ? $r[0]['filename'] : '') . '"[/attach]'; } $body = str_replace($match[1], '', $body); } } $wall = 0; if ($post_type === 'wall' || $post_type === 'wall-comment') { $wall = 1; } if (!strlen($verb)) { $verb = ACTIVITY_POST; } if ($network == "") { $network = NETWORK_DFRN; } $gravity = $parent ? 6 : 0; // even if the post arrived via API we are considering that it // originated on this site by default for determining relayability. $origin = x($_REQUEST, 'origin') ? intval($_REQUEST['origin']) : 1; $notify_type = $parent ? 'comment-new' : 'wall-new'; $uri = $message_id ? $message_id : item_new_uri($a->get_hostname(), $profile_uid); // Fallback so that we alway have a thr-parent if (!$thr_parent) { $thr_parent = $uri; } $datarray = array(); $datarray['uid'] = $profile_uid; $datarray['type'] = $post_type; $datarray['wall'] = $wall; $datarray['gravity'] = $gravity; $datarray['network'] = $network; $datarray['contact-id'] = $contact_id; $datarray['owner-name'] = $contact_record['name']; $datarray['owner-link'] = $contact_record['url']; $datarray['owner-avatar'] = $contact_record['thumb']; $datarray['author-name'] = $author['name']; $datarray['author-link'] = $author['url']; $datarray['author-avatar'] = $author['thumb']; $datarray['created'] = datetime_convert(); $datarray['edited'] = datetime_convert(); $datarray['commented'] = datetime_convert(); $datarray['received'] = datetime_convert(); $datarray['changed'] = datetime_convert(); $datarray['extid'] = $extid; $datarray['guid'] = $guid; $datarray['uri'] = $uri; $datarray['title'] = $title; $datarray['body'] = $body; $datarray['app'] = $app; $datarray['location'] = $location; $datarray['coord'] = $coord; $datarray['tag'] = $str_tags; $datarray['file'] = $categories; $datarray['inform'] = $inform; $datarray['verb'] = $verb; $datarray['object-type'] = $objecttype; $datarray['allow_cid'] = $str_contact_allow; $datarray['allow_gid'] = $str_group_allow; $datarray['deny_cid'] = $str_contact_deny; $datarray['deny_gid'] = $str_group_deny; $datarray['private'] = $private; $datarray['pubmail'] = $pubmail_enable; $datarray['attach'] = $attachments; $datarray['bookmark'] = intval($bookmark); $datarray['thr-parent'] = $thr_parent; $datarray['postopts'] = $postopts; $datarray['origin'] = $origin; $datarray['moderated'] = $allow_moderated; /** * These fields are for the convenience of plugins... * 'self' if true indicates the owner is posting on their own wall * If parent is 0 it is a top-level post. */ $datarray['parent'] = $parent; $datarray['self'] = $self; // $datarray['prvnets'] = $user['prvnets']; if ($orig_post) { $datarray['edit'] = true; } // Search for hashtags item_body_set_hashtags($datarray); // preview mode - prepare the body for display and send it via json if ($preview) { require_once 'include/conversation.php'; $o = conversation($a, array(array_merge($contact_record, $datarray)), 'search', false, true); logger('preview: ' . $o); echo json_encode(array('preview' => $o)); killme(); } call_hooks('post_local', $datarray); if (x($datarray, 'cancel')) { logger('mod_item: post cancelled by plugin.'); if ($return_path) { goaway($a->get_baseurl() . "/" . $return_path); } $json = array('cancel' => 1); if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) { $json['reload'] = $a->get_baseurl() . '/' . $_REQUEST['jsreload']; } echo json_encode($json); killme(); } // Fill the cache field put_item_in_cache($datarray); if ($orig_post) { $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `attach` = '%s', `file` = '%s', `rendered-html` = '%s', `rendered-hash` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['tag']), dbesc($datarray['attach']), dbesc($datarray['file']), dbesc($datarray['rendered-html']), dbesc($datarray['rendered-hash']), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($post_id), intval($profile_uid)); create_tags_from_item($post_id); create_files_from_item($post_id); update_thread($post_id); // update filetags in pconfig file_tag_update_pconfig($uid, $categories_old, $categories_new, 'category'); proc_run('php', "include/notifier.php", 'edit_post', "{$post_id}"); if (x($_REQUEST, 'return') && strlen($return_path)) { logger('return: ' . $return_path); goaway($a->get_baseurl() . "/" . $return_path); } killme(); } else { $post_id = 0; } $r = q("INSERT INTO `item` (`guid`, `extid`, `uid`,`type`,`wall`,`gravity`, `network`, `contact-id`,`owner-name`,`owner-link`,`owner-avatar`, `author-name`, `author-link`, `author-avatar`,\n\t\t`created`, `edited`, `commented`, `received`, `changed`, `uri`, `thr-parent`, `title`, `body`, `app`, `location`, `coord`, `tag`, `inform`, `verb`, `object-type`, `postopts`,\n\t\t`allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `private`, `pubmail`, `attach`, `bookmark`,`origin`, `moderated`, `file`, `rendered-html`, `rendered-hash`)\n\t\tVALUES( '%s', '%s', %d, '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s')", dbesc($datarray['guid']), dbesc($datarray['extid']), intval($datarray['uid']), dbesc($datarray['type']), intval($datarray['wall']), intval($datarray['gravity']), dbesc($datarray['network']), intval($datarray['contact-id']), dbesc($datarray['owner-name']), dbesc($datarray['owner-link']), dbesc($datarray['owner-avatar']), dbesc($datarray['author-name']), dbesc($datarray['author-link']), dbesc($datarray['author-avatar']), dbesc($datarray['created']), dbesc($datarray['edited']), dbesc($datarray['commented']), dbesc($datarray['received']), dbesc($datarray['changed']), dbesc($datarray['uri']), dbesc($datarray['thr-parent']), dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['app']), dbesc($datarray['location']), dbesc($datarray['coord']), dbesc($datarray['tag']), dbesc($datarray['inform']), dbesc($datarray['verb']), dbesc($datarray['object-type']), dbesc($datarray['postopts']), dbesc($datarray['allow_cid']), dbesc($datarray['allow_gid']), dbesc($datarray['deny_cid']), dbesc($datarray['deny_gid']), intval($datarray['private']), intval($datarray['pubmail']), dbesc($datarray['attach']), intval($datarray['bookmark']), intval($datarray['origin']), intval($datarray['moderated']), dbesc($datarray['file']), dbesc($datarray['rendered-html']), dbesc($datarray['rendered-hash'])); $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($datarray['uri'])); if (!count($r)) { logger('mod_item: unable to retrieve post that was just stored.'); notice(t('System error. Post not saved.') . EOL); goaway($a->get_baseurl() . "/" . $return_path); // NOTREACHED } $post_id = $r[0]['id']; logger('mod_item: saved item ' . $post_id); $datarray["id"] = $post_id; $datarray["plink"] = $a->get_baseurl() . '/display/' . urlencode($datarray["guid"]); // update filetags in pconfig file_tag_update_pconfig($uid, $categories_old, $categories_new, 'category'); if ($parent) { // This item is the last leaf and gets the comment box, clear any ancestors $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent` = %d ", dbesc(datetime_convert()), intval($parent)); update_thread($parent, true); // Inherit ACLs from the parent item. $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `private` = %d\n\t\t\tWHERE `id` = %d", dbesc($parent_item['allow_cid']), dbesc($parent_item['allow_gid']), dbesc($parent_item['deny_cid']), dbesc($parent_item['deny_gid']), intval($parent_item['private']), intval($post_id)); if ($contact_record != $author) { notification(array('type' => NOTIFY_COMMENT, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'uid' => $user['uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode($datarray['guid']), 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, 'parent_uri' => $parent_item['uri'])); } // Store the comment signature information in case we need to relay to Diaspora store_diaspora_comment_sig($datarray, $author, $self ? $a->user['prvkey'] : false, $parent_item, $post_id); } else { $parent = $post_id; if ($contact_record != $author) { notification(array('type' => NOTIFY_WALL, 'notify_flags' => $user['notify-flags'], 'language' => $user['language'], 'to_name' => $user['username'], 'to_email' => $user['email'], 'uid' => $user['uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . urlencode($datarray['guid']), 'source_name' => $datarray['author-name'], 'source_link' => $datarray['author-link'], 'source_photo' => $datarray['author-avatar'], 'verb' => ACTIVITY_POST, 'otype' => 'item')); } } // fallback so that parent always gets set to non-zero. if (!$parent) { $parent = $post_id; } $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s', `plink` = '%s', `changed` = '%s', `last-child` = 1, `visible` = 1\n\t\tWHERE `id` = %d", intval($parent), dbesc($parent == $post_id ? $uri : $parent_item['uri']), dbesc($a->get_baseurl() . '/display/' . urlencode($datarray['guid'])), dbesc(datetime_convert()), intval($post_id)); // photo comments turn the corresponding item visible to the profile wall // This way we don't see every picture in your new photo album posted to your wall at once. // They will show up as people comment on them. if (!$parent_item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d", intval($parent_item['id'])); update_thread($parent_item['id']); } // update the commented timestamp on the parent q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($parent)); if ($post_id != $parent) { update_thread($parent); } call_hooks('post_local_end', $datarray); if (strlen($emailcc) && $profile_uid == local_user()) { $erecips = explode(',', $emailcc); if (count($erecips)) { foreach ($erecips as $recip) { $addr = trim($recip); if (!strlen($addr)) { continue; } $disclaimer = '<hr />' . sprintf(t('This message was sent to you by %s, a member of the Friendica social network.'), $a->user['username']) . '<br />'; $disclaimer .= sprintf(t('You may visit them online at %s'), $a->get_baseurl() . '/profile/' . $a->user['nickname']) . EOL; $disclaimer .= t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL; if (!$datarray['title'] == '') { $subject = email_header_encode($datarray['title'], 'UTF-8'); } else { $subject = email_header_encode('[Friendica]' . ' ' . sprintf(t('%s posted an update.'), $a->user['username']), 'UTF-8'); } $link = '<a href="' . $a->get_baseurl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />'; $html = prepare_body($datarray); $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>'; include_once 'include/html2plain.php'; $params = array('fromName' => $a->user['username'], 'fromEmail' => $a->user['email'], 'toEmail' => $addr, 'replyTo' => $a->user['email'], 'messageSubject' => $subject, 'htmlVersion' => $message, 'textVersion' => html2plain($html . $disclaimer)); Emailer::send($params); } } } create_tags_from_item($post_id); create_files_from_item($post_id); if ($post_id == $parent) { add_thread($post_id); } // This is a real juggling act on shared hosting services which kill your processes // e.g. dreamhost. We used to start delivery to our native delivery agents in the background // and then run our plugin delivery from the foreground. We're now doing plugin delivery first, // because as soon as you start loading up a bunch of remote delivey processes, *this* page is // likely to get killed off. If you end up looking at an /item URL and a blank page, // it's very likely the delivery got killed before all your friends could be notified. // Currently the only realistic fixes are to use a reliable server - which precludes shared hosting, // or cut back on plugins which do remote deliveries. proc_run('php', "include/notifier.php", $notify_type, "{$post_id}"); logger('post_complete'); item_post_return($a->get_baseurl(), $api_source, $return_path); // NOTREACHED }
function api_item_get_user(&$a, $item) { // The author is our direct contact, in a conversation with us. if (link_compare($item['url'], $item['author-link'])) { return api_get_user($a, $item['cid']); } else { // The author may be a contact of ours, but is replying to somebody else. // Figure out if we know him/her. $normalised = normalise_link(strlen($item['author-link']) ? $item['author-link'] : $item['url']); if ($normalised != 'mailbox' && x($a->contacts[$normalised])) { return api_get_user($a, $a->contacts[$normalised]['id']); } } // We don't know this person directly. list($nick, $name) = array_map("trim", explode("(", $item['author-name'])); $name = str_replace(")", "", $name); $ret = array('uid' => 0, 'id' => 0, 'name' => $name, 'screen_name' => $nick, 'location' => '', 'profile_image_url' => $item['author-avatar'], 'url' => $item['author-link'], 'contact_url' => 0, 'protected' => false, 'friends_count' => 0, 'created_at' => '', 'utc_offset' => 0, 'time_zone' => '', 'geo_enabled' => false, 'statuses_count' => 0, 'lang' => 'en', 'description' => '', 'followers_count' => 0, 'favourites_count' => 0, 'contributors_enabled' => false, 'follow_request_sent' => false, 'profile_background_color' => 'cfe8f6', 'profile_text_color' => '000000', 'profile_link_color' => 'FF8500', 'profile_sidebar_fill_color' => 'AD0066', 'profile_sidebar_border_color' => 'AD0066', 'profile_background_image_url' => '', 'profile_background_tile' => false, 'profile_use_background_image' => false, 'notifications' => false, 'verified' => true, 'followers' => '', 'status' => array()); return $ret; }
function item_photo_menu($item) { $a = get_app(); $contact = null; $ssl_state = false; $sub_link = ""; $poke_link = ""; $contact_url = ""; $pm_url = ""; $vsrc_link = ""; $follow_url = ""; $local_channel = local_channel(); if ($local_channel) { $ssl_state = true; if (!count($a->contacts)) { load_contact_links($local_channel); } $channel = $a->get_channel(); $channel_hash = $channel ? $channel['channel_hash'] : ''; } if ($local_channel && $local_channel == $item['uid']) { $vsrc_link = 'javascript:viewsrc(' . $item['id'] . '); return false;'; if ($item['parent'] == $item['id'] && $channel && $channel_hash != $item['author_xchan']) { $sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;'; } } $profile_link = chanlink_hash($item['author_xchan']); if ($item['uid'] > 0) { $pm_url = $a->get_baseurl($ssl_state) . '/mail/new/?f=&hash=' . $item['author_xchan']; } if ($a->contacts && array_key_exists($item['author_xchan'], $a->contacts)) { $contact = $a->contacts[$item['author_xchan']]; } else { if ($local_channel && $item['author']['xchan_addr']) { $follow_url = z_root() . '/follow/?f=&url=' . $item['author']['xchan_addr']; } } if ($contact) { $poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $contact['abook_id']; if (!($contact['abook_flags'] & ABOOK_FLAG_SELF)) { $contact_url = $a->get_baseurl($ssl_state) . '/connedit/' . $contact['abook_id']; } $posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $contact['abook_id']; $clean_url = normalise_link($item['author-link']); } $menu = array(t("View Source") => $vsrc_link, t("Follow Thread") => $sub_link, t("View Status") => $status_link, t("View Profile") => $profile_link, t("View Photos") => $photos_link, t("Matrix Activity") => $posts_link, t("Connect") => $follow_url, t("Edit Contact") => $contact_url, t("Send PM") => $pm_url, t("Poke") => $poke_link); $args = array('item' => $item, 'menu' => $menu); call_hooks('item_photo_menu', $args); $menu = $args['menu']; $o = ""; foreach ($menu as $k => $v) { if (strpos($v, 'javascript:') === 0) { $v = substr($v, 11); $o .= "<li><a href=\"#\" onclick=\"{$v}\">{$k}</a></li>\n"; } elseif ($v != "") { $o .= "<li><a href=\"{$v}\">{$k}</a></li>\n"; } } return $o; }
function item_photo_menu($item) { $a = get_app(); $ssl_state = false; if (local_user()) { $ssl_state = true; if (!count($a->contacts)) { load_contact_links(local_user()); } } $sub_link = ""; $poke_link = ""; $contact_url = ""; $pm_url = ""; $status_link = ""; $photos_link = ""; $posts_link = ""; if (local_user() && local_user() == $item['uid'] && $item['parent'] == $item['id'] && !$item['self']) { $sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;'; } $sparkle = false; $profile_link = best_link_url($item, $sparkle, $ssl_state); if ($profile_link === 'mailbox') { $profile_link = ''; } if ($sparkle) { $cid = intval(basename($profile_link)); $status_link = $profile_link . "?url=status"; $photos_link = $profile_link . "?url=photos"; $profile_link = $profile_link . "?url=profile"; $pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid; $zurl = ''; } else { $profile_link = zrl($profile_link); if (local_user() && local_user() == $item['uid'] && link_compare($item['url'], $item['author-link'])) { $cid = $item['contact-id']; } else { $cid = 0; } } if ($cid && !$item['self']) { $poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $cid; $contact_url = $a->get_baseurl($ssl_state) . '/contacts/' . $cid; $posts_link = $a->get_baseurl($ssl_state) . '/network/0?nets=all&cid=' . $cid; $clean_url = normalise_link($item['author-link']); if (local_user() && local_user() == $item['uid']) { if (isset($a->contacts) && x($a->contacts, $clean_url)) { if ($a->contacts[$clean_url]['network'] === NETWORK_DIASPORA) { $pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid; } } } } $menu = array(t("Follow Thread") => $sub_link, t("View Status") => $status_link, t("View Profile") => $profile_link, t("View Photos") => $photos_link, t("Network Posts") => $posts_link, t("Edit Contact") => $contact_url, t("Send PM") => $pm_url, t("Poke") => $poke_link); $args = array('item' => $item, 'menu' => $menu); call_hooks('item_photo_menu', $args); $menu = $args['menu']; $o = ""; foreach ($menu as $k => $v) { if (strpos($v, 'javascript:') === 0) { $v = substr($v, 11); $o .= "<li><a href=\"#\" onclick=\"{$v}\">{$k}</a></li>\n"; } elseif ($v != "") { $o .= "<li><a href=\"{$v}\">{$k}</a></li>\n"; } } return $o; }
function new_contact($uid, $url, $interactive = false) { $result = array('cid' => -1, 'success' => false, 'message' => ''); $a = get_app(); // remove ajax junk, e.g. Twitter $url = str_replace('/#!/', '/', $url); if (!allowed_url($url)) { $result['message'] = t('Disallowed profile URL.'); return $result; } if (!$url) { $result['message'] = t('Connect URL missing.'); return $result; } $arr = array('url' => $url, 'contact' => array()); call_hooks('follow', $arr); if (x($arr['contact'], 'name')) { $ret = $arr['contact']; } else { $ret = probe_url($url); } if ($ret['network'] === NETWORK_DFRN) { if ($interactive) { if (strlen($a->path)) { $myaddr = bin2hex($a->get_baseurl() . '/profile/' . $a->user['nickname']); } else { $myaddr = bin2hex($a->user['nickname'] . '@' . $a->get_hostname()); } goaway($ret['request'] . "&addr={$myaddr}"); // NOTREACHED } } else { if (get_config('system', 'dfrn_only')) { $result['message'] = t('This site is not configured to allow communications with other networks.') . EOL; $result['message'] != t('No compatible communication protocols or feeds were discovered.') . EOL; return $result; } } // This extra param just confuses things, remove it if ($ret['network'] === NETWORK_DIASPORA) { $ret['url'] = str_replace('?absolute=true', '', $ret['url']); } // do we have enough information? if (!(x($ret, 'name') && x($ret, 'poll') && (x($ret, 'url') || x($ret, 'addr')))) { $result['message'] .= t('The profile address specified does not provide adequate information.') . EOL; if (!x($ret, 'poll')) { $result['message'] .= t('No compatible communication protocols or feeds were discovered.') . EOL; } if (!x($ret, 'name')) { $result['message'] .= t('An author or name was not found.') . EOL; } if (!x($ret, 'url')) { $result['message'] .= t('No browser URL could be matched to this address.') . EOL; } if (strpos($url, '@') !== false) { $result['message'] .= t('Unable to match @-style Identity Address with a known protocol or email contact.') . EOL; $result['message'] .= t('Use mailto: in front of address to force email check.') . EOL; } return $result; } if ($ret['network'] === NETWORK_OSTATUS && get_config('system', 'ostatus_disabled')) { $result['message'] .= t('The profile address specified belongs to a network which has been disabled on this site.') . EOL; $ret['notify'] = ''; } if (!$ret['notify']) { $result['message'] .= t('Limited profile. This person will be unable to receive direct/personal notifications from you.') . EOL; } $writeable = $ret['network'] === NETWORK_OSTATUS && $ret['notify'] ? 1 : 0; $subhub = $ret['network'] === NETWORK_OSTATUS ? true : false; $hidden = $ret['network'] === NETWORK_MAIL ? 1 : 0; if ($ret['network'] === NETWORK_MAIL) { $writeable = 1; } if ($ret['network'] === NETWORK_DIASPORA) { $writeable = 1; } // check if we already have a contact // the poll url is more reliable than the profile url, as we may have // indirect links or webfinger links $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `poll` IN ('%s', '%s') AND `network` = '%s' LIMIT 1", intval($uid), dbesc($ret['poll']), dbesc(normalise_link($ret['poll'])), dbesc($ret['network'])); if (!count($r)) { $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` = '%s' LIMIT 1", intval($uid), dbesc(normalise_link($url)), dbesc($ret['network'])); } if (count($r)) { // update contact if ($r[0]['rel'] == CONTACT_IS_FOLLOWER || $network === NETWORK_DIASPORA && $r[0]['rel'] == CONTACT_IS_SHARING) { q("UPDATE `contact` SET `rel` = %d , `subhub` = %d, `readonly` = 0 WHERE `id` = %d AND `uid` = %d", intval(CONTACT_IS_FRIEND), intval($subhub), intval($r[0]['id']), intval($uid)); } } else { // check service class limits $r = q("select count(*) as total from contact where uid = %d and pending = 0 and self = 0", intval($uid)); if (count($r)) { $total_contacts = $r[0]['total']; } if (!service_class_allows($uid, 'total_contacts', $total_contacts)) { $result['message'] .= upgrade_message(); return $result; } $r = q("select count(network) as total from contact where uid = %d and network = '%s' and pending = 0 and self = 0", intval($uid), dbesc($network)); if (count($r)) { $total_network = $r[0]['total']; } if (!service_class_allows($uid, 'total_contacts_' . $network, $total_network)) { $result['message'] .= upgrade_message(); return $result; } $new_relation = $ret['network'] === NETWORK_MAIL ? CONTACT_IS_FRIEND : CONTACT_IS_SHARING; if ($ret['network'] === NETWORK_DIASPORA) { $new_relation = CONTACT_IS_FOLLOWER; } // create contact record $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `batch`, `notify`, `poll`, `poco`, `name`, `nick`, `network`, `pubkey`, `rel`, `priority`,\n\t\t\t`writable`, `hidden`, `blocked`, `readonly`, `pending`, `subhub` )\n\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, 0, 0, 0, %d ) ", intval($uid), dbesc(datetime_convert()), dbesc($ret['url']), dbesc(normalise_link($ret['url'])), dbesc($ret['addr']), dbesc($ret['alias']), dbesc($ret['batch']), dbesc($ret['notify']), dbesc($ret['poll']), dbesc($ret['poco']), dbesc($ret['name']), dbesc($ret['nick']), dbesc($ret['network']), dbesc($ret['pubkey']), intval($new_relation), intval($ret['priority']), intval($writeable), intval($hidden), intval($subhub)); } $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `network` = '%s' AND `uid` = %d LIMIT 1", dbesc($ret['url']), dbesc($ret['network']), intval($uid)); if (!count($r)) { $result['message'] .= t('Unable to retrieve contact information.') . EOL; return $result; } $contact = $r[0]; $contact_id = $r[0]['id']; $result['cid'] = $contact_id; $g = q("select def_gid from user where uid = %d limit 1", intval($uid)); if ($g && intval($g[0]['def_gid'])) { require_once 'include/group.php'; group_add_member($uid, '', $contact_id, $g[0]['def_gid']); } require_once "include/Photo.php"; $photos = import_profile_photo($ret['photo'], $uid, $contact_id); $r = q("UPDATE `contact` SET `photo` = '%s',\n\t\t\t`thumb` = '%s',\n\t\t\t`micro` = '%s',\n\t\t\t`name-date` = '%s',\n\t\t\t`uri-date` = '%s',\n\t\t\t`avatar-date` = '%s'\n\t\t\tWHERE `id` = %d", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($contact_id)); // pull feed and consume it, which should subscribe to the hub. proc_run('php', "include/onepoll.php", "{$contact_id}", "force"); // create a follow slap $tpl = get_markup_template('follow_slap.tpl'); $slap = replace_macros($tpl, array('$name' => $a->user['username'], '$profile_page' => $a->get_baseurl() . '/profile/' . $a->user['nickname'], '$photo' => $a->contact['photo'], '$thumb' => $a->contact['thumb'], '$published' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME), '$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':follow:' . get_guid(32), '$title' => '', '$type' => 'text', '$content' => t('following'), '$nick' => $a->user['nickname'], '$verb' => ACTIVITY_FOLLOW, '$ostat_follow' => '')); $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\tWHERE `user`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", intval($uid)); if (count($r)) { if ($contact['network'] == NETWORK_OSTATUS && strlen($contact['notify'])) { require_once 'include/salmon.php'; slapper($r[0], $contact['notify'], $slap); } if ($contact['network'] == NETWORK_DIASPORA) { require_once 'include/diaspora.php'; $ret = diaspora_share($a->user, $contact); logger('mod_follow: diaspora_share returns: ' . $ret); } } $result['success'] = true; return $result; }
function poco_store($item) { // Isn't it public? if ($item['private']) { return; } // Or is it from a network where we don't store the global contacts? if (!in_array($item["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_STATUSNET, ""))) { return; } // Is it a global copy? $store_gcontact = $item["uid"] == 0; // Is it a comment on a global copy? if (!$store_gcontact and $item["uri"] != $item["parent-uri"]) { $q = q("SELECT `id` FROM `item` WHERE `uri`='%s' AND `uid` = 0", $item["parent-uri"]); $store_gcontact = count($q); } if (!$store_gcontact) { return; } // "3" means: We don't know this contact directly (Maybe a reshared item) $generation = 3; $network = ""; $profile_url = $item["author-link"]; // Is it a user from our server? $q = q("SELECT `id` FROM `contact` WHERE `self` AND `nurl` = '%s' LIMIT 1", dbesc(normalise_link($item["author-link"]))); if (count($q)) { logger("Our user (generation 1): " . $item["author-link"], LOGGER_DEBUG); $generation = 1; $network = NETWORK_DFRN; } else { // Is it a contact from a user on our server? $q = q("SELECT `network`, `url` FROM `contact` WHERE `uid` != 0 AND `network` != ''\n\t\t\tAND (`nurl` = '%s' OR `alias` IN ('%s', '%s')) AND `network` != '%s' LIMIT 1", dbesc(normalise_link($item["author-link"])), dbesc(normalise_link($item["author-link"])), dbesc($item["author-link"]), dbesc(NETWORK_STATUSNET)); if (count($q)) { $generation = 2; $network = $q[0]["network"]; $profile_url = $q[0]["url"]; logger("Known contact (generation 2): " . $profile_url, LOGGER_DEBUG); } } if ($generation == 3) { logger("Unknown contact (generation 3): " . $item["author-link"], LOGGER_DEBUG); } poco_check($profile_url, $item["author-name"], $network, $item["author-avatar"], "", "", "", "", "", $item["received"], $generation, $item["contact-id"], $item["uid"]); // Maybe its a body with a shared item? Then extract a global contact from it. poco_contact_from_body($item["body"], $item["received"], $item["contact-id"], $item["uid"]); }
function poco_load($cid, $uid = 0, $zcid = 0, $url = null) { $a = get_app(); if ($cid) { if (!$url || !$uid) { $r = q("select `poco`, `uid` from `contact` where `id` = %d limit 1", intval($cid)); if (count($r)) { $url = $r[0]['poco']; $uid = $r[0]['uid']; } } if (!$uid) { return; } } if (!$url) { return; } $url = $url . ($uid ? '/@me/@all?fields=displayName,urls,photos' : '?fields=displayName,urls,photos'); logger('poco_load: ' . $url, LOGGER_DEBUG); $s = fetch_url($url); logger('poco_load: returns ' . $s, LOGGER_DATA); logger('poco_load: return code: ' . $a->get_curl_code(), LOGGER_DEBUG); if ($a->get_curl_code() > 299 || !$s) { return; } $j = json_decode($s); logger('poco_load: json: ' . print_r($j, true), LOGGER_DATA); if (!isset($j->entry)) { return; } $total = 0; foreach ($j->entry as $entry) { $total++; $profile_url = ''; $profile_photo = ''; $connect_url = ''; $name = ''; $name = $entry->displayName; if (isset($entry->urls)) { foreach ($entry->urls as $url) { if ($url->type == 'profile') { $profile_url = $url->value; continue; } if ($url->type == 'webfinger') { $connect_url = str_replace('acct:', '', $url->value); continue; } } } if (isset($entry->photos)) { foreach ($entry->photos as $photo) { if ($photo->type == 'profile') { $profile_photo = $photo->value; continue; } } } if (!$name || !$profile_url || !$profile_photo) { continue; } $x = q("select * from `gcontact` where `nurl` = '%s' limit 1", dbesc(normalise_link($profile_url))); if (count($x)) { $gcid = $x[0]['id']; if ($x[0]['name'] != $name || $x[0]['photo'] != $profile_photo) { q("update gcontact set `name` = '%s', `photo` = '%s', `connect` = '%s', `url` = '%s' \n\t\t\t\t\twhere `nurl` = '%s' limit 1", dbesc($name), dbesc($profile_photo), dbesc($connect_url), dbesc($profile_url), dbesc(normalise_link($profile_url))); } } else { q("insert into `gcontact` (`name`,`url`,`nurl`,`photo`,`connect`)\n\t\t\t\tvalues ( '%s', '%s', '%s', '%s','%s') ", dbesc($name), dbesc($profile_url), dbesc(normalise_link($profile_url)), dbesc($profile_photo), dbesc($connect_url)); $x = q("select * from `gcontact` where `nurl` = '%s' limit 1", dbesc(normalise_link($profile_url))); if (count($x)) { $gcid = $x[0]['id']; } } if (!$gcid) { return; } $r = q("select * from glink where `cid` = %d and `uid` = %d and `gcid` = %d and `zcid` = %d limit 1", intval($cid), intval($uid), intval($gcid), intval($zcid)); if (!count($r)) { q("insert into glink ( `cid`,`uid`,`gcid`,`zcid`, `updated`) values (%d,%d,%d,%d, '%s') ", intval($cid), intval($uid), intval($gcid), intval($zcid), dbesc(datetime_convert())); } else { q("update glink set updated = '%s' where `cid` = %d and `uid` = %d and `gcid` = %d and zcid = %d limit 1", dbesc(datetime_convert()), intval($cid), intval($uid), intval($gcid), intval($zcid)); } } logger("poco_load: loaded {$total} entries", LOGGER_DEBUG); q("delete from glink where `cid` = %d and `uid` = %d and `zcid` = %d and `updated` < UTC_TIMESTAMP - INTERVAL 2 DAY", intval($cid), intval($uid), intval($zcid)); }
function randpost_enotify_store(&$a, &$b) { if (!($b['ntype'] == NOTIFY_COMMENT || $b['ntype'] == NOTIFY_TAGSELF)) { return; } if (!get_pconfig($b['uid'], 'randpost', 'enable')) { return; } $fort_server = get_config('fortunate', 'server'); if (!$fort_server) { return; } $c = q("select * from channel where channel_id = %d limit 1", intval($b['uid'])); if (!$c) { return; } $my_conversation = false; $p = q("select id, item_flags, author_xchan from item where parent_mid = mid and parent_mid = '%s' and uid = %d limit 1", dbesc($b['item']['parent_mid']), intval($b['uid'])); if (!$p) { return; } $p = fetch_post_tags($p, true); if (intval($p[0]['item_obscured'])) { return; } if ($b['ntype'] == NOTIFY_TAGSELF) { $my_conversation = true; } elseif ($p[0]['author_xchan'] === $c[0]['channel_hash']) { $my_conversation = true; } elseif ($p[0]['term']) { $v = get_terms_oftype($p[0]['term'], TERM_MENTION); $link = normalise_link(z_root() . '/channel/' . $c[0]['channel_address']); if ($v) { foreach ($v as $vv) { if (link_compare($vv['url'], $link)) { $my_conversation = true; break; } } } } // don't hijack somebody else's conversation, but respond (once) if invited to. if (!$my_conversation) { return; } // This conversation is boring me. $limit = mt_rand(5, 20); $h = q("select id, body from item where author_xchan = '%s' and parent_mid = '%s' and uid = %d", dbesc($c[0]['channel_hash']), dbesc($b['item']['parent_mid']), intval($b['uid'])); if ($h && count($h) > $limit) { return; } // Be gracious and not obnoxious if thanked $replies = array(t('You\'re welcome.'), t('Ah shucks...'), t('Don\'t mention it.'), t('<blush>'), ':like'); // TODO: if you really want to freak somebody out, add a relevance search function to mod_zotfeed and // use somebody's own words from long ago to craft a reply to them.... require_once 'include/bbcode.php'; require_once 'include/html2plain.php'; if ($b['item'] && $b['item']['body']) { if (stristr($b['item']['body'], 'nocomment')) { return; } $txt = preg_replace('/\\@\\[z(.*?)\\[\\/zrl\\]/', '', $b['item']['body']); $txt = html2plain(bbcode($txt)); $pattern = substr($txt, 0, 255); } if ($b['item']['author_xchan']) { $z = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($b['item']['author_xchan'])); if ($z) { $mention = '@' . '[zrl=' . $z[0]['xchan_url'] . ']' . $z[0]['xchan_name'] . '[/zrl]' . "\n\n"; } } if (stristr($b['item']['body'], $c[0]['channel_name']) && mb_strlen($pattern) < 36 && stristr($pattern, 'thank')) { $reply = $replies[mt_rand(0, count($replies) - 1)]; } $x = array(); if ($reply) { $x['body'] = $mention . $reply; } else { require_once 'include/html2bbcode.php'; $valid = false; do { $url = 'http://' . $fort_server . '/cookie.php?f=&lang=any&off=a&pattern=' . urlencode($pattern); $s = z_fetch_url($url); if ($s['success'] && !$s['body']) { $s = z_fetch_url('http://' . $fort_server . '/cookie.php'); } if (!$s['success'] || !$s['body']) { return; } // if it might be a quote make it a quote if (strpos($s['body'], '--')) { $x['body'] = '[quote]' . html2bbcode($s['body']) . '[/quote]'; } else { $x['body'] = html2bbcode($s['body']); } $found_text = false; if ($h) { foreach ($h as $hh) { if (stripos($hh['body'], $x['body']) !== false) { $pattern = ''; $found_text = true; break; } } } if (!$found_text) { $valid = true; } } while (!$valid); } if ($mention) { $x['body'] = $mention . $x['body']; $x['term'] = array(array('uid' => $c[0]['channel_id'], 'type' => TERM_MENTION, 'otype' => TERM_OBJ_POST, 'term' => $z[0]['xchan_name'], 'url' => $z[0]['xchan_url'])); } $x['uid'] = $c[0]['channel_id']; $x['aid'] = $c[0]['channel_account_id']; $x['mid'] = item_message_id(); $x['parent'] = $p[0]['id']; $x['parent_mid'] = $b['item']['parent_mid']; $x['author_xchan'] = $c[0]['channel_hash']; $x['owner_xchan'] = $b['item']['owner_xchan']; $x['item_origin'] = 1; $x['item_verified'] = 1; // You can't pass a Turing test if you reply in milliseconds. // Also I believe we've got ten minutes fudge before we declare a post as time traveling. // Otherwise we'll just set it to now and it will still go out in milliseconds. // So set the reply to post sometime in the next 15-45 minutes (depends on poller interval) $fudge = mt_rand(15, 30); $x['created'] = $x['edited'] = datetime_convert('UTC', 'UTC', 'now + ' . $fudge . ' minutes'); $x['body'] = trim($x['body']); $x['sig'] = base64url_encode(rsa_sign($x['body'], $c[0]['channel_prvkey'])); $post = item_store($x); $post_id = $post['item_id']; $x['id'] = $post_id; call_hooks('post_local_end', $x); Zotlabs\Daemon\Master::Summon(array('Notifier', 'comment-new', $post_id)); }
/** * @function tgroup_check($uid,$item) * * This function is called pre-deliver to see if a post matches the criteria to be tag delivered. * We don't actually do anything except check that it matches the criteria. * This is so that the channel with tag_delivery enabled can receive the post even if they turn off * permissions for the sender to send their stream. tag_deliver() can't be called until the post is actually stored. * By then it would be too late to reject it. */ function tgroup_check($uid, $item) { $a = get_app(); $mention = false; // check that the message originated elsewhere and is a top-level post // or is a followup and we have already accepted the top level post as an uplink if ($item['mid'] != $item['parent_mid']) { $r = q("select id from item where mid = '%s' and uid = %d and ( item_flags & %d ) limit 1", dbesc($item['parent_mid']), intval($uid), intval(ITEM_UPLINK)); if ($r) { return true; } return false; } if (!perm_is_allowed($uid, $item['author_xchan'], 'tag_deliver')) { return false; } $u = q("select * from channel where channel_id = %d limit 1", intval($uid)); if (!$u) { return false; } $terms = get_terms_oftype($item['term'], TERM_MENTION); if ($terms) { logger('tgroup_check: post mentions: ' . print_r($terms, true), LOGGER_DATA); } $link = normalise_link($a->get_baseurl() . '/channel/' . $u[0]['channel_address']); if ($terms) { foreach ($terms as $term) { if (link_compare($term['url'], $link)) { $mention = true; break; } } } if ($mention) { logger('tgroup_check: mention found for ' . $u[0]['channel_name']); } else { return false; } // At this point we've determined that the person receiving this post was mentioned in it. // Now let's check if this mention was inside a reshare so we don't spam a forum $body = preg_replace('/\\[share(.*?)\\[\\/share\\]/', '', $item['body']); $pattern = '/@\\!?\\[zrl\\=' . preg_quote($term['url'], '/') . '\\]' . preg_quote($term['term'] . '+', '/') . '\\[\\/zrl\\]/'; if (!preg_match($pattern, $body, $matches)) { logger('tgroup_check: mention was in a reshare - ignoring'); return false; } return true; }