function lostpass_content(&$a) { if (x($_GET, 'verify')) { $verify = $_GET['verify']; $hash = hash('whirlpool', $verify); $r = q("SELECT * FROM `user` WHERE `pwdreset` = '%s' LIMIT 1", dbesc($hash)); if (!count($r)) { notice(t("Request could not be verified. (You may have previously submitted it.) Password reset failed.") . EOL); goaway(z_root()); return; } $uid = $r[0]['uid']; $username = $r[0]['username']; $email = $r[0]['email']; $new_password = autoname(6) . mt_rand(100, 9999); $new_password_encoded = hash('whirlpool', $new_password); $r = q("UPDATE `user` SET `password` = '%s', `pwdreset` = '' WHERE `uid` = %d LIMIT 1", dbesc($new_password_encoded), intval($uid)); if ($r) { $tpl = get_markup_template('pwdreset.tpl'); $o .= replace_macros($tpl, array('$lbl1' => t('Password Reset'), '$lbl2' => t('Your password has been reset as requested.'), '$lbl3' => t('Your new password is'), '$lbl4' => t('Save or copy your new password - and then'), '$lbl5' => '<a href="' . $a->get_baseurl() . '">' . t('click here to login') . '</a>.', '$lbl6' => t('Your password may be changed from the <em>Settings</em> page after successful login.'), '$newpass' => $new_password, '$baseurl' => $a->get_baseurl())); info("Your password has been reset." . EOL); $email_tpl = get_intltext_template("passchanged_eml.tpl"); $email_tpl = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $username, '$email' => $email, '$new_password' => $new_password, '$uid' => $newuid)); $res = mail($email, "Your password has changed at {$a->config['sitename']}", $email_tpl, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); return $o; } } else { $tpl = get_markup_template('lostpass.tpl'); $o .= replace_macros($tpl, array('$title' => t('Forgot your Password?'), '$desc' => t('Enter your email address and submit to have your password reset. Then check your email for further instructions.'), '$name' => t('Nickname or Email: '), '$submit' => t('Reset'))); return $o; } }
function lostpass_content(&$a) { if (x($_GET, 'verify')) { $verify = $_GET['verify']; $r = q("SELECT * FROM account WHERE account_reset = '%s' LIMIT 1", dbesc($verify)); if (!$r) { notice(t("Request could not be verified. (You may have previously submitted it.) Password reset failed.") . EOL); goaway(z_root()); return; } $aid = $r[0]['account_id']; $email = $r[0]['account_email']; $new_password = autoname(6) . mt_rand(100, 9999); $salt = random_string(32); $password_encoded = hash('whirlpool', $salt . $new_password); $r = q("UPDATE account SET account_salt = '%s', account_password = '******', account_reset = '', account_flags = (account_flags & ~%d) where account_id = %d", dbesc($salt), dbesc($password_encoded), intval(ACCOUNT_UNVERIFIED), intval($aid)); if ($r) { $tpl = get_markup_template('pwdreset.tpl'); $o .= replace_macros($tpl, array('$lbl1' => t('Password Reset'), '$lbl2' => t('Your password has been reset as requested.'), '$lbl3' => t('Your new password is'), '$lbl4' => t('Save or copy your new password - and then'), '$lbl5' => '<a href="' . $a->get_baseurl() . '">' . t('click here to login') . '</a>.', '$lbl6' => t('Your password may be changed from the <em>Settings</em> page after successful login.'), '$newpass' => $new_password, '$baseurl' => $a->get_baseurl())); info("Your password has been reset." . EOL); $email_tpl = get_intltext_template("passchanged_eml.tpl"); $message = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => sprintf(t('Site Member (%s)'), $email), '$email' => $email, '$new_password' => $new_password, '$uid' => $newuid)); $subject = email_header_encode(sprintf(t('Your password has changed at %s'), get_config('system', 'sitename')), 'UTF-8'); $res = mail($email, $subject, $message, 'From: ' . 'Administrator@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); return $o; } } else { $tpl = get_markup_template('lostpass.tpl'); $o .= replace_macros($tpl, array('$title' => t('Forgot your Password?'), '$desc' => t('Enter your email address and submit to have your password reset. Then check your email for further instructions.'), '$name' => t('Email Address'), '$submit' => t('Reset'))); return $o; } }
function user_allow($hash) { $a = get_app(); $register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($hash)); if (!count($register)) { return false; } $user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($register[0]['uid'])); if (!count($user)) { killme(); } $r = q("DELETE FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($register[0]['hash'])); $r = q("UPDATE `user` SET `blocked` = 0, `verified` = 1 WHERE `uid` = %d LIMIT 1", intval($register[0]['uid'])); $r = q("SELECT * FROM `profile` WHERE `uid` = %d AND `is-default` = 1", intval($user[0]['uid'])); if (count($r) && $r[0]['net-publish']) { $url = $a->get_baseurl() . '/profile/' . $user[0]['nickname']; if ($url && strlen(get_config('system', 'directory_submit_url'))) { proc_run('php', "include/directory.php", "{$url}"); } } push_lang($register[0]['language']); $email_tpl = get_intltext_template("register_open_eml.tpl"); $email_tpl = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $user[0]['username'], '$email' => $user[0]['email'], '$password' => $register[0]['password'], '$uid' => $user[0]['uid'])); $res = mail($user[0]['email'], sprintf(t('Registration details for %s'), $a->config['sitename']), $email_tpl, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); pop_lang(); if ($res) { info(t('Account approved.') . EOL); return true; } }
function install_post(&$a) { global $db; $urlpath = $a->get_path(); $dbhost = notags(trim($_POST['dbhost'])); $dbuser = notags(trim($_POST['dbuser'])); $dbpass = notags(trim($_POST['dbpass'])); $dbdata = notags(trim($_POST['dbdata'])); $timezone = notags(trim($_POST['timezone'])); $phpath = notags(trim($_POST['phpath'])); $adminmail = notags(trim($_POST['adminmail'])); require_once "dba.php"; unset($db); $db = new dba($dbhost, $dbuser, $dbpass, $dbdata, true); if (get_db_errno()) { unset($db); $db = new dba($dbhost, $dbuser, $dbpass, '', true); if (!get_db_errno()) { $r = q("CREATE DATABASE '%s'", dbesc($dbdata)); if ($r) { unset($db); $db = new dba($dbhost, $dbuser, $dbpass, $dbdata, true); } } if (get_db_errno()) { notice(t('Could not create/connect to database.') . EOL); return; } } info(t('Connected to database.') . EOL); $tpl = get_intltext_template('htconfig.tpl'); $txt = replace_macros($tpl, array('$dbhost' => $dbhost, '$dbuser' => $dbuser, '$dbpass' => $dbpass, '$dbdata' => $dbdata, '$timezone' => $timezone, '$urlpath' => $urlpath, '$phpath' => $phpath, '$adminmail' => $adminmail)); $result = file_put_contents('.htconfig.php', $txt); if (!$result) { $a->data['txt'] = $txt; } $errors = load_database($db); if ($errors) { $a->data['db_failed'] = true; } else { $a->data['db_installed'] = true; } return; }
function register_post(&$a) { global $lang; $verified = 0; $blocked = 1; switch ($a->config['register_policy']) { case REGISTER_OPEN: $blocked = 0; $verified = 1; break; case REGISTER_APPROVE: $blocked = 1; $verified = 0; break; default: case REGISTER_CLOSED: if (!x($_SESSION, 'authenticated') && !x($_SESSION, 'administrator')) { notice(t('Permission denied.') . EOL); return; } $blocked = 1; $verified = 0; break; } $using_invites = get_config('system', 'invitation_only'); $num_invites = get_config('system', 'number_invites'); $invite_id = x($_POST, 'invite_id') ? notags(trim($_POST['invite_id'])) : ''; $username = x($_POST, 'username') ? notags(trim($_POST['username'])) : ''; $nickname = x($_POST, 'nickname') ? notags(trim($_POST['nickname'])) : ''; $email = x($_POST, 'email') ? notags(trim($_POST['email'])) : ''; $openid_url = x($_POST, 'openid_url') ? notags(trim($_POST['openid_url'])) : ''; $photo = x($_POST, 'photo') ? notags(trim($_POST['photo'])) : ''; $publish = x($_POST, 'profile_publish_reg') && intval($_POST['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) { notice(t('An invitation is required.') . EOL); return; } $r = q("select * from register where `hash` = '%s' limit 1", dbesc($invite_id)); if (!results($r)) { notice(t('Invitation could not be verified.') . EOL); return; } } if (!x($username) || !x($email) || !x($nickname)) { if ($openid_url) { if (!validate_url($tmp_str)) { notice(t('Invalid OpenID url') . EOL); return; } $_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'); goaway($openid->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) { $err .= t('Please use a shorter name.') . EOL; } if (mb_strlen($username) < 3) { $err .= 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, ' ')) { $err .= t("That doesn't appear to be your full (First Last) name.") . EOL; } } if (!allowed_email($email)) { $err .= t('Your email domain is not among those allowed on this site.') . EOL; } if (!valid_email($email) || !validate_email($email)) { $err .= 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. if (x($a->config, 'admin_email') && strcasecmp($email, $a->config['admin_email']) == 0 && strlen($openid_url)) { $r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1", dbesc($email)); if (count($r)) { $err .= t('Cannot use that email.') . EOL; } } $nickname = $_POST['nickname'] = strtolower($nickname); if (!preg_match("/^[a-z][a-z0-9\\-\\_]*\$/", $nickname)) { $err .= 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)) { $err .= t('Nickname is already registered. Please choose another.') . EOL; } if (strlen($err)) { notice($err); return; } $new_password = autoname(6) . mt_rand(100, 9999); $new_password_encoded = hash('whirlpool', $new_password); $res = openssl_pkey_new(array('digest_alg' => 'sha1', 'private_key_bits' => 4096, 'encrypt_key' => false)); // Get private key if (empty($res)) { notice(t('SERIOUS ERROR: Generation of security keys failed.') . EOL); return; } $prvkey = ''; openssl_pkey_export($res, $prvkey); // Get public key $pkey = openssl_pkey_get_details($res); $pubkey = $pkey["key"]; /** * * 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 = openssl_pkey_new(array('digest_alg' => 'sha1', 'private_key_bits' => 512, 'encrypt_key' => false)); // Get private key $sprvkey = ''; openssl_pkey_export($sres, $sprvkey); // Get public key $spkey = openssl_pkey_get_details($sres); $spubkey = $spkey["key"]; $r = q("INSERT INTO `user` ( `guid`, `username`, `password`, `email`, `openid`, `nickname`,\n\t\t`pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked` )\n\t\tVALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )", 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)); if ($r) { $r = q("SELECT `uid` FROM `user` \n\t\t\tWHERE `username` = '%s' AND `password` = '%s' LIMIT 1", dbesc($username), dbesc($new_password_encoded)); if ($r !== false && count($r)) { $newuid = intval($r[0]['uid']); } } else { notice(t('An error occurred during registration. Please try again.') . EOL); return; } /** * 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) { $err .= t('Nickname is already registered. Please choose another.') . EOL; q("DELETE FROM `user` WHERE `uid` = %d LIMIT 1", intval($newuid)); notice($err); return; } 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), '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) { notice(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; } $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` )\n\t\t\tVALUES ( %d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", 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())); } $use_gravatar = get_config('system', 'no_gravatar') ? false : true; // if we have an openid photo use it. // otherwise unless it is disabled, use gravatar if ($use_gravatar || strlen($photo)) { require_once 'include/Photo.php'; if ($use_gravatar && !strlen($photo)) { $photo = gravatar_img($email); } $photo_failure = false; $filename = basename($photo); $img_str = fetch_url($photo, true); $img = new Photo($img_str); 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)); } } } if ($netpublish && $a->config['register_policy'] != REGISTER_APPROVE) { $url = $a->get_baseurl() . "/profile/{$nickname}"; proc_run('php', "include/directory.php", "{$url}"); } call_hooks('register_account', $newuid); if ($a->config['register_policy'] == REGISTER_OPEN) { if ($using_invites && $invite_id) { q("delete * from register where hash = '%s' limit 1", dbesc($invite_id)); set_pconfig($newuid, 'system', 'invites_remaining', $num_invites); } $email_tpl = get_intltext_template("register_open_eml.tpl"); $email_tpl = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $username, '$email' => $email, '$password' => $new_password, '$uid' => $newuid)); $res = mail($email, sprintf(t('Registration details for %s'), $a->config['sitename']), $email_tpl, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); if ($res) { info(t('Registration successful. Please check your email for further instructions.') . EOL); goaway(z_root()); } else { notice(t('Failed to send email message. Here is the message that failed.') . $email_tpl . EOL); } } elseif ($a->config['register_policy'] == REGISTER_APPROVE) { if (!strlen($a->config['admin_email'])) { notice(t('Your registration can not be processed.') . EOL); goaway(z_root()); } $hash = random_string(); $r = q("INSERT INTO `register` ( `hash`, `created`, `uid`, `password`, `language` ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ", dbesc($hash), dbesc(datetime_convert()), intval($newuid), dbesc($new_password), dbesc($lang)); $r = q("SELECT `language` FROM `user` WHERE `email` = '%s' LIMIT 1", dbesc($a->config['admin_email'])); if (count($r)) { push_lang($r[0]['language']); } else { push_lang('en'); } if ($using_invites && $invite_id) { q("delete * from register where hash = '%s' limit 1", dbesc($invite_id)); set_pconfig($newuid, 'system', 'invites_remaining', $num_invites); } $email_tpl = get_intltext_template("register_verify_eml.tpl"); $email_tpl = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $username, '$email' => $email, '$password' => $new_password, '$uid' => $newuid, '$hash' => $hash)); $res = mail($a->config['admin_email'], sprintf(t('Registration request at %s'), $a->config['sitename']), $email_tpl, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); pop_lang(); if ($res) { info(t('Your registration is pending approval by the site owner.') . EOL); goaway(z_root()); } } return; }
function check_config(&$a) { $build = get_config('system', 'db_version'); if (!intval($build)) { $build = set_config('system', 'db_version', DB_UPDATE_VERSION); } $saved = get_config('system', 'urlverify'); if (!$saved) { set_config('system', 'urlverify', bin2hex(z_root())); } if ($saved && $saved != bin2hex(z_root())) { // our URL changed. Do something. $oldurl = hex2bin($saved); logger('Baseurl changed!'); $oldhost = substr($oldurl, strpos($oldurl, '//') + 2); $host = substr(z_root(), strpos(z_root(), '//') + 2); $is_ip_addr = preg_match("/^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\$/", $host) ? true : false; $was_ip_addr = preg_match("/^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\$/", $oldhost) ? true : false; // only change the url to an ip address if it was already an ip and not a dns name if (!$is_ip_addr || $is_ip_addr && $was_ip_addr) { fix_system_urls($oldurl, z_root()); set_config('system', 'urlverify', bin2hex(z_root())); } else { logger('Attempt to change baseurl from a DNS name to an IP address was refused.'); } } // This will actually set the url to the one stored in .htconfig, and ignore what // we're passing - unless we are installing and it has never been set. $a->set_baseurl($a->get_baseurl()); // Make sure each site has a system channel. This is now created on install // so we just need to keep this around a couple of weeks until the hubs that // already exist have one $syschan_exists = get_sys_channel(); if (!$syschan_exists) { create_sys_channel(); } if ($build != DB_UPDATE_VERSION) { $stored = intval($build); if (!$stored) { logger('Critical: check_config unable to determine database schema version'); return; } $current = intval(DB_UPDATE_VERSION); if ($stored < $current && file_exists('install/update.php')) { load_config('database'); // We're reporting a different version than what is currently installed. // Run any existing update scripts to bring the database up to current. require_once 'install/update.php'; // make sure that boot.php and update.php are the same release, we might be // updating right this very second and the correct version of the update.php // file may not be here yet. This can happen on a very busy site. if (DB_UPDATE_VERSION == UPDATE_VERSION) { for ($x = $stored; $x < $current; $x++) { if (function_exists('update_r' . $x)) { // There could be a lot of processes running or about to run. // We want exactly one process to run the update command. // So store the fact that we're taking responsibility // after first checking to see if somebody else already has. // If the update fails or times-out completely you may need to // delete the config entry to try again. if (get_config('database', 'update_r' . $x)) { break; } set_config('database', 'update_r' . $x, '1'); // call the specific update $func = 'update_r' . $x; $retval = $func(); if ($retval) { // Prevent sending hundreds of thousands of emails by creating // a lockfile. $lockfile = 'store/[data]/mailsent'; if (file_exists($lockfile) && filemtime($lockfile) > time() - 86400) { return; } @unlink($lockfile); //send the administrator an e-mail file_put_contents($lockfile, $x); $email_tpl = get_intltext_template("update_fail_eml.tpl"); $email_msg = replace_macros($email_tpl, array('$sitename' => $a->config['system']['sitename'], '$siteurl' => $a->get_baseurl(), '$update' => $x, '$error' => sprintf(t('Update %s failed. See error logs.'), $x))); $subject = email_header_encode(sprintf(t('Update Error at %s'), $a->get_baseurl())); mail($a->config['system']['admin_email'], $subject, $email_msg, 'From: Administrator' . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); //try the logger logger('CRITICAL: Update Failed: ' . $x); } else { set_config('database', 'update_r' . $x, 'success'); } } } set_config('system', 'db_version', DB_UPDATE_VERSION); } } } /** * * Synchronise plugins: * * $a->config['system']['addon'] contains a comma-separated list of names * of plugins/addons which are used on this system. * Go through the database list of already installed addons, and if we have * an entry, but it isn't in the config list, call the unload procedure * and mark it uninstalled in the database (for now we'll remove it). * Then go through the config list and if we have a plugin that isn't installed, * call the install procedure and add it to the database. * */ $r = q("SELECT * FROM `addon` WHERE `installed` = 1"); if ($r) { $installed = $r; } else { $installed = array(); } $plugins = get_config('system', 'addon'); $plugins_arr = array(); if ($plugins) { $plugins_arr = explode(',', str_replace(' ', '', $plugins)); } $a->plugins = $plugins_arr; $installed_arr = array(); if (count($installed)) { foreach ($installed as $i) { if (!in_array($i['name'], $plugins_arr)) { unload_plugin($i['name']); } else { $installed_arr[] = $i['name']; } } } if (count($plugins_arr)) { foreach ($plugins_arr as $p) { if (!in_array($p, $installed_arr)) { load_plugin($p); } } } load_hooks(); return; }
/** * @brief Handle the actions of the different setup steps. * */ function post() { switch ($this->install_wizard_pass) { case 1: case 2: return; // implied break; // implied break; case 3: $urlpath = \App::get_path(); $dbhost = trim($_POST['dbhost']); $dbport = intval(trim($_POST['dbport'])); $dbuser = trim($_POST['dbuser']); $dbpass = trim($_POST['dbpass']); $dbdata = trim($_POST['dbdata']); $dbtype = intval(trim($_POST['dbtype'])); $phpath = trim($_POST['phpath']); $adminmail = trim($_POST['adminmail']); $siteurl = trim($_POST['siteurl']); $advanced = intval($_POST['advanced']) ? 1 : 0; // $siteurl should not have a trailing slash $siteurl = rtrim($siteurl, '/'); require_once 'include/dba/dba_driver.php'; $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true); if (!\DBA::$dba->connected) { echo 'Database Connect failed: ' . DBA::$dba->error; killme(); } return; // implied break; // implied break; case 4: $urlpath = \App::get_path(); $dbhost = notags(trim($_POST['dbhost'])); $dbport = intval(notags(trim($_POST['dbport']))); $dbuser = notags(trim($_POST['dbuser'])); $dbpass = notags(trim($_POST['dbpass'])); $dbdata = notags(trim($_POST['dbdata'])); $dbtype = intval(notags(trim($_POST['dbtype']))); $phpath = notags(trim($_POST['phpath'])); $timezone = notags(trim($_POST['timezone'])); $adminmail = notags(trim($_POST['adminmail'])); $siteurl = notags(trim($_POST['siteurl'])); $advanced = intval($_POST['advanced']) ? 1 : 0; if ($siteurl != z_root()) { $test = z_fetch_url($siteurl . "/setup/testrewrite"); if (!$test['success'] || $test['body'] != 'ok') { \App::$data['url_fail'] = true; \App::$data['url_error'] = $test['error']; return; } } if (!\DBA::$dba->connected) { // connect to db $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true); } if (!\DBA::$dba->connected) { echo 'CRITICAL: DB not connected.'; killme(); } $tpl = get_intltext_template('htconfig.tpl'); $txt = replace_macros($tpl, array('$dbhost' => $dbhost, '$dbport' => $dbport, '$dbuser' => $dbuser, '$dbpass' => $dbpass, '$dbdata' => $dbdata, '$dbtype' => $dbtype, '$uno' => 1 - $advanced, '$timezone' => $timezone, '$siteurl' => $siteurl, '$site_id' => random_string(), '$phpath' => $phpath, '$adminmail' => $adminmail)); $result = file_put_contents('.htconfig.php', $txt); if (!$result) { \App::$data['txt'] = $txt; } $errors = $this->load_database($db); if ($errors) { \App::$data['db_failed'] = $errors; } else { \App::$data['db_installed'] = true; } return; // implied break; // implied break; default: break; } }
function update_db(&$a) { $build = get_config('system', 'build'); if (!x($build)) { $build = set_config('system', 'build', DB_UPDATE_VERSION); } if ($build != DB_UPDATE_VERSION) { $stored = intval($build); $current = intval(DB_UPDATE_VERSION); if ($stored < $current && file_exists('update.php')) { load_config('database'); // We're reporting a different version than what is currently installed. // Run any existing update scripts to bring the database up to current. require_once 'update.php'; // make sure that boot.php and update.php are the same release, we might be // updating right this very second and the correct version of the update.php // file may not be here yet. This can happen on a very busy site. if (DB_UPDATE_VERSION == UPDATE_VERSION) { for ($x = $stored; $x < $current; $x++) { if (function_exists('update_' . $x)) { // There could be a lot of processes running or about to run. // We want exactly one process to run the update command. // So store the fact that we're taking responsibility // after first checking to see if somebody else already has. // If the update fails or times-out completely you may need to // delete the config entry to try again. $t = get_config('database', 'update_' . $x); if ($t !== false) { break; } set_config('database', 'update_' . $x, time()); // call the specific update $func = 'update_' . $x; $retval = $func(); if ($retval) { //send the administrator an e-mail $email_tpl = get_intltext_template("update_fail_eml.tpl"); $email_msg = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$update' => $x, '$error' => sprintf(t('Update %s failed. See error logs.'), $x))); $subject = sprintf(t('Update Error at %s'), $a->get_baseurl()); require_once 'include/email.php'; $subject = email_header_encode($subject, 'UTF-8'); mail($a->config['admin_email'], $subject, $email_msg, 'From: ' . 'Administrator' . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); //try the logger logger('CRITICAL: Update Failed: ' . $x); break; } else { set_config('database', 'update_' . $x, 'success'); set_config('system', 'build', $x + 1); } } } } } } return; }
/** * @brief Allows a user registration. * * @param string $hash * @return array|boolean */ function account_allow($hash) { $ret = array('success' => false); $register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($hash)); if (!$register) { return $ret; } $account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1", intval($register[0]['uid'])); if (!$account) { return $ret; } $r = q("DELETE FROM register WHERE hash = '%s'", dbesc($register[0]['hash'])); $r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d", intval(ACCOUNT_BLOCKED), intval(ACCOUNT_BLOCKED), intval($register[0]['uid'])); $r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d", intval(ACCOUNT_PENDING), intval(ACCOUNT_PENDING), intval($register[0]['uid'])); push_lang($register[0]['language']); $email_tpl = get_intltext_template("register_open_eml.tpl"); $email_tpl = replace_macros($email_tpl, array('$sitename' => get_config('system', 'sitename'), '$siteurl' => z_root(), '$username' => $account[0]['account_email'], '$email' => $account[0]['account_email'], '$password' => '', '$uid' => $account[0]['account_id'])); $res = mail($account[0]['account_email'], sprintf(t('Registration details for %s'), get_config('system', 'sitename')), $email_tpl, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); pop_lang(); if (get_config('system', 'auto_channel_create')) { auto_channel_create($register[0]['uid']); } if ($res) { info(t('Account approved.') . EOL); return true; } }
/** * @brief Allows a user registration. * * @param string $hash * @return array|boolean */ function account_allow($hash) { $ret = array('success' => false); $register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($hash)); if (!$register) { return $ret; } $account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1", intval($register[0]['uid'])); if (!$account) { return $ret; } $r = q("DELETE FROM register WHERE hash = '%s'", dbesc($register[0]['hash'])); $r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d", intval(ACCOUNT_BLOCKED), intval(ACCOUNT_BLOCKED), intval($register[0]['uid'])); $r = q("update account set account_flags = (account_flags & ~%d) where (account_flags & %d)>0 and account_id = %d", intval(ACCOUNT_PENDING), intval(ACCOUNT_PENDING), intval($register[0]['uid'])); push_lang($register[0]['lang']); $email_tpl = get_intltext_template("register_open_eml.tpl"); $email_msg = replace_macros($email_tpl, array('$sitename' => get_config('system', 'sitename'), '$siteurl' => z_root(), '$username' => $account[0]['account_email'], '$email' => $account[0]['account_email'], '$password' => '', '$uid' => $account[0]['account_id'])); $res = z_mail(['toEmail' => $account[0]['account_email'], 'messageSubject' => sprintf(t('Registration details for %s'), get_config('system', 'sitename')), 'textVersion' => $email_msg]); pop_lang(); if (get_config('system', 'auto_channel_create') || get_config('system', 'server_role') === 'basic') { auto_channel_create($register[0]['uid']); } if ($res) { info(t('Account approved.') . EOL); return true; } }
function new_follower($importer, $contact, $datarray, $item, $sharing = false) { $url = notags(trim($datarray['author-link'])); $name = notags(trim($datarray['author-name'])); $photo = notags(trim($datarray['author-avatar'])); $rawtag = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor'); if ($rawtag && $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data']) { $nick = $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data']; } if (is_array($contact)) { if ($contact['network'] == NETWORK_OSTATUS && $contact['rel'] == CONTACT_IS_SHARING || $sharing && $contact['rel'] == CONTACT_IS_FOLLOWER) { $r = q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1", intval(CONTACT_IS_FRIEND), intval($contact['id']), intval($importer['uid'])); } // send email notification to owner? } else { // create contact record $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`, \n\t\t\t`blocked`, `readonly`, `pending`, `writable` )\n\t\t\tVALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, 1 ) ", intval($importer['uid']), dbesc(datetime_convert()), dbesc($url), dbesc(normalise_link($url)), dbesc($name), dbesc($nick), dbesc($photo), dbesc($sharing ? NETWORK_ZOT : NETWORK_OSTATUS), intval($sharing ? CONTACT_IS_SHARING : CONTACT_IS_FOLLOWER)); $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `pending` = 1 LIMIT 1", intval($importer['uid']), dbesc($url)); if (count($r)) { $contact_record = $r[0]; } // create notification $hash = random_string(); if (is_array($contact_record)) { $ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `hash`, `datetime`)\n\t\t\t\tVALUES ( %d, %d, 0, 0, '%s', '%s' )", intval($importer['uid']), intval($contact_record['id']), dbesc($hash), dbesc(datetime_convert())); } $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer['uid'])); $a = get_app(); if (count($r)) { if (intval($r[0]['def_gid'])) { require_once 'include/group.php'; group_add_member($r[0]['uid'], '', $contact_record['id'], $r[0]['def_gid']); } if ($r[0]['notify-flags'] & NOTIFY_INTRO && $r[0]['page-flags'] == PAGE_NORMAL) { $email_tpl = get_intltext_template('follow_notify_eml.tpl'); $email = replace_macros($email_tpl, array('$requestor' => strlen($name) ? $name : t('[Name Withheld]'), '$url' => $url, '$myname' => $r[0]['username'], '$siteurl' => $a->get_baseurl(), '$sitename' => $a->config['sitename'])); $res = mail($r[0]['email'], ($sharing ? t('A new person is sharing with you at ') : t("You have a new follower at ")) . $a->config['sitename'], $email, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); } } } }
function dfrn_confirm_post(&$a, $handsfree = null) { if (is_array($handsfree)) { /** * We were called directly from dfrn_request due to automatic friend acceptance. * Any $_POST parameters we may require are supplied in the $handsfree array. * */ $node = $handsfree['node']; $a->interactive = false; // notice() becomes a no-op since nobody is there to see it } else { if ($a->argc > 1) { $node = $a->argv[1]; } } /** * * Main entry point. Scenario 1. Our user received a friend request notification (perhaps * from another site) and clicked 'Approve'. * $POST['source_url'] is not set. If it is, it indicates Scenario 2. * * We may also have been called directly from dfrn_request ($handsfree != null) due to * this being a page type which supports automatic friend acceptance. That is also Scenario 1 * since we are operating on behalf of our registered user to approve a friendship. * */ if (!x($_POST, 'source_url')) { $uid = is_array($handsfree) ? $handsfree['uid'] : local_user(); if (!$uid) { notice(t('Permission denied.') . EOL); return; } $user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid)); if (!$user) { notice(t('Profile not found.') . EOL); return; } // These data elements may come from either the friend request notification form or $handsfree array. if (is_array($handsfree)) { logger('dfrn_confirm: Confirm in handsfree mode'); $dfrn_id = $handsfree['dfrn_id']; $intro_id = $handsfree['intro_id']; $duplex = $handsfree['duplex']; $hidden = array_key_exists('hidden', $handsfree) ? intval($handsfree['hidden']) : 0; $activity = array_key_exists('activity', $handsfree) ? intval($handsfree['activity']) : 0; } else { $dfrn_id = x($_POST, 'dfrn_id') ? notags(trim($_POST['dfrn_id'])) : ""; $intro_id = x($_POST, 'intro_id') ? intval($_POST['intro_id']) : 0; $duplex = x($_POST, 'duplex') ? intval($_POST['duplex']) : 0; $cid = x($_POST, 'contact_id') ? intval($_POST['contact_id']) : 0; $hidden = x($_POST, 'hidden') ? intval($_POST['hidden']) : 0; $activity = x($_POST, 'activity') ? intval($_POST['activity']) : 0; } /** * * Ensure that dfrn_id has precedence when we go to find the contact record. * We only want to search based on contact id if there is no dfrn_id, * e.g. for OStatus network followers. * */ if (strlen($dfrn_id)) { $cid = 0; } logger('dfrn_confirm: Confirming request for dfrn_id (issued) ' . $dfrn_id); if ($cid) { logger('dfrn_confirm: Confirming follower with contact_id: ' . $cid); } /** * * The other person will have been issued an ID when they first requested friendship. * Locate their record. At this time, their record will have both pending and blocked set to 1. * There won't be any dfrn_id if this is a network follower, so use the contact_id instead. * */ $r = q("SELECT * FROM `contact` WHERE ( ( `issued-id` != '' AND `issued-id` = '%s' ) OR ( `id` = %d AND `id` != 0 ) ) AND `uid` = %d AND `duplex` = 0 LIMIT 1", dbesc($dfrn_id), intval($cid), intval($uid)); if (!count($r)) { logger('dfrn_confirm: Contact not found in DB.'); notice(t('Contact not found.') . EOL); notice(t('This may occasionally happen if contact was requested by both persons and it has already been approved.') . EOL); return; } $contact = $r[0]; $contact_id = $contact['id']; $relation = $contact['rel']; $site_pubkey = $contact['site-pubkey']; $dfrn_confirm = $contact['confirm']; $aes_allow = $contact['aes_allow']; $network = strlen($contact['issued-id']) ? NETWORK_DFRN : NETWORK_OSTATUS; if ($contact['network']) { $network = $contact['network']; } if ($network === NETWORK_DFRN) { /** * * Generate a key pair for all further communications with this person. * We have a keypair for every contact, and a site key for unknown people. * This provides a means to carry on relationships with other people if * any single key is compromised. It is a robust key. We're much more * worried about key leakage than anybody cracking it. * */ require_once 'include/crypto.php'; $res = new_keypair(4096); $private_key = $res['prvkey']; $public_key = $res['pubkey']; // Save the private key. Send them the public key. $r = q("UPDATE `contact` SET `prvkey` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($private_key), intval($contact_id), intval($uid)); $params = array(); /** * * Per the DFRN protocol, we will verify both ends by encrypting the dfrn_id with our * site private key (person on the other end can decrypt it with our site public key). * Then encrypt our profile URL with the other person's site public key. They can decrypt * it with their site private key. If the decryption on the other end fails for either * item, it indicates tampering or key failure on at least one site and we will not be * able to provide a secure communication pathway. * * If other site is willing to accept full encryption, (aes_allow is 1 AND we have php5.3 * or later) then we encrypt the personal public key we send them using AES-256-CBC and a * random key which is encrypted with their site public key. * */ $src_aes_key = random_string(); $result = ''; openssl_private_encrypt($dfrn_id, $result, $user[0]['prvkey']); $params['dfrn_id'] = bin2hex($result); $params['public_key'] = $public_key; $my_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname']; openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey); $params['source_url'] = bin2hex($params['source_url']); if ($aes_allow && function_exists('openssl_encrypt')) { openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey); $params['aes_key'] = bin2hex($params['aes_key']); $params['public_key'] = bin2hex(openssl_encrypt($public_key, 'AES-256-CBC', $src_aes_key)); } $params['dfrn_version'] = DFRN_PROTOCOL_VERSION; if ($duplex == 1) { $params['duplex'] = 1; } if ($user[0]['page-flags'] == PAGE_COMMUNITY) { $params['page'] = 1; } if ($user[0]['page-flags'] == PAGE_PRVGROUP) { $params['page'] = 2; } logger('dfrn_confirm: Confirm: posting data to ' . $dfrn_confirm . ': ' . print_r($params, true), LOGGER_DATA); /** * * POST all this stuff to the other site. * Temporarily raise the network timeout to 120 seconds because the default 60 * doesn't always give the other side quite enough time to decrypt everything. * */ $a->config['system']['curl_timeout'] = 120; $res = post_url($dfrn_confirm, $params); logger('dfrn_confirm: Confirm: received data: ' . $res, LOGGER_DATA); // Now figure out what they responded. Try to be robust if the remote site is // having difficulty and throwing up errors of some kind. $leading_junk = substr($res, 0, strpos($res, '<?xml')); $res = substr($res, strpos($res, '<?xml')); if (!strlen($res)) { // No XML at all, this exchange is messed up really bad. // We shouldn't proceed, because the xml parser might choke, // and $status is going to be zero, which indicates success. // We can hardly call this a success. notice(t('Response from remote site was not understood.') . EOL); return; } if (strlen($leading_junk) && get_config('system', 'debugging')) { // This might be more common. Mixed error text and some XML. // If we're configured for debugging, show the text. Proceed in either case. notice(t('Unexpected response from remote site: ') . EOL . $leading_junk . EOL); } $xml = parse_xml_string($res); $status = (int) $xml->status; $message = unxmlify($xml->message); // human readable text of what may have gone wrong. switch ($status) { case 0: info(t("Confirmation completed successfully.") . EOL); if (strlen($message)) { notice(t('Remote site reported: ') . $message . EOL); } break; case 1: // birthday paradox - generate new dfrn-id and fall through. $new_dfrn_id = random_string(); $r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($new_dfrn_id), intval($contact_id), intval($uid)); case 2: notice(t("Temporary failure. Please wait and try again.") . EOL); if (strlen($message)) { notice(t('Remote site reported: ') . $message . EOL); } break; case 3: notice(t("Introduction failed or was revoked.") . EOL); if (strlen($message)) { notice(t('Remote site reported: ') . $message . EOL); } break; } if ($status == 0 && $intro_id) { // Success. Delete the notification. $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($intro_id), intval($uid)); } if ($status != 0) { return; } } /* * * We have now established a relationship with the other site. * Let's make our own personal copy of their profile photo so we don't have * to always load it from their site. * * We will also update the contact record with the nature and scope of the relationship. * */ require_once 'include/Photo.php'; $photos = import_profile_photo($contact['photo'], $uid, $contact_id); logger('dfrn_confirm: confirm - imported photos'); if ($network === NETWORK_DFRN) { $new_relation = CONTACT_IS_FOLLOWER; if ($relation == CONTACT_IS_SHARING || $duplex) { $new_relation = CONTACT_IS_FRIEND; } if ($relation == CONTACT_IS_SHARING && $duplex) { $duplex = 0; } $r = q("UPDATE `contact` SET \n\t\t\t\t`photo` = '%s', \n\t\t\t\t`thumb` = '%s',\n\t\t\t\t`micro` = '%s', \n\t\t\t\t`rel` = %d, \n\t\t\t\t`name-date` = '%s', \n\t\t\t\t`uri-date` = '%s', \n\t\t\t\t`avatar-date` = '%s', \n\t\t\t\t`blocked` = 0, \n\t\t\t\t`pending` = 0,\n\t\t\t\t`duplex` = %d,\n\t\t\t\t`hidden` = %d,\n\t\t\t\t`network` = 'dfrn' WHERE `id` = %d LIMIT 1\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($new_relation), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($duplex), intval($hidden), intval($contact_id)); } else { // $network !== NETWORK_DFRN $network = $contact['network'] ? $contact['network'] : NETWORK_OSTATUS; $notify = $contact['notify'] ? $contact['notify'] : ''; $poll = $contact['poll'] ? $contact['poll'] : ''; if (!$contact['notify'] || !$contact['poll']) { $arr = lrdd($contact['url']); if (count($arr)) { foreach ($arr as $link) { if ($link['@attributes']['rel'] === 'salmon') { $notify = $link['@attributes']['href']; } if ($link['@attributes']['rel'] === NAMESPACE_FEED) { $poll = $link['@attributes']['href']; } } } } $new_relation = $contact['rel']; $writable = $contact['writable']; if ($network === NETWORK_DIASPORA) { if ($duplex) { $new_relation = CONTACT_IS_FRIEND; } else { $new_relation = CONTACT_IS_SHARING; } if ($new_relation != CONTACT_IS_FOLLOWER) { $writable = 1; } } $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($intro_id), intval($uid)); $r = q("UPDATE `contact` SET `photo` = '%s', \n\t\t\t\t`thumb` = '%s',\n\t\t\t\t`micro` = '%s', \n\t\t\t\t`name-date` = '%s', \n\t\t\t\t`uri-date` = '%s', \n\t\t\t\t`avatar-date` = '%s', \n\t\t\t\t`notify` = '%s',\n\t\t\t\t`poll` = '%s',\n\t\t\t\t`blocked` = 0, \n\t\t\t\t`pending` = 0,\n\t\t\t\t`network` = '%s',\n\t\t\t\t`writable` = %d,\n\t\t\t\t`hidden` = %d,\n\t\t\t\t`rel` = %d\n\t\t\t\tWHERE `id` = %d LIMIT 1\n\t\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($notify), dbesc($poll), dbesc($network), intval($writable), intval($hidden), intval($new_relation), intval($contact_id)); } if ($r === false) { notice(t('Unable to set contact photo.') . EOL); } // reload contact info $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($contact_id)); if (count($r)) { $contact = $r[0]; } else { $contact = null; } if (isset($new_relation) && $new_relation == CONTACT_IS_FRIEND) { if ($contact && $contact['network'] === NETWORK_DIASPORA) { require_once 'include/diaspora.php'; $ret = diaspora_share($user[0], $r[0]); logger('mod_follow: diaspora_share returns: ' . $ret); } // Send a new friend post if we are allowed to... $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", intval($uid)); if (count($r) && $r[0]['hide-friends'] == 0 && $activity && !$hidden) { require_once 'include/items.php'; $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($uid)); if (count($self)) { $arr = array(); $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $uid); $arr['uid'] = $uid; $arr['contact-id'] = $self[0]['id']; $arr['wall'] = 1; $arr['type'] = 'wall'; $arr['gravity'] = 0; $arr['origin'] = 1; $arr['author-name'] = $arr['owner-name'] = $self[0]['name']; $arr['author-link'] = $arr['owner-link'] = $self[0]['url']; $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb']; $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]'; $APhoto = '[url=' . $self[0]['url'] . ']' . '[img]' . $self[0]['thumb'] . '[/img][/url]'; $B = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]'; $BPhoto = '[url=' . $contact['url'] . ']' . '[img]' . $contact['thumb'] . '[/img][/url]'; $arr['verb'] = ACTIVITY_FRIEND; $arr['object-type'] = ACTIVITY_OBJ_PERSON; $arr['body'] = sprintf(t('%1$s is now friends with %2$s'), $A, $B) . "\n\n\n" . $BPhoto; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact['name'] . '</title>' . '<id>' . $contact['url'] . '/' . $contact['name'] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact['url'] . '" />' . "\n"); $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact['thumb'] . '" />' . "\n"); $arr['object'] .= '</link></object>' . "\n"; $arr['last-child'] = 1; $arr['allow_cid'] = $user[0]['allow_cid']; $arr['allow_gid'] = $user[0]['allow_gid']; $arr['deny_cid'] = $user[0]['deny_cid']; $arr['deny_gid'] = $user[0]['deny_gid']; $i = item_store($arr); if ($i) { proc_run('php', "include/notifier.php", "activity", "{$i}"); } } } } $g = q("select def_gid from user where uid = %d limit 1", intval($uid)); if ($contact && $g && intval($g[0]['def_gid'])) { require_once 'include/group.php'; group_add_member($uid, '', $contact['id'], $g[0]['def_gid']); } // Let's send our user to the contact editor in case they want to // do anything special with this new friend. if ($handsfree === null) { goaway($a->get_baseurl() . '/contacts/' . intval($contact_id)); } else { return; } //NOTREACHED } /** * * * End of Scenario 1. [Local confirmation of remote friend request]. * * Begin Scenario 2. This is the remote response to the above scenario. * This will take place on the site that originally initiated the friend request. * In the section above where the confirming party makes a POST and * retrieves xml status information, they are communicating with the following code. * */ if (x($_POST, 'source_url')) { // We are processing an external confirmation to an introduction created by our user. $public_key = x($_POST, 'public_key') ? $_POST['public_key'] : ''; $dfrn_id = x($_POST, 'dfrn_id') ? hex2bin($_POST['dfrn_id']) : ''; $source_url = x($_POST, 'source_url') ? hex2bin($_POST['source_url']) : ''; $aes_key = x($_POST, 'aes_key') ? $_POST['aes_key'] : ''; $duplex = x($_POST, 'duplex') ? intval($_POST['duplex']) : 0; $page = x($_POST, 'page') ? intval($_POST['page']) : 0; $version_id = x($_POST, 'dfrn_version') ? (double) $_POST['dfrn_version'] : 2.0; $forum = $page == 1 ? 1 : 0; $prv = $page == 2 ? 1 : 0; logger('dfrn_confirm: requestee contacted: ' . $node); logger('dfrn_confirm: request: POST=' . print_r($_POST, true), LOGGER_DATA); // If $aes_key is set, both of these items require unpacking from the hex transport encoding. if (x($aes_key)) { $aes_key = hex2bin($aes_key); $public_key = hex2bin($public_key); } // Find our user's account $r = q("SELECT * FROM `user` WHERE `nickname` = '%s' LIMIT 1", dbesc($node)); if (!count($r)) { $message = sprintf(t('No user record found for \'%s\' '), $node); xml_status(3, $message); // failure // NOTREACHED } $my_prvkey = $r[0]['prvkey']; $local_uid = $r[0]['uid']; if (!strstr($my_prvkey, 'PRIVATE KEY')) { $message = t('Our site encryption key is apparently messed up.'); xml_status(3, $message); } // verify everything $decrypted_source_url = ""; openssl_private_decrypt($source_url, $decrypted_source_url, $my_prvkey); if (!strlen($decrypted_source_url)) { $message = t('Empty site URL was provided or URL could not be decrypted by us.'); xml_status(3, $message); // NOTREACHED } $ret = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($decrypted_source_url), intval($local_uid)); if (!count($ret)) { if (strstr($decrypted_source_url, 'http:')) { $newurl = str_replace('http:', 'https:', $decrypted_source_url); } else { $newurl = str_replace('https:', 'http:', $decrypted_source_url); } $ret = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1", dbesc($newurl), intval($local_uid)); if (!count($ret)) { // this is either a bogus confirmation (?) or we deleted the original introduction. $message = t('Contact record was not found for you on our site.'); xml_status(3, $message); return; // NOTREACHED } } $relation = $ret[0]['rel']; // Decrypt all this stuff we just received $foreign_pubkey = $ret[0]['site-pubkey']; $dfrn_record = $ret[0]['id']; if (!$foreign_pubkey) { $message = sprintf(t('Site public key not available in contact record for URL %s.'), $newurl); xml_status(3, $message); } $decrypted_dfrn_id = ""; openssl_public_decrypt($dfrn_id, $decrypted_dfrn_id, $foreign_pubkey); if (strlen($aes_key)) { $decrypted_aes_key = ""; openssl_private_decrypt($aes_key, $decrypted_aes_key, $my_prvkey); $dfrn_pubkey = openssl_decrypt($public_key, 'AES-256-CBC', $decrypted_aes_key); } else { $dfrn_pubkey = $public_key; } $r = q("SELECT * FROM `contact` WHERE `dfrn-id` = '%s' LIMIT 1", dbesc($decrypted_dfrn_id)); if (count($r)) { $message = t('The ID provided by your system is a duplicate on our system. It should work if you try again.'); xml_status(1, $message); // Birthday paradox - duplicate dfrn-id // NOTREACHED } $r = q("UPDATE `contact` SET `dfrn-id` = '%s', `pubkey` = '%s' WHERE `id` = %d LIMIT 1", dbesc($decrypted_dfrn_id), dbesc($dfrn_pubkey), intval($dfrn_record)); if (!count($r)) { $message = t('Unable to set your contact credentials on our system.'); xml_status(3, $message); } // It's possible that the other person also requested friendship. // If it is a duplex relationship, ditch the issued-id if one exists. if ($duplex) { $r = q("UPDATE `contact` SET `issued-id` = '' WHERE `id` = %d LIMIT 1", intval($dfrn_record)); } // We're good but now we have to scrape the profile photo and send notifications. $r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1", intval($dfrn_record)); if (count($r)) { $photo = $r[0]['photo']; } else { $photo = $a->get_baseurl() . '/images/person-175.jpg'; } require_once "include/Photo.php"; $photos = import_profile_photo($photo, $local_uid, $dfrn_record); logger('dfrn_confirm: request - photos imported'); $new_relation = CONTACT_IS_SHARING; if ($relation == CONTACT_IS_FOLLOWER || $duplex) { $new_relation = CONTACT_IS_FRIEND; } if ($relation == CONTACT_IS_FOLLOWER && $duplex) { $duplex = 0; } $r = q("UPDATE `contact` SET \n\t\t\t`photo` = '%s', \n\t\t\t`thumb` = '%s', \n\t\t\t`micro` = '%s',\n\t\t\t`rel` = %d, \n\t\t\t`name-date` = '%s', \n\t\t\t`uri-date` = '%s', \n\t\t\t`avatar-date` = '%s', \n\t\t\t`blocked` = 0, \n\t\t\t`pending` = 0,\n\t\t\t`duplex` = %d, \n\t\t\t`forum` = %d,\n\t\t\t`prv` = %d,\n\t\t\t`network` = '%s' WHERE `id` = %d LIMIT 1\n\t\t", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), intval($new_relation), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($duplex), intval($forum), intval($prv), dbesc(NETWORK_DFRN), intval($dfrn_record)); if ($r === false) { // indicates schema is messed up or total db failure $message = t('Unable to update your contact profile details on our system'); xml_status(3, $message); } // Otherwise everything seems to have worked and we are almost done. Yay! // Send an email notification logger('dfrn_confirm: request: info updated'); $r = q("SELECT `contact`.*, `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\tWHERE `contact`.`id` = %d LIMIT 1", intval($dfrn_record)); if (count($r)) { $combined = $r[0]; } if (count($r) && $r[0]['notify-flags'] & NOTIFY_CONFIRM) { push_lang($r[0]['language']); $tpl = $new_relation == CONTACT_IS_FRIEND ? get_intltext_template('friend_complete_eml.tpl') : get_intltext_template('intro_complete_eml.tpl'); $email_tpl = replace_macros($tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $r[0]['username'], '$email' => $r[0]['email'], '$fn' => $r[0]['name'], '$dfrn_url' => $r[0]['url'], '$uid' => $newuid)); require_once 'include/email.php'; $res = mail($r[0]['email'], email_header_encode(sprintf(t("Connection accepted at %s"), $a->config['sitename']), 'UTF-8'), $email_tpl, 'From: ' . 'Administrator' . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); if (!$res) { // pointless throwing an error here and confusing the person at the other end of the wire. } pop_lang(); } // Send a new friend post if we are allowed to... if ($page && intval(get_pconfig($local_uid, 'system', 'post_joingroup'))) { $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", intval($local_uid)); if (count($r) && $r[0]['hide-friends'] == 0) { require_once 'include/items.php'; $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($local_uid)); if (count($self)) { $arr = array(); $arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $local_uid); $arr['uid'] = $local_uid; $arr['contact-id'] = $self[0]['id']; $arr['wall'] = 1; $arr['type'] = 'wall'; $arr['gravity'] = 0; $arr['origin'] = 1; $arr['author-name'] = $arr['owner-name'] = $self[0]['name']; $arr['author-link'] = $arr['owner-link'] = $self[0]['url']; $arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb']; $A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]'; $APhoto = '[url=' . $self[0]['url'] . ']' . '[img]' . $self[0]['thumb'] . '[/img][/url]'; $B = '[url=' . $combined['url'] . ']' . $combined['name'] . '[/url]'; $BPhoto = '[url=' . $combined['url'] . ']' . '[img]' . $combined['thumb'] . '[/img][/url]'; $arr['verb'] = ACTIVITY_JOIN; $arr['object-type'] = ACTIVITY_OBJ_GROUP; $arr['body'] = sprintf(t('%1$s has joined %2$s'), $A, $B) . "\n\n\n" . $BPhoto; $arr['object'] = '<object><type>' . ACTIVITY_OBJ_GROUP . '</type><title>' . $combined['name'] . '</title>' . '<id>' . $combined['url'] . '/' . $combined['name'] . '</id>'; $arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $combined['url'] . '" />' . "\n"); $arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $combined['thumb'] . '" />' . "\n"); $arr['object'] .= '</link></object>' . "\n"; $arr['last-child'] = 1; $arr['allow_cid'] = $user[0]['allow_cid']; $arr['allow_gid'] = $user[0]['allow_gid']; $arr['deny_cid'] = $user[0]['deny_cid']; $arr['deny_gid'] = $user[0]['deny_gid']; $i = item_store($arr); if ($i) { proc_run('php', "include/notifier.php", "activity", "{$i}"); } } } } xml_status(0); // Success return; // NOTREACHED ////////////////////// End of this scenario /////////////////////////////////////////////// } // somebody arrived here by mistake or they are fishing. Send them to the homepage. goaway(z_root()); // NOTREACHED }
function item_post(&$a) { if (!local_user() && !remote_user()) { return; } require_once 'include/security.php'; $uid = local_user(); if (x($_POST, 'dropitems')) { require_once 'include/items.php'; $arr_drop = explode(',', $_POST['dropitems']); drop_items($arr_drop); $json = array('success' => 1); echo json_encode($json); killme(); } call_hooks('post_local_start', $_POST); $api_source = x($_POST, 'api_source') && $_POST['api_source'] ? true : false; $return_path = x($_POST, 'return') ? $_POST['return'] : ''; /** * Is this a reply to something? */ $parent = x($_POST, 'parent') ? intval($_POST['parent']) : 0; $parent_uri = x($_POST, 'parent_uri') ? trim($_POST['parent_uri']) : ''; $parent_item = null; $parent_contact = null; $thr_parent = ''; $parid = 0; $r = false; if ($parent || $parent_uri) { if (!x($_POST, 'type')) { $_POST['type'] = 'net-comment'; } if ($parent) { $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent)); } elseif ($parent_uri && local_user()) { // This is coming from an API source, and we are logged in $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_uri), intval(local_user())); } // if this isn't the real parent of the conversation, find it if ($r !== false && count($r)) { $parid = $r[0]['parent']; if ($r[0]['id'] != $r[0]['parent']) { $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1", intval($parid)); } } if ($r === false || !count($r)) { notice(t('Unable to locate original post.') . EOL); if (x($_POST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } $parent_item = $r[0]; $parent = $r[0]['id']; // multi-level threading - preserve the info but re-parent to our single level threading if ($parid && $parid != $parent) { $thr_parent = $parent_uri; } if ($parent_item['contact-id'] && $uid) { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($parent_item['contact-id']), intval($uid)); if (count($r)) { $parent_contact = $r[0]; } } } if ($parent) { logger('mod_post: parent=' . $parent); } $profile_uid = x($_POST, 'profile_uid') ? intval($_POST['profile_uid']) : 0; $post_id = x($_POST['post_id']) ? intval($_POST['post_id']) : 0; $app = x($_POST['source']) ? strip_tags($_POST['source']) : ''; if (!can_write_wall($a, $profile_uid)) { notice(t('Permission denied.') . EOL); if (x($_POST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } // is this an edited post? $orig_post = null; if ($post_id) { $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($post_id)); if (!count($i)) { killme(); } $orig_post = $i[0]; } $user = null; $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($profile_uid)); if (count($r)) { $user = $r[0]; } if ($orig_post) { $str_group_allow = $orig_post['allow_gid']; $str_contact_allow = $orig_post['allow_cid']; $str_group_deny = $orig_post['deny_gid']; $str_contact_deny = $orig_post['deny_cid']; $title = $orig_post['title']; $location = $orig_post['location']; $coord = $orig_post['coord']; $verb = $orig_post['verb']; $emailcc = $orig_post['emailcc']; $app = $orig_post['app']; $body = escape_tags(trim($_POST['body'])); $private = $orig_post['private']; $pubmail_enable = $orig_post['pubmail']; } else { $str_group_allow = perms2str($_POST['group_allow']); $str_contact_allow = perms2str($_POST['contact_allow']); $str_group_deny = perms2str($_POST['group_deny']); $str_contact_deny = perms2str($_POST['contact_deny']); $title = notags(trim($_POST['title'])); $location = notags(trim($_POST['location'])); $coord = notags(trim($_POST['coord'])); $verb = notags(trim($_POST['verb'])); $emailcc = notags(trim($_POST['emailcc'])); $body = escape_tags(trim($_POST['body'])); $private = strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) ? 1 : 0; if ($parent_item && ($parent_item['private'] || strlen($parent_item['allow_cid']) || strlen($parent_item['allow_gid']) || strlen($parent_item['deny_cid']) || strlen($parent_item['deny_gid']))) { $private = 1; } $pubmail_enable = x($_POST, 'pubmail_enable') && intval($_POST['pubmail_enable']) && !$private ? 1 : 0; // if using the API, we won't see pubmail_enable - figure out if it should be set if ($api_source && $profile_uid && $profile_uid == local_user() && !$private) { $mail_disabled = function_exists('imap_open') && !get_config('system', 'imap_disabled') ? 0 : 1; if (!$mail_disabled) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user())); if (count($r) && intval($r[0]['pubmail'])) { $pubmail_enabled = true; } } } if (!strlen($body)) { info(t('Empty post discarded.') . EOL); if (x($_POST, 'return')) { goaway($a->get_baseurl() . "/" . $return_path); } killme(); } } if ($api_source && !array_key_exists('allow_cid', $_REQUEST) && !array_key_exists('allow_gid', $_REQUEST) && !array_key_exists('deny_cid', $_REQUEST) && !array_key_exists('deny_gid', $_REQUEST)) { $str_group_allow = $user['allow_gid']; $str_contact_allow = $user['allow_cid']; $str_group_deny = $user['deny_gid']; $str_contact_deny = $user['deny_cid']; } // get contact info for poster $author = null; $self = false; if ($_SESSION['uid'] && $_SESSION['uid'] == $profile_uid) { $self = true; $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($_SESSION['uid'])); } else { if (x($_SESSION, 'visitor_id') && intval($_SESSION['visitor_id'])) { $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($_SESSION['visitor_id'])); } } if (count($r)) { $author = $r[0]; $contact_id = $author['id']; } // get contact info for owner if ($profile_uid == $_SESSION['uid']) { $contact_record = $author; } else { $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($profile_uid)); if (count($r)) { $contact_record = $r[0]; } } $post_type = notags(trim($_POST['type'])); if ($post_type === 'net-comment') { if ($parent_item !== null) { if ($parent_item['wall'] == 1) { $post_type = 'wall-comment'; } else { $post_type = 'remote-comment'; } } } /** * * When a photo was uploaded into the message using the (profile wall) ajax * uploader, The permissions are initially set to disallow anybody but the * owner from seeing it. This is because the permissions may not yet have been * set for the post. If it's private, the photo permissions should be set * appropriately. But we didn't know the final permissions on the post until * now. So now we'll look for links of uploaded messages that are in the * post and set them to the same permissions as the post itself. * */ $match = null; if (preg_match_all("/\\[img\\](.*?)\\[\\/img\\]/", $body, $match)) { $images = $match[1]; if (count($images)) { foreach ($images as $image) { if (!stristr($image, $a->get_baseurl() . '/photo/')) { continue; } $image_uri = substr($image, strrpos($image, '/') + 1); $image_uri = substr($image_uri, 0, strpos($image_uri, '-')); if (!strlen($image_uri)) { continue; } $srch = '<' . intval($profile_uid) . '>'; $r = q("SELECT `id` FROM `photo` WHERE `allow_cid` = '%s' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = ''\n\t\t\t\t\tAND `resource-id` = '%s' AND `uid` = %d LIMIT 1", dbesc($srch), dbesc($image_uri), intval($profile_uid)); if (!count($r)) { continue; } $r = q("UPDATE `photo` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\tWHERE `resource-id` = '%s' AND `uid` = %d AND `album` = '%s' ", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), dbesc($image_uri), intval($profile_uid), dbesc(t('Wall Photos'))); } } } /** * Next link in any attachment references we find in the post. */ $match = false; if (preg_match_all("/\\[attachment\\](.*?)\\[\\/attachment\\]/", $body, $match)) { $attaches = $match[1]; if (count($attaches)) { foreach ($attaches as $attach) { $r = q("SELECT * FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($attach)); if (count($r)) { $r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'\n\t\t\t\t\t\tWHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), intval($profile_uid), intval($attach)); } } } } // embedded bookmark in post? set bookmark flag $bookmark = 0; if (preg_match_all("/\\[bookmark\\=([^\\]]*)\\](.*?)\\[\\/bookmark\\]/ism", $body, $match, PREG_SET_ORDER)) { $bookmark = 1; // foreach($match as $mtch) { // $body = str_replace( // '[bookmark=' . $mtch[1] . ']' . $mtch[2] . '[/bookmark]', // '[url=' . $mtch[1] . ']' . $mtch[2] . '[/url]', // $body // ); // } } $body = bb_translate_video($body); /** * Fold multi-line [code] sequences */ $body = preg_replace('/\\[\\/code\\]\\s*\\[code\\]/ism', "\n", $body); /** * Look for any tags and linkify them */ $str_tags = ''; $inform = ''; $tags = get_tags($body); /** * add a statusnet style reply tag if the original post was from there * and we are replying, and there isn't one already */ if ($parent_contact && $parent_contact['network'] === NETWORK_OSTATUS && $parent_contact['nick'] && !in_array('@' . $parent_contact['nick'], $tags)) { $body = '@' . $parent_contact['nick'] . ' ' . $body; $tags[] = '@' . $parent_contact['nick']; } if (count($tags)) { foreach ($tags as $tag) { if (isset($profile)) { unset($profile); } if (strpos($tag, '#') === 0) { if (strpos($tag, '[url=')) { continue; } $basetag = str_replace('_', ' ', substr($tag, 1)); $body = str_replace($tag, '#[url=' . $a->get_baseurl() . '/search?search=' . rawurlencode($basetag) . ']' . $basetag . '[/url]', $body); if (strlen($str_tags)) { $str_tags .= ','; } $str_tags .= '#[url=' . $a->get_baseurl() . '/search?search=' . rawurlencode($basetag) . ']' . $basetag . '[/url]'; continue; } if (strpos($tag, '@') === 0) { if (strpos($tag, '[url=')) { continue; } $stat = false; $name = substr($tag, 1); if (strpos($name, '@') || strpos($name, 'http://')) { $newname = $name; $links = @lrdd($name); if (count($links)) { foreach ($links as $link) { if ($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') { $profile = $link['@attributes']['href']; } if ($link['@attributes']['rel'] === 'salmon') { if (strlen($inform)) { $inform .= ','; } $inform .= 'url:' . str_replace(',', '%2c', $link['@attributes']['href']); } } } } else { $newname = $name; $alias = ''; $tagcid = 0; if (strrpos($newname, '+')) { $tagcid = intval(substr($newname, strrpos($newname, '+') + 1)); if (strpos($name, ' ')) { $name = substr($name, 0, strpos($name, ' ')); } } if ($tagcid) { $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($tagcid), intval($profile_uid)); } elseif (strstr($name, '_') || strstr($name, ' ')) { $newname = str_replace('_', ' ', $name); $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1", dbesc($newname), intval($profile_uid)); } else { $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1", dbesc($name), dbesc($name), intval($profile_uid)); } if (count($r)) { $profile = $r[0]['url']; if ($r[0]['network'] === 'stat') { $newname = $r[0]['nick']; $stat = true; if ($r[0]['alias']) { $alias = $r[0]['alias']; } } else { $newname = $r[0]['name']; } if (strlen($inform)) { $inform .= ','; } $inform .= 'cid:' . $r[0]['id']; } } if ($profile) { $body = str_replace('@' . $name, '@' . '[url=' . $profile . ']' . $newname . '[/url]', $body); $profile = str_replace(',', '%2c', $profile); $newtag = '@[url=' . $profile . ']' . $newname . '[/url]'; if (!stristr($str_tags, $newtag)) { if (strlen($str_tags)) { $str_tags .= ','; } $str_tags .= $newtag; } // Status.Net seems to require the numeric ID URL in a mention if the person isn't // subscribed to you. But the nickname URL is OK if they are. Grrr. We'll tag both. if (strlen($alias)) { $newtag = '@[url=' . $alias . ']' . $newname . '[/url]'; if (!stristr($str_tags, $newtag)) { if (strlen($str_tags)) { $str_tags .= ','; } $str_tags .= $newtag; } } } } } } $attachments = ''; $match = false; if (preg_match_all('/(\\[attachment\\]([0-9]+)\\[\\/attachment\\])/', $body, $match)) { foreach ($match[2] as $mtch) { $r = q("SELECT `id`,`filename`,`filesize`,`filetype` FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($mtch)); if (count($r)) { if (strlen($attachments)) { $attachments .= ','; } $attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" length="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . ($r[0]['filename'] ? $r[0]['filename'] : '') . '"[/attach]'; } $body = str_replace($match[1], '', $body); } } $wall = 0; if ($post_type === 'wall' || $post_type === 'wall-comment') { $wall = 1; } if (!strlen($verb)) { $verb = ACTIVITY_POST; } $gravity = $parent ? 6 : 0; // even if the post arrived via API we are considering that it // originated on this site by default for determining relayability. $origin = x($_REQUEST, 'origin') ? intval($_REQUEST['origin']) : 1; $notify_type = $parent ? 'comment-new' : 'wall-new'; $uri = item_new_uri($a->get_hostname(), $profile_uid); $datarray = array(); $datarray['uid'] = $profile_uid; $datarray['type'] = $post_type; $datarray['wall'] = $wall; $datarray['gravity'] = $gravity; $datarray['contact-id'] = $contact_id; $datarray['owner-name'] = $contact_record['name']; $datarray['owner-link'] = $contact_record['url']; $datarray['owner-avatar'] = $contact_record['thumb']; $datarray['author-name'] = $author['name']; $datarray['author-link'] = $author['url']; $datarray['author-avatar'] = $author['thumb']; $datarray['created'] = datetime_convert(); $datarray['edited'] = datetime_convert(); $datarray['commented'] = datetime_convert(); $datarray['received'] = datetime_convert(); $datarray['changed'] = datetime_convert(); $datarray['uri'] = $uri; $datarray['title'] = $title; $datarray['body'] = $body; $datarray['app'] = $app; $datarray['location'] = $location; $datarray['coord'] = $coord; $datarray['tag'] = $str_tags; $datarray['inform'] = $inform; $datarray['verb'] = $verb; $datarray['allow_cid'] = $str_contact_allow; $datarray['allow_gid'] = $str_group_allow; $datarray['deny_cid'] = $str_contact_deny; $datarray['deny_gid'] = $str_group_deny; $datarray['private'] = $private; $datarray['pubmail'] = $pubmail_enable; $datarray['attach'] = $attachments; $datarray['bookmark'] = intval($bookmark); $datarray['thr-parent'] = $thr_parent; $datarray['postopts'] = ''; $datarray['origin'] = $origin; /** * These fields are for the convenience of plugins... * 'self' if true indicates the owner is posting on their own wall * If parent is 0 it is a top-level post. */ $datarray['parent'] = $parent; $datarray['self'] = $self; // $datarray['prvnets'] = $user['prvnets']; if ($orig_post) { $datarray['edit'] = true; } else { $datarray['guid'] = get_guid(); } call_hooks('post_local', $datarray); if ($orig_post) { $r = q("UPDATE `item` SET `body` = '%s', `edited` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1", dbesc($body), dbesc(datetime_convert()), intval($post_id), intval($profile_uid)); proc_run('php', "include/notifier.php", 'edit_post', "{$post_id}"); if (x($_POST, 'return') && strlen($return_path)) { logger('return: ' . $return_path); goaway($a->get_baseurl() . "/" . $return_path); } killme(); } else { $post_id = 0; } $r = q("INSERT INTO `item` (`guid`, `uid`,`type`,`wall`,`gravity`,`contact-id`,`owner-name`,`owner-link`,`owner-avatar`, \n\t\t`author-name`, `author-link`, `author-avatar`, `created`, `edited`, `commented`, `received`, `changed`, `uri`, `thr-parent`, `title`, `body`, `app`, `location`, `coord`, \n\t\t`tag`, `inform`, `verb`, `postopts`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `private`, `pubmail`, `attach`, `bookmark`,`origin` )\n\t\tVALUES( '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d )", dbesc($datarray['guid']), intval($datarray['uid']), dbesc($datarray['type']), intval($datarray['wall']), intval($datarray['gravity']), intval($datarray['contact-id']), dbesc($datarray['owner-name']), dbesc($datarray['owner-link']), dbesc($datarray['owner-avatar']), dbesc($datarray['author-name']), dbesc($datarray['author-link']), dbesc($datarray['author-avatar']), dbesc($datarray['created']), dbesc($datarray['edited']), dbesc($datarray['commented']), dbesc($datarray['received']), dbesc($datarray['changed']), dbesc($datarray['uri']), dbesc($datarray['thr-parent']), dbesc($datarray['title']), dbesc($datarray['body']), dbesc($datarray['app']), dbesc($datarray['location']), dbesc($datarray['coord']), dbesc($datarray['tag']), dbesc($datarray['inform']), dbesc($datarray['verb']), dbesc($datarray['postopts']), dbesc($datarray['allow_cid']), dbesc($datarray['allow_gid']), dbesc($datarray['deny_cid']), dbesc($datarray['deny_gid']), intval($datarray['private']), intval($datarray['pubmail']), dbesc($datarray['attach']), intval($datarray['bookmark']), intval($datarray['origin'])); $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($datarray['uri'])); if (count($r)) { $post_id = $r[0]['id']; logger('mod_item: saved item ' . $post_id); if ($parent) { // This item is the last leaf and gets the comment box, clear any ancestors $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent` = %d ", dbesc(datetime_convert()), intval($parent)); // Inherit ACL's from the parent item. $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `private` = %d\n\t\t\t\tWHERE `id` = %d LIMIT 1", dbesc($parent_item['allow_cid']), dbesc($parent_item['allow_gid']), dbesc($parent_item['deny_cid']), dbesc($parent_item['deny_gid']), intval($parent_item['private']), intval($post_id)); // Send a notification email to the conversation owner, unless the owner is me and I wrote this item if ($user['notify-flags'] & NOTIFY_COMMENT && $contact_record != $author) { push_lang($user['language']); require_once 'bbcode.php'; $from = $author['name']; // name of the automated email sender $msg['notificationfromname'] = stripslashes($datarray['author-name']); // noreply address to send from $msg['notificationfromemail'] = t('noreply') . '@' . $a->get_hostname(); // text version // process the message body to display properly in text mode $msg['textversion'] = html_entity_decode(strip_tags(bbcode(stripslashes($datarray['body']))), ENT_QUOTES, 'UTF-8'); // html version // process the message body to display properly in text mode $msg['htmlversion'] = html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n\\n", "\\n"), "<br />\n", $datarray['body'])))); // load the template for private message notifications $tpl = get_intltext_template('cmnt_received_html_body_eml.tpl'); $email_html_body_tpl = replace_macros($tpl, array('$username' => $user['username'], '$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$thumb' => $author['thumb'], '$email' => $importer['email'], '$url' => $author['url'], '$from' => $from, '$body' => $msg['htmlversion'], '$display' => $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id)); // load the template for private message notifications $tpl = get_intltext_template('cmnt_received_text_body_eml.tpl'); $email_text_body_tpl = replace_macros($tpl, array('$username' => $user['username'], '$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$thumb' => $author['thumb'], '$email' => $importer['email'], '$url' => $author['url'], '$from' => $from, '$body' => $msg['textversion'], '$display' => $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id)); // use the EmailNotification library to send the message require_once "include/EmailNotification.php"; EmailNotification::sendTextHtmlEmail($msg['notificationfromname'], t("Administrator@") . $a->get_hostname(), t("noreply") . '@' . $a->get_hostname(), $user['email'], sprintf(t('%s commented on an item at %s'), $from, $a->config['sitename']), $email_html_body_tpl, $email_text_body_tpl); pop_lang(); } // We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key if ($self) { require_once 'include/bb2diaspora.php'; $signed_body = html_entity_decode(bb2diaspora($datarray['body'])); $myaddr = $a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3); if ($datarray['verb'] === ACTIVITY_LIKE) { $signed_text = $datarray['guid'] . ';' . 'Post' . ';' . $parent_item['guid'] . ';' . 'true' . ';' . $myaddr; } else { $signed_text = $datarray['guid'] . ';' . $parent_item['guid'] . ';' . $signed_body . ';' . $myaddr; } $authorsig = base64_encode(rsa_sign($signed_text, $a->user['prvkey'], 'sha256')); q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($post_id), dbesc($signed_text), dbesc(base64_encode($authorsig)), dbesc($myaddr)); } } else { $parent = $post_id; // let me know if somebody did a wall-to-wall post on my profile if ($user['notify-flags'] & NOTIFY_WALL && $contact_record != $author) { push_lang($user['language']); require_once 'bbcode.php'; $from = $author['name']; // name of the automated email sender $msg['notificationfromname'] = $from; // noreply address to send from $msg['notificationfromemail'] = t('noreply') . '@' . $a->get_hostname(); // text version // process the message body to display properly in text mode $msg['textversion'] = html_entity_decode(strip_tags(bbcode(stripslashes($datarray['body']))), ENT_QUOTES, 'UTF-8'); // html version // process the message body to display properly in text mode $msg['htmlversion'] = html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n\\n", "\\n"), "<br />\n", $datarray['body'])))); // load the template for private message notifications $tpl = load_view_file('view/wall_received_html_body_eml.tpl'); $email_html_body_tpl = replace_macros($tpl, array('$username' => $user['username'], '$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$thumb' => $author['thumb'], '$url' => $author['url'], '$from' => $from, '$body' => $msg['htmlversion'], '$display' => $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id)); // load the template for private message notifications $tpl = load_view_file('view/wall_received_text_body_eml.tpl'); $email_text_body_tpl = replace_macros($tpl, array('$username' => $user['username'], '$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$thumb' => $author['thumb'], '$url' => $author['url'], '$from' => $from, '$body' => $msg['textversion'], '$display' => $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id)); // use the EmailNotification library to send the message require_once "include/EmailNotification.php"; EmailNotification::sendTextHtmlEmail($msg['notificationfromname'], t("Administrator@") . $a->get_hostname(), t("noreply") . '@' . $a->get_hostname(), $user['email'], sprintf(t('%s posted to your profile wall at %s'), $from, $a->config['sitename']), $email_html_body_tpl, $email_text_body_tpl); pop_lang(); } } // fallback so that parent always gets set to non-zero. if (!$parent) { $parent = $post_id; } $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s', `plink` = '%s', `changed` = '%s', `last-child` = 1, `visible` = 1\n\t\t\tWHERE `id` = %d LIMIT 1", intval($parent), dbesc($parent == $post_id ? $uri : $parent_item['uri']), dbesc($a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id), dbesc(datetime_convert()), intval($post_id)); // photo comments turn the corresponding item visible to the profile wall // This way we don't see every picture in your new photo album posted to your wall at once. // They will show up as people comment on them. if (!$parent_item['visible']) { $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d LIMIT 1", intval($parent_item['id'])); } } else { logger('mod_item: unable to retrieve post that was just stored.'); notify(t('System error. Post not saved.')); goaway($a->get_baseurl() . "/" . $return_path); // NOTREACHED } // update the commented timestamp on the parent q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($parent)); $datarray['id'] = $post_id; $datarray['plink'] = $a->get_baseurl() . '/display/' . $user['nickname'] . '/' . $post_id; call_hooks('post_local_end', $datarray); if (strlen($emailcc) && $profile_uid == local_user()) { $erecips = explode(',', $emailcc); if (count($erecips)) { foreach ($erecips as $recip) { $addr = trim($recip); if (!strlen($addr)) { continue; } $disclaimer = '<hr />' . sprintf(t('This message was sent to you by %s, a member of the Friendica social network.'), $a->user['username']) . '<br />'; $disclaimer .= sprintf(t('You may visit them online at %s'), $a->get_baseurl() . '/profile/' . $a->user['nickname']) . EOL; $disclaimer .= t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL; $subject = '[Friendica]' . ' ' . sprintf(t('%s posted an update.'), $a->user['username']); $headers = 'From: ' . $a->user['username'] . ' <' . $a->user['email'] . '>' . "\n"; $headers .= 'MIME-Version: 1.0' . "\n"; $headers .= 'Content-Type: text/html; charset=UTF-8' . "\n"; $headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; $link = '<a href="' . $a->get_baseurl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />'; $html = prepare_body($datarray); $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>'; @mail($addr, $subject, $message, $headers); } } } // This is a real juggling act on shared hosting services which kill your processes // e.g. dreamhost. We used to start delivery to our native delivery agents in the background // and then run our plugin delivery from the foreground. We're now doing plugin delivery first, // because as soon as you start loading up a bunch of remote delivey processes, *this* page is // likely to get killed off. If you end up looking at an /item URL and a blank page, // it's very likely the delivery got killed before all your friends could be notified. // Currently the only realistic fixes are to use a reliable server - which precludes shared hosting, // or cut back on plugins which do remote deliveries. proc_run('php', "include/notifier.php", $notify_type, "{$post_id}"); logger('post_complete'); // figure out how to return, depending on from whence we came if ($api_source) { return; } if ($return_path) { goaway($a->get_baseurl() . "/" . $return_path); } $json = array('success' => 1); if (x($_POST, 'jsreload') && strlen($_POST['jsreload'])) { $json['reload'] = $a->get_baseurl() . '/' . $_POST['jsreload']; } logger('post_json: ' . print_r($json, true), LOGGER_DEBUG); echo json_encode($json); killme(); // NOTREACHED }
/** * @brief Handle the actions of the different setup steps. * * @param[in,out] App &$a */ function setup_post(&$a) { global $install_wizard_pass, $db; switch ($install_wizard_pass) { case 1: case 2: return; break; // just in case return don't return :) // just in case return don't return :) case 3: $urlpath = $a->get_path(); $dbhost = trim($_POST['dbhost']); $dbport = intval(trim($_POST['dbport'])); $dbuser = trim($_POST['dbuser']); $dbpass = trim($_POST['dbpass']); $dbdata = trim($_POST['dbdata']); $dbtype = intval(trim($_POST['dbtype'])); $phpath = trim($_POST['phpath']); $adminmail = trim($_POST['adminmail']); $siteurl = trim($_POST['siteurl']); require_once 'include/dba/dba_driver.php'; unset($db); $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true); if (!$db->connected) { echo 'Database Connect failed: ' . $db->error; killme(); $a->data['db_conn_failed'] = true; } /*if(get_db_errno()) { unset($db); $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, '', true); if(! get_db_errno()) { $r = q("CREATE DATABASE '%s'", dbesc($dbdata) ); if($r) { unset($db); $db = new dba($dbhost, $dbport, $dbuser, $dbpass, $dbdata, true); } else { $a->data['db_create_failed']=true; } } else { $a->data['db_conn_failed']=true; return; } }*/ //if(get_db_errno()) { //} return; break; case 4: $urlpath = $a->get_path(); $dbhost = notags(trim($_POST['dbhost'])); $dbport = intval(notags(trim($_POST['dbport']))); $dbuser = notags(trim($_POST['dbuser'])); $dbpass = notags(trim($_POST['dbpass'])); $dbdata = notags(trim($_POST['dbdata'])); $dbtype = intval(notags(trim($_POST['dbtype']))); $phpath = notags(trim($_POST['phpath'])); $timezone = notags(trim($_POST['timezone'])); $adminmail = notags(trim($_POST['adminmail'])); $siteurl = notags(trim($_POST['siteurl'])); if ($siteurl != z_root()) { $test = z_fetch_url($siteurl . "/setup/testrewrite"); if (!$test['success'] || $test['body'] != 'ok') { $a->data['url_fail'] = true; $a->data['url_error'] = $test['error']; return; } } // connect to db $db = dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true); if (!$db->connected) { echo 'CRITICAL: DB not connected.'; killme(); } $tpl = get_intltext_template('htconfig.tpl'); $txt = replace_macros($tpl, array('$dbhost' => $dbhost, '$dbport' => $dbport, '$dbuser' => $dbuser, '$dbpass' => $dbpass, '$dbdata' => $dbdata, '$dbtype' => $dbtype, '$timezone' => $timezone, '$siteurl' => $siteurl, '$site_id' => random_string(), '$phpath' => $phpath, '$adminmail' => $adminmail)); $result = file_put_contents('.htconfig.php', $txt); if (!$result) { $a->data['txt'] = $txt; } $errors = load_database($db); if ($errors) { $a->data['db_failed'] = $errors; } else { $a->data['db_installed'] = true; } return; break; } }
function dfrn_request_content(&$a) { if ($a->argc != 2 || !count($a->profile)) { return ""; } // "Homecoming". Make sure we're logged in to this site as the correct user. Then offer a confirm button // to send us to the post section to record the introduction. if (x($_GET, 'dfrn_url')) { if (!local_user()) { info(t("Please login to confirm introduction.") . EOL); /* setup the return URL to come back to this page if they use openid */ $stripped = str_replace('q=', '', $a->query_string); $_SESSION['return_url'] = trim($stripped, '/'); return login(); } // Edge case, but can easily happen in the wild. This person is authenticated, // but not as the person who needs to deal with this request. if ($a->user['nickname'] != $a->argv[1]) { notice(t("Incorrect identity currently logged in. Please login to <strong>this</strong> profile.") . EOL); return login(); } $dfrn_url = notags(trim(hex2bin($_GET['dfrn_url']))); $aes_allow = x($_GET, 'aes_allow') && $_GET['aes_allow'] == 1 ? 1 : 0; $confirm_key = x($_GET, 'confirm_key') ? $_GET['confirm_key'] : ""; $tpl = get_markup_template("dfrn_req_confirm.tpl"); $o = replace_macros($tpl, array('$dfrn_url' => $dfrn_url, '$aes_allow' => $aes_allow ? '<input type="hidden" name="aes_allow" value="1" />' : "", '$confirm_key' => $confirm_key, '$welcome' => sprintf(t('Welcome home %s.'), $a->user['username']), '$please' => sprintf(t('Please confirm your introduction/connection request to %s.'), $dfrn_url), '$submit' => t('Confirm'), '$uid' => $_SESSION['uid'], '$nickname' => $a->user['nickname'], 'dfrn_rawurl' => $_GET['dfrn_url'])); return $o; } elseif (x($_GET, 'confirm_key') && strlen($_GET['confirm_key'])) { // we are the requestee and it is now safe to send our user their introduction, // We could just unblock it, but first we have to jump through a few hoops to // send an email, or even to find out if we need to send an email. $intro = q("SELECT * FROM `intro` WHERE `hash` = '%s' LIMIT 1", dbesc($_GET['confirm_key'])); if (count($intro)) { $r = q("SELECT `contact`.*, `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\t\tWHERE `contact`.`id` = %d LIMIT 1", intval($intro[0]['contact-id'])); $auto_confirm = false; if (count($r)) { if ($r[0]['page-flags'] != PAGE_NORMAL) { $auto_confirm = true; } if ($r[0]['notify-flags'] & NOTIFY_INTRO && !$auto_confirm) { $email_tpl = get_intltext_template('request_notify_eml.tpl'); $email = replace_macros($email_tpl, array('$requestor' => strlen(stripslashes($r[0]['name'])) ? stripslashes($r[0]['name']) : t('[Name Withheld]'), '$url' => stripslashes($r[0]['url']), '$myname' => $r[0]['username'], '$siteurl' => $a->get_baseurl(), '$sitename' => $a->config['sitename'])); $res = mail($r[0]['email'], t("Introduction received at ") . $a->config['sitename'], $email, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); // This is a redundant notification - no point throwing errors if it fails. } if ($auto_confirm) { require_once 'mod/dfrn_confirm.php'; $handsfree = array('uid' => $r[0]['uid'], 'node' => $r[0]['nickname'], 'dfrn_id' => $r[0]['issued-id'], 'intro_id' => $intro[0]['id'], 'duplex' => $r[0]['page-flags'] == PAGE_FREELOVE ? 1 : 0); dfrn_confirm_post($a, $handsfree); } } if (!$auto_confirm) { // If we are auto_confirming, this record will have already been nuked // in dfrn_confirm_post() $r = q("UPDATE `intro` SET `blocked` = 0 WHERE `hash` = '%s' LIMIT 1", dbesc($_GET['confirm_key'])); } } killme(); return; // NOTREACHED } else { /** * Normal web request. Display our user's introduction form. */ if (get_config('system', 'block_public') && !local_user() && !remote_user()) { notice(t('Public access denied.') . EOL); return; } /** * Try to auto-fill the profile address */ if (local_user()) { if (strlen($a->path)) { $myaddr = $a->get_baseurl() . '/profile/' . $a->user['nickname']; } else { $myaddr = $a->user['nickname'] . '@' . substr(z_root(), strpos(z_root(), '://') + 3); } } elseif (x($_GET, 'addr')) { $myaddr = hex2bin($_GET['addr']); } else { /* $_GET variables are already urldecoded */ $myaddr = x($_GET, 'address') ? $_GET['address'] : ''; } $target_addr = $a->profile['nickname'] . '@' . substr(z_root(), strpos(z_root(), '://') + 3); /** * * The auto_request form only has the profile address * because nobody is going to read the comments and * it doesn't matter if they know you or not. * */ if ($a->profile['page-flags'] == PAGE_NORMAL) { $tpl = get_markup_template('dfrn_request.tpl'); } else { $tpl = get_markup_template('auto_request.tpl'); } $page_desc = sprintf(t('Diaspora members: Please do not use this form. Instead, enter "%s" into your Diaspora search bar.'), $target_addr) . EOL . EOL; $page_desc .= t("Please enter your 'Identity Address' from one of the following supported social networks:"); $o .= replace_macros($tpl, array('$header' => t('Friend/Connection Request'), '$desc' => t('Examples: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, testuser@identi.ca'), '$pls_answer' => t('Please answer the following:'), '$does_know' => sprintf(t('Does %s know you?'), $a->profile['name']), '$yes' => t('Yes'), '$no' => t('No'), '$add_note' => t('Add a personal note:'), '$page_desc' => $page_desc, '$friendika' => t('Friendica'), '$statusnet' => t('StatusNet/Federated Social Web'), '$diaspora' => t('Diaspora'), '$diasnote' => t('- please share from your own site as noted above'), '$your_address' => t('Your Identity Address:'), '$submit' => t('Submit Request'), '$cancel' => t('Cancel'), '$nickname' => $a->argv[1], '$name' => $a->profile['name'], '$myaddr' => $myaddr)); return $o; } return; // Somebody is fishing. }
/** * @brief Send warnings every 3-5 days if cron is not running. */ function check_cron_broken() { $t = get_config('system', 'lastpollcheck'); if (!$t) { // never checked before. Start the timer. set_config('system', 'lastpollcheck', datetime_convert()); return; } if ($t > datetime_convert('UTC', 'UTC', 'now - 3 days')) { // Wait for 3 days before we do anything so as not to swamp the admin with messages return; } $d = get_config('system', 'lastpoll'); if ($d && $d > datetime_convert('UTC', 'UTC', 'now - 3 days')) { // Scheduled tasks have run successfully in the last 3 days. set_config('system', 'lastpollcheck', datetime_convert()); return; } $a = get_app(); $email_tpl = get_intltext_template("cron_bad_eml.tpl"); $email_msg = replace_macros($email_tpl, array('$sitename' => $a->config['system']['sitename'], '$siteurl' => $a->get_baseurl(), '$error' => t('Cron/Scheduled tasks not running.'), '$lastdate' => $d ? $d : t('never'))); $subject = email_header_encode(sprintf(t('[red] Cron tasks not running on %s'), $a->get_hostname())); mail($a->config['system']['admin_email'], $subject, $email_msg, 'From: Administrator' . '@' . $a->get_hostname() . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); set_config('system', 'lastpollcheck', datetime_convert()); return; }
function check_config(&$a) { $build = get_config('system', 'build'); if (!x($build)) { $build = set_config('system', 'build', DB_UPDATE_VERSION); } $url = get_config('system', 'url'); // if the url isn't set or the stored url is radically different // than the currently visited url, store the current value accordingly. // "Radically different" ignores common variations such as http vs https // and www.example.com vs example.com. if (!x($url) || !link_compare($url, $a->get_baseurl())) { $url = set_config('system', 'url', $a->get_baseurl()); } if ($build != DB_UPDATE_VERSION) { $stored = intval($build); $current = intval(DB_UPDATE_VERSION); if ($stored < $current && file_exists('update.php')) { load_config('database'); // We're reporting a different version than what is currently installed. // Run any existing update scripts to bring the database up to current. require_once 'update.php'; // make sure that boot.php and update.php are the same release, we might be // updating right this very second and the correct version of the update.php // file may not be here yet. This can happen on a very busy site. if (DB_UPDATE_VERSION == UPDATE_VERSION) { for ($x = $stored; $x < $current; $x++) { if (function_exists('update_' . $x)) { // There could be a lot of processes running or about to run. // We want exactly one process to run the update command. // So store the fact that we're taking responsibility // after first checking to see if somebody else already has. // If the update fails or times-out completely you may need to // delete the config entry to try again. if (get_config('database', 'update_' . $x)) { break; } set_config('database', 'update_' . $x, '1'); // call the specific update $func = 'update_' . $x; $retval = $func(); if ($retval) { //send the administrator an e-mail $email_tpl = get_intltext_template("update_fail_eml.tpl"); $email_msg = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$update' => $x, '$error' => sprintf(t('Update %s failed. See error logs.'), $x))); $subject = sprintf(t('Update Error at %s'), $a->get_baseurl()); mail($a->config['admin_email'], $subject, $email_msg, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); //try the logger logger('CRITICAL: Update Failed: ' . $x); } else { set_config('database', 'update_' . $x, 'success'); } } } set_config('system', 'build', DB_UPDATE_VERSION); } } } /** * * Synchronise plugins: * * $a->config['system']['addon'] contains a comma-separated list of names * of plugins/addons which are used on this system. * Go through the database list of already installed addons, and if we have * an entry, but it isn't in the config list, call the uninstall procedure * and mark it uninstalled in the database (for now we'll remove it). * Then go through the config list and if we have a plugin that isn't installed, * call the install procedure and add it to the database. * */ $r = q("SELECT * FROM `addon` WHERE `installed` = 1"); if (count($r)) { $installed = $r; } else { $installed = array(); } $plugins = get_config('system', 'addon'); $plugins_arr = array(); if ($plugins) { $plugins_arr = explode(',', str_replace(' ', '', $plugins)); } $a->plugins = $plugins_arr; $installed_arr = array(); if (count($installed)) { foreach ($installed as $i) { if (!in_array($i['name'], $plugins_arr)) { uninstall_plugin($i['name']); } else { $installed_arr[] = $i['name']; } } } if (count($plugins_arr)) { foreach ($plugins_arr as $p) { if (!in_array($p, $installed_arr)) { install_plugin($p); } } } load_hooks(); return; }
function install_post(&$a) { global $install_wizard_pass, $db; switch ($install_wizard_pass) { case 1: case 2: return; break; // just in case return don't return :) // just in case return don't return :) case 3: $urlpath = $a->get_path(); $dbhost = notags(trim($_POST['dbhost'])); $dbuser = notags(trim($_POST['dbuser'])); $dbpass = notags(trim($_POST['dbpass'])); $dbdata = notags(trim($_POST['dbdata'])); $phpath = notags(trim($_POST['phpath'])); require_once "include/dba.php"; unset($db); $db = new dba($dbhost, $dbuser, $dbpass, $dbdata, true); /*if(get_db_errno()) { unset($db); $db = new dba($dbhost, $dbuser, $dbpass, '', true); if(! get_db_errno()) { $r = q("CREATE DATABASE '%s'", dbesc($dbdata) ); if($r) { unset($db); $db = new dba($dbhost, $dbuser, $dbpass, $dbdata, true); } else { $a->data['db_create_failed']=true; } } else { $a->data['db_conn_failed']=true; return; } }*/ if (get_db_errno()) { $a->data['db_conn_failed'] = true; } return; break; case 4: $urlpath = $a->get_path(); $dbhost = notags(trim($_POST['dbhost'])); $dbuser = notags(trim($_POST['dbuser'])); $dbpass = notags(trim($_POST['dbpass'])); $dbdata = notags(trim($_POST['dbdata'])); $phpath = notags(trim($_POST['phpath'])); $timezone = notags(trim($_POST['timezone'])); $adminmail = notags(trim($_POST['adminmail'])); // connect to db $db = new dba($dbhost, $dbuser, $dbpass, $dbdata, true); $tpl = get_intltext_template('htconfig.tpl'); $txt = replace_macros($tpl, array('$dbhost' => $dbhost, '$dbuser' => $dbuser, '$dbpass' => $dbpass, '$dbdata' => $dbdata, '$timezone' => $timezone, '$urlpath' => $urlpath, '$phpath' => $phpath, '$adminmail' => $adminmail)); $result = file_put_contents('.htconfig.php', $txt); if (!$result) { $a->data['txt'] = $txt; } $errors = load_database($db); if ($errors) { $a->data['db_failed'] = $errors; } else { $a->data['db_installed'] = true; } return; break; } }
function register_post(&$a) { global $lang; $verified = 0; $blocked = 1; $arr = array('post' => $_POST); call_hooks('register_post', $arr); $max_dailies = intval(get_config('system', 'max_daily_registrations')); if ($max_dailes) { $r = q("select count(*) as total from user where register_date > UTC_TIMESTAMP - INTERVAL 1 day"); if ($r && $r[0]['total'] >= $max_dailies) { return; } } switch ($a->config['register_policy']) { case REGISTER_OPEN: $blocked = 0; $verified = 1; break; case REGISTER_APPROVE: $blocked = 1; $verified = 0; break; default: case REGISTER_CLOSED: if (!x($_SESSION, 'authenticated') && !x($_SESSION, 'administrator')) { notice(t('Permission denied.') . EOL); return; } $blocked = 1; $verified = 0; break; } require_once 'include/user.php'; $arr = $_POST; $arr['blocked'] = $blocked; $arr['verified'] = $verified; $result = create_user($arr); if (!$result['success']) { notice($result['message']); return; } $user = $result['user']; if ($netpublish && $a->config['register_policy'] != REGISTER_APPROVE) { $url = $a->get_baseurl() . '/profile/' . $user['nickname']; proc_run('php', "include/directory.php", "{$url}"); } $using_invites = get_config('system', 'invitation_only'); $num_invites = get_config('system', 'number_invites'); $invite_id = x($_POST, 'invite_id') ? notags(trim($_POST['invite_id'])) : ''; if ($a->config['register_policy'] == REGISTER_OPEN) { if ($using_invites && $invite_id) { q("delete * from register where hash = '%s' limit 1", dbesc($invite_id)); set_pconfig($user['uid'], 'system', 'invites_remaining', $num_invites); } $email_tpl = get_intltext_template("register_open_eml.tpl"); $email_tpl = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $user['username'], '$email' => $user['email'], '$password' => $result['password'], '$uid' => $user['uid'])); $res = mail($user['email'], sprintf(t('Registration details for %s'), $a->config['sitename']), $email_tpl, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); if ($res) { info(t('Registration successful. Please check your email for further instructions.') . EOL); goaway(z_root()); } else { notice(t('Failed to send email message. Here is the message that failed.') . $email_tpl . EOL); } } elseif ($a->config['register_policy'] == REGISTER_APPROVE) { if (!strlen($a->config['admin_email'])) { notice(t('Your registration can not be processed.') . EOL); goaway(z_root()); } $hash = random_string(); $r = q("INSERT INTO `register` ( `hash`, `created`, `uid`, `password`, `language` ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ", dbesc($hash), dbesc(datetime_convert()), intval($user['uid']), dbesc($result['password']), dbesc($lang)); $r = q("SELECT `language` FROM `user` WHERE `email` = '%s' LIMIT 1", dbesc($a->config['admin_email'])); if (count($r)) { push_lang($r[0]['language']); } else { push_lang('en'); } if ($using_invites && $invite_id) { q("delete * from register where hash = '%s' limit 1", dbesc($invite_id)); set_pconfig($user['uid'], 'system', 'invites_remaining', $num_invites); } $email_tpl = get_intltext_template("register_verify_eml.tpl"); $email_tpl = replace_macros($email_tpl, array('$sitename' => $a->config['sitename'], '$siteurl' => $a->get_baseurl(), '$username' => $user['username'], '$email' => $user['email'], '$password' => $result['password'], '$uid' => $user['uid'], '$hash' => $hash)); $res = mail($a->config['admin_email'], sprintf(t('Registration request at %s'), $a->config['sitename']), $email_tpl, 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit'); pop_lang(); if ($res) { info(t('Your registration is pending approval by the site owner.') . EOL); goaway(z_root()); } } return; }