Beispiel #1
0
            function emailadmins($idofuser, $ticketid)
            {
                include '../page/db.php';
                $sql = "SELECT * FROM UserAccounts WHERE RowID='{$idofuser}'";
                $emaildata = mysqli_query($conn, $sql);
                $emaildata = mysqli_fetch_assoc($emaildata);
                $to = $emaildata['Email'];
                $subject = 'New Support Ticket';
                $message = '
								<html>
								<head>
								  <title>New Support Ticket</title>
								</head>
								<body>
								  <p>' . $emaildata['UserName'] . ',</p>
								  <p>A new support ticket was posted. Click here to view it <a href="http:ChrisSiena.com/support/TicketView?a=' . base64url_encode($ticketid) . '">http:ChrisSiena.com/support/TicketView?a=' . base64url_encode($ticketid) . '</a> or copy and paste this into your browser.</p><br />
								  <p>Do not reply to this email. It will not be checked.</p>
								</body>
								</html>
								';
                $headers .= 'MIME-Version: 1.0' . "\r\n";
                $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
                $headers .= 'From: ChrisSiena.com@ChrisSiena.com' . "\r\n";
                $headers .= 'Return-Path: return@ChrisSiena.com' . "\r\n";
                $headers .= 'X-Mailer: PHP/' . phpversion();
                mail($to, $subject, $message, $headers, '*****@*****.**');
                mysqli_close($conn);
            }
 function validate_credentials_front()
 {
     $this->load->library('form_validation');
     $this->form_validation->set_rules('username', 'User Name', 'required');
     $this->form_validation->set_rules('password', 'Password', 'required');
     $this->form_validation->set_error_delimiters('<div class="alert alert-error"><a class="close" data-dismiss="alert">&#215;</a><strong>', '</strong></div>');
     if ($this->form_validation->run()) {
         if (!$this->session->userdata('is_logged_in')) {
             $this->load->model('Admin_model');
             $username = $this->input->post('username');
             $password = $this->__encrip_password($this->input->post('password'));
             $is_valid = $this->Admin_model->validate_front($username, $password);
             if ($is_valid) {
                 $where_username = "******";
                 $user_type = $this->common_model->getFieldData('user', 'type_of_membership', $where_username);
                 if ($user_type == "User") {
                     $is_account_confirm = $this->Admin_model->validate_front_account_confirm($username);
                     if ($is_account_confirm) {
                         $stored_user_data = $this->Admin_model->get_user_id($username);
                         $user_id = $stored_user_data[0]->user_id;
                         $primary_email = $stored_user_data[0]->primary_email;
                         $affiliate = $stored_user_data[0]->type;
                         $type_of_membership = $stored_user_data[0]->type_of_membership;
                         if (!empty($affiliate)) {
                             $type = $affiliate;
                         } else {
                             $type = 'user';
                         }
                         $data = array('username' => $username, 'primary_email' => $primary_email, 'user_id' => $user_id, 'type' => $type, 'type_of_membership' => $type_of_membership, 'is_logged_in' => true);
                         $this->session->set_userdata($data);
                         if ($affiliate == 'affiliate') {
                             redirect("signin/signin_user/{$user_id}/affiliate");
                         } else {
                             $email = base64url_encode($primary_email);
                             redirect("home/account/{$user_id}/{$email}");
                         }
                     } else {
                         $this->session->set_flashdata('flash_class', 'alert-danger');
                         $this->session->set_flashdata('flash_message', '<strong>ohh snap!</strong> Please Confirm Your Account By Your Email  </strong>');
                         redirect('signin/signin_user');
                     }
                 } else {
                     $this->session->set_flashdata('flash_class', 'alert-danger');
                     $this->session->set_flashdata('flash_message', '<strong>ohh snap!</strong> Your are Affiliate User Please login with Affilite login </strong>');
                     redirect('signin/signin_user');
                 }
             } else {
                 $url = '<a href="' . base_url() . 'home/set_pass_mail">reset your password</a>';
                 $this->session->set_flashdata('flash_class', 'alert-danger');
                 $this->session->set_flashdata('flash_message', '<strong>ohh snap!</strong> Wrong Username And Password  </strong>');
                 $this->session->set_flashdata('flash_reset_url', 'Please try again or <strong>' . $url . '</strong>');
                 redirect('signin/signin_user');
             }
         } else {
             redirect('home');
         }
     }
     $data['main_content'] = 'signin_view';
     $this->load->view('includes/template', $data);
 }
Beispiel #3
0
 function random_string($size = 64, $type = RANDOM_STRING_HEX)
 {
     // generate a bit of entropy and run it through the whirlpool
     $s = hash('whirlpool', (string) rand() . uniqid(rand(), true) . (string) rand(), $type == RANDOM_STRING_TEXT ? true : false);
     $s = $type == RANDOM_STRING_TEXT ? str_replace("\n", "", base64url_encode($s, true)) : $s;
     return substr($s, 0, $size);
 }
Beispiel #4
0
function slapper($owner, $url, $slap)
{
    // does contact have a salmon endpoint?
    if (!strlen($url)) {
        return;
    }
    if (!$owner['channel_prvkey']) {
        logger(sprintf("channel '%s' (%d) does not have a salmon private key. Send failed.", $owner['channel_address'], $owner['channel_id']));
        return;
    }
    logger('slapper called for ' . $url . '. Data: ' . $slap, LOGGER_DATA, LOG_DEBUG);
    // create a magic envelope
    $data = base64url_encode($slap);
    $data_type = 'application/atom+xml';
    $encoding = 'base64url';
    $algorithm = 'RSA-SHA256';
    $keyhash = base64url_encode(hash('sha256', salmon_key($owner['channel_pubkey'])), true);
    // precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
    $precomputed = '.YXBwbGljYXRpb24vYXRvbSt4bWw=.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
    $signature = base64url_encode(rsa_sign(str_replace('=', '', $data . $precomputed), $owner['channel_prvkey']));
    $signature2 = base64url_encode(rsa_sign($data . $precomputed, $owner['channel_prvkey']));
    $signature3 = base64url_encode(rsa_sign($data, $owner['channel_prvkey']));
    $salmon_tpl = get_markup_template('magicsig.tpl');
    $salmon = replace_macros($salmon_tpl, array('$data' => $data, '$encoding' => $encoding, '$algorithm' => $algorithm, '$keyhash' => $keyhash, '$signature' => $signature));
    // slap them
    $redirects = 0;
    $ret = z_post_url($url, $salmon, $redirects, array('headers' => array('Content-type: application/magic-envelope+xml', 'Content-length: ' . strlen($salmon))));
    $return_code = $ret['return_code'];
    // check for success, e.g. 2xx
    if ($return_code > 299) {
        logger('compliant salmon failed. Falling back to status.net hack2');
        // Entirely likely that their salmon implementation is
        // non-compliant. Let's try once more, this time only signing
        // the data, without stripping '=' chars
        $salmon = replace_macros($salmon_tpl, array('$data' => $data, '$encoding' => $encoding, '$algorithm' => $algorithm, '$keyhash' => $keyhash, '$signature' => $signature2));
        $redirects = 0;
        $ret = z_post_url($url, $salmon, $redirects, array('headers' => array('Content-type: application/magic-envelope+xml', 'Content-length: ' . strlen($salmon))));
        $return_code = $ret['return_code'];
        if ($return_code > 299) {
            logger('compliant salmon failed. Falling back to status.net hack3');
            // Entirely likely that their salmon implementation is
            // non-compliant. Let's try once more, this time only signing
            // the data, without the precomputed blob
            $salmon = replace_macros($salmon_tpl, array('$data' => $data, '$encoding' => $encoding, '$algorithm' => $algorithm, '$keyhash' => $keyhash, '$signature' => $signature3));
            $redirects = 0;
            $ret = z_post_url($url, $salmon, $redirects, array('headers' => array('Content-type: application/magic-envelope+xml', 'Content-length: ' . strlen($salmon))));
            $return_code = $ret['return_code'];
        }
    }
    logger('slapper for ' . $url . ' returned ' . $return_code);
    if (!$return_code) {
        return -1;
    }
    if ($return_code == 503 && stristr($ret['header'], 'retry-after')) {
        return -1;
    }
    return $return_code >= 200 && $return_code < 300 ? 0 : 1;
}
Beispiel #5
0
function generate_state_parameter()
{
    if (isset($_SESSION['state'])) {
        return $_SESSION['state'];
    } else {
        $state = base64url_encode(openssl_random_pseudo_bytes(32));
        $_SESSION['state'] = $state;
        return $state;
    }
}
Beispiel #6
0
 function login_nonce(&$args)
 {
     /* generate a nonce (state) for this oauth request */
     function base64url_encode($data)
     {
         return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
     }
     $_SESSION['nonce'] = base64url_encode(openssl_random_pseudo_bytes(32));
     $args->retval = $_SESSION['nonce'];
 }
Beispiel #7
0
 function get()
 {
     $uid = local_channel();
     if (\App::$is_sys && is_site_admin()) {
         $sys = get_sys_channel();
         $uid = intval($sys['channel_id']);
     }
     if (!$uid) {
         notice(t('Permission denied.') . EOL);
         return '';
     }
     if (argc() == 1) {
         $channel = $sys ? $sys : \App::get_channel();
         // list menus
         $x = menu_list($uid);
         if ($x) {
             for ($y = 0; $y < count($x); $y++) {
                 $m = menu_fetch($x[$y]['menu_name'], $uid, get_observer_hash());
                 if ($m) {
                     $x[$y]['element'] = '[element]' . base64url_encode(json_encode(menu_element($channel, $m))) . '[/element]';
                 }
                 $x[$y]['bookmark'] = $x[$y]['menu_flags'] & MENU_BOOKMARK ? true : false;
             }
         }
         $create = replace_macros(get_markup_template('menuedit.tpl'), array('$menu_name' => array('menu_name', t('Menu Name'), '', t('Unique name (not visible on webpage) - required'), '*'), '$menu_desc' => array('menu_desc', t('Menu Title'), '', t('Visible on webpage - leave empty for no title'), ''), '$menu_bookmark' => array('menu_bookmark', t('Allow Bookmarks'), 0, t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))), '$submit' => t('Submit and proceed'), '$sys' => \App::$is_sys, '$display' => 'none'));
         $o = replace_macros(get_markup_template('menulist.tpl'), array('$title' => t('Menus'), '$create' => $create, '$menus' => $x, '$nametitle' => t('Menu Name'), '$desctitle' => t('Menu Title'), '$edit' => t('Edit'), '$drop' => t('Drop'), '$created' => t('Created'), '$edited' => t('Edited'), '$new' => t('New'), '$bmark' => t('Bookmarks allowed'), '$hintnew' => t('Create'), '$hintdrop' => t('Delete this menu'), '$hintcontent' => t('Edit menu contents'), '$hintedit' => t('Edit this menu'), '$sys' => \App::$is_sys));
         return $o;
     }
     if (argc() > 1) {
         if (intval(argv(1))) {
             if (argc() == 3 && argv(2) == 'drop') {
                 menu_sync_packet($uid, get_observer_hash(), intval(argv(1)), true);
                 $r = menu_delete_id(intval(argv(1)), $uid);
                 if (!$r) {
                     notice(t('Menu could not be deleted.') . EOL);
                 }
                 goaway(z_root() . '/menu' . (\App::$is_sys ? '?f=&sys=1' : ''));
             }
             $m = menu_fetch_id(intval(argv(1)), $uid);
             if (!$m) {
                 notice(t('Menu not found.') . EOL);
                 return '';
             }
             $o = replace_macros(get_markup_template('menuedit.tpl'), array('$header' => t('Edit Menu'), '$sys' => \App::$is_sys, '$menu_id' => intval(argv(1)), '$menu_edit_link' => 'mitem/' . intval(argv(1)) . (\App::$is_sys ? '?f=&sys=1' : ''), '$hintedit' => t('Add or remove entries to this menu'), '$editcontents' => t('Edit menu contents'), '$menu_name' => array('menu_name', t('Menu name'), $m['menu_name'], t('Must be unique, only seen by you'), '*'), '$menu_desc' => array('menu_desc', t('Menu title'), $m['menu_desc'], t('Menu title as seen by others'), ''), '$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), $m['menu_flags'] & MENU_BOOKMARK ? 1 : 0, t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))), '$menu_system' => $m['menu_flags'] & MENU_SYSTEM ? 1 : 0, '$submit' => t('Submit and proceed')));
             return $o;
         } else {
             notice(t('Not found.') . EOL);
             return;
         }
     }
 }
Beispiel #8
0
function loadcomment($id, $number)
{
    include '../page/protection.php';
    include '../page/db.php';
    $id = (int) base64url_decode($id);
    $sql = "SELECT * FROM Comments WHERE ID='{$id}'";
    $data = mysqli_query($conn, $sql);
    $data = mysqli_fetch_assoc($data);
    $userid = $data['UserID'];
    $usersql = "SELECT UserName,ProfilePicture FROM UserAccounts WHERE RowID='{$userid}'";
    $userdata = mysqli_query($conn, $usersql);
    $userdata = mysqli_fetch_assoc($userdata);
    $user = $userdata['UserName'];
    $comment = $data['Comment'];
    $space = "&emsp;";
    $postdate = date_create($data['CreateDate']);
    $postdate = date_format($postdate, 'm/d/Y g:ia');
    $modifieddate = date_create($data['ModifiedDate']);
    $modifieddate = date_format($modifieddate, 'm/d/Y g:ia');
    if ($userid === $_SESSION['id']) {
        $poster = "<span style=\"float:right;padding-right:10px;\" class=\"link2\"><a href=\"/admin/CommentDelete?a=" . base64url_encode($id) . "\">Delete</a></span>";
    }
    if ($data['Edited']) {
        $time = "<span style=\"float:right;\">Edited: " . $modifieddate . "</span>";
    } else {
        $time = "<span style=\"float:right;\">Posted: " . $postdate . "</span>";
    }
    $text .= "\n\t\t\t<div class=\"commentshadow\" id=\"comment-{$id}\">\n\t\t\t<div class=\"commenttitle\">#{$number} " . $time . $poster . "</div>\n\t\t\t<div class=\"fullcomment\">\n\t\t\t<!--<hr class=\"commenthr\">-->\n\t\t\t<div class=\"commentimage\">\n\t\t";
    $text .= "<div class=\"commentimageinner\"><span class=\"profilepichelper\"></span>";
    if (strlen($userdata['ProfilePicture'])) {
        $text .= "<img src=\"/account/ProfilePictureShow?a=" . base64url_encode($userid) . "\" class=\"commentpic\">";
    } else {
        $text .= "<img src=\"/theme/grey-question-mark.png\" class=\"commentpic hideLight\">";
        $text .= "<img src=\"/theme/darkgrey-question-mark.png\" class=\"commentpic hideDark\">";
    }
    $text .= "</div>";
    $text .= "\n\t\t\t</div>\n\t\t\t\t<div class=\"commentusername\"><span class=\"link3\"><a href=\"/account/Profile?a=" . base64url_encode($userid) . "\">{$user}</a></span></div>\n\t\t";
    include '../page/BBCode.php';
    if (isset($comment)) {
        $comment = decrypt($comment);
        $comment = strip_tags($comment);
        $comment = preg_replace('/\\r\\n?/', "\n<br />", $comment);
        $comment = bb_parse($comment);
    } else {
        $comment = '';
    }
    $text .= "<div class=\"comment\">" . $comment . "</div></div></div>";
    mysqli_close($conn);
    return $text;
}
Beispiel #9
0
 /**
  * 输出上传图片按钮,调用上传窗口
  */
 public function uploadButton()
 {
     $config = $this->config;
     if (!isset($config['alowexts']) or empty($config['alowexts'])) {
         $config['alowexts'] = 'jpg,jpeg,gif,bmp,png,doc,docx';
     }
     $uploadObject = new UploadManager();
     if (!isset($config['uploadPath']) or empty($config['uploadPath'])) {
         $config['uploadPath'] = Config::get('sys.sys_upload_path') . '/';
     }
     $config['uploadPath'] = base64url_encode($config['uploadPath']);
     $config['uploadUrl'] = route('foundation.upload.index');
     //生成密钥,附止表单被修改。
     $authkey = $uploadObject->setParam($config)->uploadKey();
     return view('admin.widget.uploadbutton', compact('config', 'authkey'));
 }
function make_rsa_jwk_key($n, $e, $kid = NULL, $use = '')
{
    if (!$n || !$e) {
        return false;
    }
    $key_info = array('e' => base64url_encode($e), 'kty' => 'RSA', 'n' => base64url_encode($n));
    if ($kid) {
        $key_info['kid'] = $kid;
    } else {
        printf("jwk = %s\n", json_encode($key_info));
        $key_info['kid'] = base64url_encode(hash('sha256', json_encode($key_info), true));
    }
    if ($use) {
        $key_info['use'] = $use;
    }
    return $key_info;
}
Beispiel #11
0
 function get()
 {
     if (!is_site_admin()) {
         return;
     }
     $o = '';
     $r = q("select * from channel where channel_removed = 0");
     $sitekey = get_config('system', 'pubkey');
     if ($r) {
         foreach ($r as $rr) {
             $found = false;
             $primary_address = '';
             $x = zot_get_hublocs($rr['channel_hash']);
             if ($x) {
                 foreach ($x as $xx) {
                     if ($xx['hubloc_url'] === z_root() && $xx['hubloc_sitekey'] === $sitekey) {
                         $found = true;
                         break;
                     }
                 }
                 if ($found) {
                     $o .= 'Hubloc exists for ' . $rr['channel_name'] . EOL;
                     continue;
                 }
             }
             $y = q("select xchan_addr from xchan where xchan_hash = '%s' limit 1", dbesc($rr['channel_hash']));
             if ($y) {
                 $primary_address = $y[0]['xchan_addr'];
             }
             $hub_address = $rr['channel']['channel_address'] . '@' . \App::get_hostname();
             $primary = $hub_address === $primary_address ? 1 : 0;
             if (!$y) {
                 $primary = 1;
             }
             $m = q("delete from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ", dbesc($rr['channel_hash']), dbesc(z_root()));
             // Create a verified hub location pointing to this site.
             $h = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_primary, hubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_network )\n\t\t\t\t\tvalues ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )", dbesc($rr['channel_guid']), dbesc($rr['channel_guid_sig']), dbesc($rr['channel_hash']), dbesc($rr['channel_address'] . '@' . \App::get_hostname()), intval($primary), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(), $rr['channel_prvkey']))), dbesc(\App::get_hostname()), dbesc(z_root() . '/post'), dbesc($sitekey), dbesc('zot'));
             if ($h) {
                 $o . 'local hubloc created for ' . $rr['channel_name'] . EOL;
             } else {
                 $o .= 'DB update failed for ' . $rr['channel_name'] . EOL;
             }
         }
         return $o;
     }
 }
 function validate_credentials_front()
 {
     if (!$this->session->userdata('is_logged_in')) {
         $this->load->model('Admin_model');
         $username = $this->input->post('username');
         $password = $this->__encrip_password($this->input->post('password'));
         $is_account_confirm = $this->Admin_model->validate_front_account_confirm($username, $password);
         if ($is_account_confirm) {
             $is_valid = $this->Admin_model->validate_front($username, $password);
             if ($is_valid) {
                 $stored_user_data = $this->Admin_model->get_user_id($username);
                 $user_id = $stored_user_data[0]->user_id;
                 $primary_email = $stored_user_data[0]->primary_email;
                 $affiliate = $stored_user_data[0]->type;
                 $type_of_membership = $stored_user_data[0]->type_of_membership;
                 if (!empty($affiliate)) {
                     $type = $affiliate;
                 } else {
                     $type = 'user';
                 }
                 $data = array('username' => $username, 'primary_email' => $primary_email, 'user_id' => $user_id, 'type' => $type, 'type_of_membership' => $type_of_membership, 'is_logged_in' => true);
                 $this->session->set_userdata($data);
                 if ($affiliate == 'affiliate') {
                     redirect("signin/signin_user/{$user_id}/affiliate");
                 } else {
                     $email = base64url_encode($primary_email);
                     redirect("home/account/{$user_id}/{$email}");
                 }
             } else {
                 $url = '<a href="' . base_url() . 'home/set_pass_mail">reset your password</a>';
                 $this->session->set_flashdata('flash_class', 'alert-danger');
                 $this->session->set_flashdata('flash_message', '<strong>ohh snap!</strong> Wrong Username And Password  </strong>');
                 $this->session->set_flashdata('flash_reset_url', 'Please try again or <strong>' . $url . '</strong>');
                 redirect('signin/signin_user');
             }
         } else {
             $this->session->set_flashdata('flash_class', 'alert-danger');
             $this->session->set_flashdata('flash_message', '<strong>ohh snap!</strong> Please Confirm Your Account By Your Email  </strong>');
             redirect('signin/signin_user');
         }
     } else {
         redirect('home');
     }
 }
Beispiel #13
0
 function index($param = NULL)
 {
     if (!isset($this->ci->session) || !$this->ci->session->userdata('uid')) {
         if ($this->ci->uri->segment(1) != 'login') {
             redirect('login/' . base64url_encode($this->ci->uri->uri_string()), 'location');
         }
     } else {
         $userInfo = $this->ci->User_Model->get($this->ci->session->userdata('uid'), 'username,fullname');
         $this->ci->username = $this->ci->User_Model->get($this->ci->session->userdata('uid'), 'username');
         // 			$this->ci->usertype = $this->ci->User_Model->usertype();
         // 			if( $this->ci->usertype =='partner' ){
         // 				$partnerID = $this->ci->Common_Model->getVal(array('owner'=>$this->ci->session->userdata('uid')),'id',$this->ci->Account_Model->partnerTable);
         // 				$this->ci->parterID = ( is_numeric($partnerID) ) ? $partnerID : NULL;
         // 			} else if ($this->ci->usertype =='customer') {
         // 				$partnerID = $this->ci->Common_Model->getVal(array('owner'=>$this->ci->session->userdata('uid')),'partner',$this->ci->Account_Model->companyTable);
         // 				$companyName = $this->ci->Common_Model->getVal(array('owner'=>$this->ci->session->userdata('uid')),'name',$this->ci->Account_Model->companyTable);
         // 				$this->ci->parterID = ( is_numeric($partnerID) ) ? $partnerID : NULL;
         // 				$this->ci->smartyci->assign('companyname',$companyName);
         // 			}
         $this->ci->smarty->assign('username', $userInfo->username);
         $this->ci->smarty->assign('fullname', $userInfo->fullname);
         // 			if( !class_exists('adminDesigns') ){
         // 			$this->ci->smartyci->assign('usertype',$this->ci->usertype);
     }
     $this->ci->suffix = $this->ci->config->item('url_suffix');
     if (isset($_SERVER['ORIG_PATH_INFO'])) {
         $pathInfo = pathinfo($_SERVER['ORIG_PATH_INFO']);
     } else {
         if (isset($_SERVER['PATH_INFO'])) {
             $pathInfo = pathinfo($_SERVER['PATH_INFO']);
         }
     }
     if (isset($pathInfo['extension']) && $pathInfo['extension']) {
         $this->ci->suffix = $pathInfo['extension'];
     }
     if ($this->ci->suffix == 'json') {
         header('Content-type: application/json');
     }
     $this->ci->lang->load('common', 'english');
     $this->ci->lang->load('common', 'vietnam');
 }
Beispiel #14
0
function prate_post(&$a)
{
    if (!local_channel()) {
        return;
    }
    $channel = App::get_channel();
    $target = trim($_REQUEST['target']);
    if (!$target) {
        return;
    }
    if ($target === $channel['channel_hash']) {
        return;
    }
    $rating = intval($_POST['rating']);
    if ($rating < -10) {
        $rating = -10;
    }
    if ($rating > 10) {
        $rating = 10;
    }
    $rating_text = trim(escape_tags($_REQUEST['rating_text']));
    $signed = $target . '.' . $rating . '.' . $rating_text;
    $sig = base64url_encode(rsa_sign($signed, $channel['channel_prvkey']));
    $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", dbesc($channel['channel_hash']), dbesc($target));
    if ($z) {
        $record = $z[0]['xlink_id'];
        $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'\n\t\t\twhere xlink_id = %d", intval($rating), dbesc($rating_text), dbesc($sig), dbesc(datetime_convert()), intval($record));
    } else {
        $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", dbesc($channel['channel_hash']), dbesc($target), intval($rating), dbesc($rating_text), dbesc($sig), dbesc(datetime_convert()));
        $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", dbesc($channel['channel_hash']), dbesc($orig_record[0]['abook_xchan']));
        if ($z) {
            $record = $z[0]['xlink_id'];
        }
    }
    if ($record) {
        proc_run('php', 'include/ratenotif.php', 'rating', $record);
    }
    json_return_and_die(array('result' => true));
}
function firstConnection($id, $mdp, $IV)
{
    if (file_exists("C:\\wamp64\\www\\Web\\" . $id) != true) {
        $chemin = "C:\\wamp64\\www\\Web\\";
        //On creer un dossier.
        mkdir($chemin . $id);
    }
    //On creer un fichier ou on stocke le mdp.
    $chemin = "C:\\wamp64\\www\\Web\\" . $id . "\\Confg.txt";
    $handle = fopen($chemin, "w+");
    $mdp = chiffrement($mdp, $IV);
    $mdp = base64url_encode($mdp);
    fwrite($handle, "mdp:" . $mdp . "\r\n");
    $min = rand(0, 1000);
    $max = rand(100000, 1000000);
    $code = rand($min, $max);
    $code = chiffrement($code, $IV);
    $code = base64url_encode($code);
    fwrite($handle, "Code:" . $code);
    fclose($handle);
    return $code;
}
Beispiel #16
0
 function post()
 {
     if (!local_channel()) {
         return;
     }
     if (!\App::$data['target']) {
         return;
     }
     if (!$_REQUEST['execute']) {
         return;
     }
     $channel = \App::get_channel();
     $rating = intval($_POST['rating']);
     if ($rating < -10) {
         $rating = -10;
     }
     if ($rating > 10) {
         $rating = 10;
     }
     $rating_text = trim(escape_tags($_REQUEST['rating_text']));
     $signed = \App::$data['target'] . '.' . $rating . '.' . $rating_text;
     $sig = base64url_encode(rsa_sign($signed, $channel['channel_prvkey']));
     $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", dbesc($channel['channel_hash']), dbesc(\App::$data['target']));
     if ($z) {
         $record = $z[0]['xlink_id'];
         $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'\n\t\t\t\twhere xlink_id = %d", intval($rating), dbesc($rating_text), dbesc($sig), dbesc(datetime_convert()), intval($record));
     } else {
         $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", dbesc($channel['channel_hash']), dbesc(\App::$data['target']), intval($rating), dbesc($rating_text), dbesc($sig), dbesc(datetime_convert()));
         $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", dbesc($channel['channel_hash']), dbesc(\App::$data['target']));
         if ($z) {
             $record = $z[0]['xlink_id'];
         }
     }
     if ($record) {
         \Zotlabs\Daemon\Master::Summon(array('Ratenotif', 'rating', $record));
     }
 }
Beispiel #17
0
function check_zotinfo($channel, $locations, &$ret)
{
    //	logger('locations: ' . print_r($locations,true),LOGGER_DATA);
    // This function will likely expand as we find more things to detect and fix.
    // 1. Because magic-auth is reliant on it, ensure that the system channel has a valid hubloc
    //    Force this to be the case if anything is found to be wrong with it.
    // @FIXME ensure that the system channel exists in the first place and has an xchan
    if ($channel['channel_system']) {
        // the sys channel must have a location (hubloc)
        $valid_location = false;
        if (count($locations) === 1 && $locations[0]['primary'] && !$locations[0]['deleted']) {
            if (rsa_verify($locations[0]['url'], base64url_decode($locations[0]['url_sig']), $channel['channel_pubkey']) && $locations[0]['sitekey'] === get_config('system', 'pubkey') && $locations[0]['url'] === z_root()) {
                $valid_location = true;
            } else {
                logger('sys channel: invalid url signature');
            }
        }
        if (!$locations || !$valid_location) {
            logger('System channel locations are not valid. Attempting repair.');
            // Don't trust any existing records. Just get rid of them, but only do this
            // for the sys channel as normal channels will be trickier.
            q("delete from hubloc where hubloc_hash = '%s'", dbesc($channel['channel_hash']));
            $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_primary,\n\t\t\t\thubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_network )\n\t\t\t\tvalues ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )", dbesc($channel['channel_guid']), dbesc($channel['channel_guid_sig']), dbesc($channel['channel_hash']), dbesc($channel['channel_address'] . '@' . get_app()->get_hostname()), intval(1), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(), $channel['channel_prvkey']))), dbesc(get_app()->get_hostname()), dbesc(z_root() . '/post'), dbesc(get_config('system', 'pubkey')), dbesc('zot'));
            if ($r) {
                $x = zot_encode_locations($channel);
                if ($x) {
                    $ret['locations'] = $x;
                }
            } else {
                logger('Unable to store sys hub location');
            }
        }
    }
}
Beispiel #18
0
 function get()
 {
     $change = false;
     logger('mod_group: ' . \App::$cmd, LOGGER_DEBUG);
     if (!local_channel()) {
         notice(t('Permission denied') . EOL);
         return;
     }
     // Switch to text mode interface if we have more than 'n' contacts or group members
     $switchtotext = get_pconfig(local_channel(), 'system', 'groupedit_image_limit');
     if ($switchtotext === false) {
         $switchtotext = get_config('system', 'groupedit_image_limit');
     }
     if ($switchtotext === false) {
         $switchtotext = 400;
     }
     $tpl = get_markup_template('group_edit.tpl');
     $context = array('$submit' => t('Submit'));
     if (argc() == 2 && argv(1) === 'new') {
         return replace_macros($tpl, $context + array('$title' => t('Create a group of channels.'), '$gname' => array('groupname', t('Privacy group name: '), '', ''), '$gid' => 'new', '$public' => array('public', t('Members are visible to other channels'), false, ''), '$form_security_token' => get_form_security_token("group_edit")));
     }
     if (argc() == 3 && argv(1) === 'drop') {
         check_form_security_token_redirectOnErr('/group', 'group_drop', 't');
         if (intval(argv(2))) {
             $r = q("SELECT `name` FROM `groups` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval(argv(2)), intval(local_channel()));
             if ($r) {
                 $result = group_rmv(local_channel(), $r[0]['gname']);
             }
             if ($result) {
                 info(t('Privacy group removed.') . EOL);
             } else {
                 notice(t('Unable to remove privacy group.') . EOL);
             }
         }
         goaway(z_root() . '/group');
         // NOTREACHED
     }
     if (argc() > 2 && intval(argv(1)) && argv(2)) {
         check_form_security_token_ForbiddenOnErr('group_member_change', 't');
         $r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1", dbesc(base64url_decode(argv(2))), intval(local_channel()));
         if (count($r)) {
             $change = base64url_decode(argv(2));
         }
     }
     if (argc() > 1 && intval(argv(1))) {
         require_once 'include/acl_selectors.php';
         $r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", intval(argv(1)), intval(local_channel()));
         if (!$r) {
             notice(t('Privacy group not found.') . EOL);
             goaway(z_root() . '/connections');
         }
         $group = $r[0];
         $members = group_get_members($group['id']);
         $preselected = array();
         if (count($members)) {
             foreach ($members as $member) {
                 if (!in_array($member['xchan_hash'], $preselected)) {
                     $preselected[] = $member['xchan_hash'];
                 }
             }
         }
         if ($change) {
             if (in_array($change, $preselected)) {
                 group_rmv_member(local_channel(), $group['gname'], $change);
             } else {
                 group_add_member(local_channel(), $group['gname'], $change);
             }
             $members = group_get_members($group['id']);
             $preselected = array();
             if (count($members)) {
                 foreach ($members as $member) {
                     $preselected[] = $member['xchan_hash'];
                 }
             }
         }
         $drop_tpl = get_markup_template('group_drop.tpl');
         $drop_txt = replace_macros($drop_tpl, array('$id' => $group['id'], '$delete' => t('Delete'), '$form_security_token' => get_form_security_token("group_drop")));
         $context = $context + array('$title' => t('Privacy group editor'), '$gname' => array('groupname', t('Privacy group name: '), $group['gname'], ''), '$gid' => $group['id'], '$drop' => $drop_txt, '$public' => array('public', t('Members are visible to other channels'), $group['visible'], ''), '$form_security_token' => get_form_security_token('group_edit'));
     }
     if (!isset($group)) {
         return;
     }
     $groupeditor = array('label_members' => t('Members'), 'members' => array(), 'label_contacts' => t('All Connected Channels'), 'contacts' => array());
     $sec_token = addslashes(get_form_security_token('group_member_change'));
     $textmode = $switchtotext && count($members) > $switchtotext ? true : false;
     foreach ($members as $member) {
         if ($member['xchan_url']) {
             $member['archived'] = intval($member['abook_archived']) ? true : false;
             $member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
             $groupeditor['members'][] = micropro($member, true, 'mpgroup', $textmode);
         } else {
             group_rmv_member(local_channel(), $group['gname'], $member['xchan_hash']);
         }
     }
     $r = q("SELECT abook.*, xchan.* FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel` = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc", intval(local_channel()));
     if (count($r)) {
         $textmode = $switchtotext && count($r) > $switchtotext ? true : false;
         foreach ($r as $member) {
             if (!in_array($member['xchan_hash'], $preselected)) {
                 $member['archived'] = intval($member['abook_archived']) ? true : false;
                 $member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;';
                 $groupeditor['contacts'][] = micropro($member, true, 'mpall', $textmode);
             }
         }
     }
     $context['$groupeditor'] = $groupeditor;
     $context['$desc'] = t('Click on a channel to add or remove.');
     if ($change) {
         $tpl = get_markup_template('groupeditor.tpl');
         echo replace_macros($tpl, $context);
         killme();
     }
     return replace_macros($tpl, $context);
 }
Beispiel #19
0
/**
 * @brief Process atom feed and update anything/everything we might need to update.
 *
 * $hub = should we find a hub declation in the feed, pass it back to our calling process, who might (or
 *        might not) try and subscribe to it.
 * $datedir sorts in reverse order
 *
 * @param array $xml
 *   The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
 * @param $importer
 *   The contact_record (joined to user_record) of the local user who owns this
 *   relationship. It is this person's stuff that is going to be updated.
 * @param $contact
 *   The person who is sending us stuff. If not set, we MAY be processing a "follow" activity
 *   from an external network and MAY create an appropriate contact record. Otherwise, we MUST
 *   have a contact record.
 * @param int $pass by default ($pass = 0) we cannot guarantee that a parent item has been
 *   imported prior to its children being seen in the stream unless we are certain
 *   of how the feed is arranged/ordered.
 *  * With $pass = 1, we only pull parent items out of the stream.
 *  * With $pass = 2, we only pull children (comments/likes).
 *
 * So running this twice, first with pass 1 and then with pass 2 will do the right
 * thing regardless of feed ordering. This won't be adequate in a fully-threaded
 * model where comments can have sub-threads. That would require some massive sorting
 * to get all the feed items into a mostly linear ordering, and might still require
 * recursion.
 */
function consume_feed($xml, $importer, &$contact, $pass = 0)
{
    require_once 'library/simplepie/simplepie.inc';
    if (!strlen($xml)) {
        logger('consume_feed: empty input');
        return;
    }
    $feed = new SimplePie();
    $feed->set_raw_data($xml);
    $feed->init();
    if ($feed->error()) {
        logger('consume_feed: Error parsing XML: ' . $feed->error());
    }
    $permalink = $feed->get_permalink();
    // Check at the feed level for updated contact name and/or photo
    // process any deleted entries
    $del_entries = $feed->get_feed_tags(NAMESPACE_TOMB, 'deleted-entry');
    if (is_array($del_entries) && count($del_entries) && $pass != 2) {
        foreach ($del_entries as $dentry) {
            $deleted = false;
            if (isset($dentry['attribs']['']['ref'])) {
                $mid = $dentry['attribs']['']['ref'];
                $deleted = true;
                if (isset($dentry['attribs']['']['when'])) {
                    $when = $dentry['attribs']['']['when'];
                    $when = datetime_convert('UTC', 'UTC', $when, 'Y-m-d H:i:s');
                } else {
                    $when = datetime_convert('UTC', 'UTC', 'now', 'Y-m-d H:i:s');
                }
            }
            if ($deleted && is_array($contact)) {
                $r = q("SELECT * from item where mid = '%s' and author_xchan = '%s' and uid = %d limit 1", dbesc(base64url_encode($mid)), dbesc($contact['xchan_hash']), intval($importer['channel_id']));
                if ($r) {
                    $item = $r[0];
                    if (!($item['item_restrict'] & ITEM_DELETED)) {
                        logger('consume_feed: deleting item ' . $item['id'] . ' mid=' . base64url_decode($item['mid']), LOGGER_DEBUG);
                        drop_item($item['id'], false);
                    }
                }
            }
        }
    }
    // Now process the feed
    if ($feed->get_item_quantity()) {
        logger('consume_feed: feed item count = ' . $feed->get_item_quantity(), LOGGER_DEBUG);
        $items = $feed->get_items();
        foreach ($items as $item) {
            $is_reply = false;
            $item_id = base64url_encode($item->get_id());
            logger('consume_feed: processing ' . $item_id, LOGGER_DEBUG);
            $rawthread = $item->get_item_tags(NAMESPACE_THREAD, 'in-reply-to');
            if (isset($rawthread[0]['attribs']['']['ref'])) {
                $is_reply = true;
                $parent_mid = base64url_encode($rawthread[0]['attribs']['']['ref']);
            }
            if ($is_reply) {
                if ($pass == 1) {
                    continue;
                }
                // Have we seen it? If not, import it.
                $item_id = base64url_encode($item->get_id());
                $author = array();
                $datarray = get_atom_elements($feed, $item, $author);
                if (!x($author, 'author_name') || $author['author_is_feed']) {
                    $author['author_name'] = $contact['xchan_name'];
                }
                if (!x($author, 'author_link') || $author['author_is_feed']) {
                    $author['author_link'] = $contact['xchan_url'];
                }
                if (!x($author, 'author_photo') || $author['author_is_feed']) {
                    $author['author_photo'] = $contact['xchan_photo_m'];
                }
                $datarray['author_xchan'] = '';
                if ($author['author_link'] != $contact['xchan_url']) {
                    $x = import_author_unknown(array('name' => $author['author_name'], 'url' => $author['author_link'], 'photo' => array('src' => $author['author_photo'])));
                    if ($x) {
                        $datarray['author_xchan'] = $x;
                    }
                }
                if (!$datarray['author_xchan']) {
                    $datarray['author_xchan'] = $contact['xchan_hash'];
                }
                $datarray['owner_xchan'] = $contact['xchan_hash'];
                $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1", dbesc($item_id), intval($importer['channel_id']));
                // Update content if 'updated' changes
                if ($r) {
                    if (x($datarray, 'edited') !== false && datetime_convert('UTC', 'UTC', $datarray['edited']) !== $r[0]['edited']) {
                        // do not accept (ignore) an earlier edit than one we currently have.
                        if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) {
                            continue;
                        }
                        update_feed_item($importer['channel_id'], $datarray);
                    }
                    continue;
                }
                $datarray['parent_mid'] = $parent_mid;
                $datarray['uid'] = $importer['channel_id'];
                logger('consume_feed: ' . print_r($datarray, true), LOGGER_DATA);
                $xx = item_store($datarray);
                $r = $xx['item_id'];
                continue;
            } else {
                // Head post of a conversation. Have we seen it? If not, import it.
                $item_id = base64url_encode($item->get_id());
                $author = array();
                $datarray = get_atom_elements($feed, $item, $author);
                if (is_array($contact)) {
                    if (!x($author, 'author_name') || $author['author_is_feed']) {
                        $author['author_name'] = $contact['xchan_name'];
                    }
                    if (!x($author, 'author_link') || $author['author_is_feed']) {
                        $author['author_link'] = $contact['xchan_url'];
                    }
                    if (!x($author, 'author_photo') || $author['author_is_feed']) {
                        $author['author_photo'] = $contact['xchan_photo_m'];
                    }
                }
                if (!x($author, 'author_name') || !x($author, 'author_link')) {
                    logger('consume_feed: no author information! ' . print_r($author, true));
                    continue;
                }
                $datarray['author_xchan'] = '';
                if ($author['author_link'] != $contact['xchan_url']) {
                    $x = import_author_unknown(array('name' => $author['author_name'], 'url' => $author['author_link'], 'photo' => array('src' => $author['author_photo'])));
                    if ($x) {
                        $datarray['author_xchan'] = $x;
                    }
                }
                if (!$datarray['author_xchan']) {
                    $datarray['author_xchan'] = $contact['xchan_hash'];
                }
                $datarray['owner_xchan'] = $contact['xchan_hash'];
                $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1", dbesc($item_id), intval($importer['channel_id']));
                // Update content if 'updated' changes
                if ($r) {
                    if (x($datarray, 'edited') !== false && datetime_convert('UTC', 'UTC', $datarray['edited']) !== $r[0]['edited']) {
                        // do not accept (ignore) an earlier edit than one we currently have.
                        if (datetime_convert('UTC', 'UTC', $datarray['edited']) < $r[0]['edited']) {
                            continue;
                        }
                        update_feed_item($importer['channel_id'], $datarray);
                    }
                    continue;
                }
                $datarray['parent_mid'] = $item_id;
                $datarray['uid'] = $importer['channel_id'];
                if (!link_compare($author['owner_link'], $contact['xchan_url'])) {
                    logger('consume_feed: Correcting item owner.', LOGGER_DEBUG);
                    $author['owner_name'] = $contact['name'];
                    $author['owner_link'] = $contact['url'];
                    $author['owner_avatar'] = $contact['thumb'];
                }
                logger('consume_feed: author ' . print_r($author, true), LOGGER_DEBUG);
                logger('consume_feed: ' . print_r($datarray, true), LOGGER_DATA);
                $xx = item_store($datarray);
                $r = $xx['item_id'];
                continue;
            }
        }
    }
}
Beispiel #20
0
 function import_account($account_id)
 {
     if (!$account_id) {
         logger("import_account: No account ID supplied");
         return;
     }
     $max_identities = account_service_class_fetch($account_id, 'total_identities');
     $max_friends = account_service_class_fetch($account_id, 'total_channels');
     $max_feeds = account_service_class_fetch($account_id, 'total_feeds');
     if ($max_identities !== false) {
         $r = q("select channel_id from channel where channel_account_id = %d", intval($account_id));
         if ($r && count($r) > $max_identities) {
             notice(sprintf(t('Your service plan only allows %d channels.'), $max_identities) . EOL);
             return;
         }
     }
     $data = null;
     $seize = x($_REQUEST, 'make_primary') ? intval($_REQUEST['make_primary']) : 0;
     $import_posts = x($_REQUEST, 'import_posts') ? intval($_REQUEST['import_posts']) : 0;
     $src = $_FILES['filename']['tmp_name'];
     $filename = basename($_FILES['filename']['name']);
     $filesize = intval($_FILES['filename']['size']);
     $filetype = $_FILES['filename']['type'];
     $completed = array_key_exists('import_step', $_SESSION) ? intval($_SESSION['import_step']) : 0;
     if ($completed) {
         logger('saved import step: ' . $_SESSION['import_step']);
     }
     if ($src) {
         // This is OS specific and could also fail if your tmpdir isn't very large
         // mostly used for Diaspora which exports gzipped files.
         if (strpos($filename, '.gz')) {
             @rename($src, $src . '.gz');
             @system('gunzip ' . escapeshellarg($src . '.gz'));
         }
         if ($filesize) {
             $data = @file_get_contents($src);
         }
         unlink($src);
     }
     if (!$src) {
         $old_address = x($_REQUEST, 'old_address') ? $_REQUEST['old_address'] : '';
         if (!$old_address) {
             logger('mod_import: nothing to import.');
             notice(t('Nothing to import.') . EOL);
             return;
         }
         $email = x($_REQUEST, 'email') ? $_REQUEST['email'] : '';
         $password = x($_REQUEST, 'password') ? $_REQUEST['password'] : '';
         $channelname = substr($old_address, 0, strpos($old_address, '@'));
         $servername = substr($old_address, strpos($old_address, '@') + 1);
         $scheme = 'https://';
         $api_path = '/api/red/channel/export/basic?f=&channel=' . $channelname;
         if ($import_posts) {
             $api_path .= '&posts=1';
         }
         $binary = false;
         $redirects = 0;
         $opts = array('http_auth' => $email . ':' . $password);
         $url = $scheme . $servername . $api_path;
         $ret = z_fetch_url($url, $binary, $redirects, $opts);
         if (!$ret['success']) {
             $ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts);
         }
         if ($ret['success']) {
             $data = $ret['body'];
         } else {
             notice(t('Unable to download data from old server') . EOL);
         }
     }
     if (!$data) {
         logger('mod_import: empty file.');
         notice(t('Imported file is empty.') . EOL);
         return;
     }
     $data = json_decode($data, true);
     //	logger('import: data: ' . print_r($data,true));
     //	print_r($data);
     if (array_key_exists('user', $data) && array_key_exists('version', $data)) {
         require_once 'include/Import/import_diaspora.php';
         import_diaspora($data);
         return;
     }
     $moving = false;
     if (array_key_exists('compatibility', $data) && array_key_exists('database', $data['compatibility'])) {
         $v1 = substr($data['compatibility']['database'], -4);
         $v2 = substr(DB_UPDATE_VERSION, -4);
         if ($v2 > $v1) {
             $t = sprintf(t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1);
             notice($t);
         }
         if (array_key_exists('server_role', $data['compatibility']) && $data['compatibility']['server_role'] == 'basic') {
             $moving = true;
         }
     }
     if ($moving) {
         $seize = 1;
     }
     // import channel
     $relocate = array_key_exists('relocate', $data) ? $data['relocate'] : null;
     if (array_key_exists('channel', $data)) {
         if ($completed < 1) {
             $channel = import_channel($data['channel'], $account_id, $seize);
         } else {
             $r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1", intval($account_id), dbesc($channel['channel_guid']));
             if ($r) {
                 $channel = $r[0];
             }
         }
         if (!$channel) {
             logger('mod_import: channel not found. ', print_r($channel, true));
             notice(t('Cloned channel not found. Import failed.') . EOL);
             return;
         }
     }
     if (!$channel) {
         $channel = \App::get_channel();
     }
     if (!$channel) {
         logger('mod_import: channel not found. ', print_r($channel, true));
         notice(t('No channel. Import failed.') . EOL);
         return;
     }
     if ($completed < 2) {
         if (is_array($data['config'])) {
             import_config($channel, $data['config']);
         }
         logger('import step 2');
         $_SESSION['import_step'] = 2;
     }
     if ($completed < 3) {
         if ($data['photo']) {
             require_once 'include/photo/photo_driver.php';
             import_channel_photo(base64url_decode($data['photo']['data']), $data['photo']['type'], $account_id, $channel['channel_id']);
         }
         if (is_array($data['profile'])) {
             import_profiles($channel, $data['profile']);
         }
         logger('import step 3');
         $_SESSION['import_step'] = 3;
     }
     if ($completed < 4) {
         if (is_array($data['hubloc']) && !$moving) {
             import_hublocs($channel, $data['hubloc'], $seize);
         }
         logger('import step 4');
         $_SESSION['import_step'] = 4;
     }
     if ($completed < 5) {
         // create new hubloc for the new channel at this site
         $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_network, hubloc_primary, \n\t\t\t\thubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey )\n\t\t\t\tvalues ( '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s' )", dbesc($channel['channel_guid']), dbesc($channel['channel_guid_sig']), dbesc($channel['channel_hash']), dbesc(channel_reddress($channel)), dbesc('zot'), intval($seize ? 1 : 0), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(), $channel['channel_prvkey']))), dbesc(\App::get_hostname()), dbesc(z_root() . '/post'), dbesc(get_config('system', 'pubkey')));
         // reset the original primary hubloc if it is being seized
         if ($seize) {
             $r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ", dbesc($channel['channel_hash']), dbesc(z_root()));
         }
         logger('import step 5');
         $_SESSION['import_step'] = 5;
     }
     if ($completed < 6) {
         // import xchans and contact photos
         if ($seize) {
             // replace any existing xchan we may have on this site if we're seizing control
             $r = q("delete from xchan where xchan_hash = '%s'", dbesc($channel['channel_hash']));
             $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_hidden, xchan_orphan, xchan_censored, xchan_selfcensored, xchan_system, xchan_pubforum, xchan_deleted ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, %d, %d, %d )", dbesc($channel['channel_hash']), dbesc($channel['channel_guid']), dbesc($channel['channel_guid_sig']), dbesc($channel['channel_pubkey']), dbesc(z_root() . "/photo/profile/l/" . $channel['channel_id']), dbesc(z_root() . "/photo/profile/m/" . $channel['channel_id']), dbesc(z_root() . "/photo/profile/s/" . $channel['channel_id']), dbesc(channel_reddress($channel)), dbesc(z_root() . '/channel/' . $channel['channel_address']), dbesc(z_root() . '/follow?f=&url=%s'), dbesc(z_root() . '/poco/' . $channel['channel_address']), dbesc($channel['channel_name']), dbesc('zot'), dbesc(datetime_convert()), dbesc(datetime_convert()), 0, 0, 0, 0, 0, 0, 0);
         }
         logger('import step 6');
         $_SESSION['import_step'] = 6;
     }
     if ($completed < 7) {
         $xchans = $data['xchan'];
         if ($xchans) {
             foreach ($xchans as $xchan) {
                 $hash = make_xchan_hash($xchan['xchan_guid'], $xchan['xchan_guid_sig']);
                 if ($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) {
                     logger('forged xchan: ' . print_r($xchan, true));
                     continue;
                 }
                 if (!array_key_exists('xchan_hidden', $xchan)) {
                     $xchan['xchan_hidden'] = $xchan['xchan_flags'] & 0x1 ? 1 : 0;
                     $xchan['xchan_orphan'] = $xchan['xchan_flags'] & 0x2 ? 1 : 0;
                     $xchan['xchan_censored'] = $xchan['xchan_flags'] & 0x4 ? 1 : 0;
                     $xchan['xchan_selfcensored'] = $xchan['xchan_flags'] & 0x8 ? 1 : 0;
                     $xchan['xchan_system'] = $xchan['xchan_flags'] & 0x10 ? 1 : 0;
                     $xchan['xchan_pubforum'] = $xchan['xchan_flags'] & 0x20 ? 1 : 0;
                     $xchan['xchan_deleted'] = $xchan['xchan_flags'] & 0x1000 ? 1 : 0;
                 }
                 $r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1", dbesc($xchan['xchan_hash']));
                 if ($r) {
                     continue;
                 }
                 dbesc_array($xchan);
                 $r = dbq("INSERT INTO xchan (`" . implode("`, `", array_keys($xchan)) . "`) VALUES ('" . implode("', '", array_values($xchan)) . "')");
                 require_once 'include/photo/photo_driver.php';
                 $photos = import_xchan_photo($xchan['xchan_photo_l'], $xchan['xchan_hash']);
                 if ($photos[4]) {
                     $photodate = NULL_DATE;
                 } else {
                     $photodate = $xchan['xchan_photo_date'];
                 }
                 $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s'\n\t\t\t\t\t\twhere xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($photodate), dbesc($xchan['xchan_hash']));
             }
         }
         logger('import step 7');
         $_SESSION['import_step'] = 7;
     }
     // FIXME - ensure we have an xchan if somebody is trying to pull a fast one
     if ($completed < 8) {
         $friends = 0;
         $feeds = 0;
         // import contacts
         $abooks = $data['abook'];
         if ($abooks) {
             foreach ($abooks as $abook) {
                 $abook_copy = $abook;
                 $abconfig = null;
                 if (array_key_exists('abconfig', $abook) && is_array($abook['abconfig']) && count($abook['abconfig'])) {
                     $abconfig = $abook['abconfig'];
                 }
                 unset($abook['abook_id']);
                 unset($abook['abook_rating']);
                 unset($abook['abook_rating_text']);
                 unset($abook['abconfig']);
                 unset($abook['abook_their_perms']);
                 unset($abook['abook_my_perms']);
                 $abook['abook_account'] = $account_id;
                 $abook['abook_channel'] = $channel['channel_id'];
                 if (!array_key_exists('abook_blocked', $abook)) {
                     $abook['abook_blocked'] = $abook['abook_flags'] & 0x1 ? 1 : 0;
                     $abook['abook_ignored'] = $abook['abook_flags'] & 0x2 ? 1 : 0;
                     $abook['abook_hidden'] = $abook['abook_flags'] & 0x4 ? 1 : 0;
                     $abook['abook_archived'] = $abook['abook_flags'] & 0x8 ? 1 : 0;
                     $abook['abook_pending'] = $abook['abook_flags'] & 0x10 ? 1 : 0;
                     $abook['abook_unconnected'] = $abook['abook_flags'] & 0x20 ? 1 : 0;
                     $abook['abook_self'] = $abook['abook_flags'] & 0x80 ? 1 : 0;
                     $abook['abook_feed'] = $abook['abook_flags'] & 0x100 ? 1 : 0;
                 }
                 if ($abook['abook_self']) {
                     $role = get_pconfig($channel['channel_id'], 'system', 'permissions_role');
                     if ($role === 'forum' || $abook['abook_my_perms'] & PERMS_W_TAGWALL) {
                         q("update xchan set xchan_pubforum = 1 where xchan_hash = '%s' ", dbesc($abook['abook_xchan']));
                     }
                 } else {
                     if ($max_friends !== false && $friends > $max_friends) {
                         continue;
                     }
                     if ($max_feeds !== false && intval($abook['abook_feed']) && $feeds > $max_feeds) {
                         continue;
                     }
                 }
                 dbesc_array($abook);
                 $r = dbq("INSERT INTO abook (`" . implode("`, `", array_keys($abook)) . "`) VALUES ('" . implode("', '", array_values($abook)) . "')");
                 $friends++;
                 if (intval($abook['abook_feed'])) {
                     $feeds++;
                 }
                 translate_abook_perms_inbound($channel, $abook_copy);
                 if ($abconfig) {
                     // @fixme does not handle sync of del_abconfig
                     foreach ($abconfig as $abc) {
                         set_abconfig($channel['channel_id'], $abc['xchan'], $abc['cat'], $abc['k'], $abc['v']);
                     }
                 }
             }
         }
         logger('import step 8');
         $_SESSION['import_step'] = 8;
     }
     if ($completed < 9) {
         $groups = $data['group'];
         if ($groups) {
             $saved = array();
             foreach ($groups as $group) {
                 $saved[$group['hash']] = array('old' => $group['id']);
                 if (array_key_exists('name', $group)) {
                     $group['gname'] = $group['name'];
                     unset($group['name']);
                 }
                 unset($group['id']);
                 $group['uid'] = $channel['channel_id'];
                 dbesc_array($group);
                 $r = dbq("INSERT INTO groups (`" . implode("`, `", array_keys($group)) . "`) VALUES ('" . implode("', '", array_values($group)) . "')");
             }
             $r = q("select * from `groups` where uid = %d", intval($channel['channel_id']));
             if ($r) {
                 foreach ($r as $rr) {
                     $saved[$rr['hash']]['new'] = $rr['id'];
                 }
             }
         }
         $group_members = $data['group_member'];
         if ($group_members) {
             foreach ($group_members as $group_member) {
                 unset($group_member['id']);
                 $group_member['uid'] = $channel['channel_id'];
                 foreach ($saved as $x) {
                     if ($x['old'] == $group_member['gid']) {
                         $group_member['gid'] = $x['new'];
                     }
                 }
                 dbesc_array($group_member);
                 $r = dbq("INSERT INTO group_member (`" . implode("`, `", array_keys($group_member)) . "`) VALUES ('" . implode("', '", array_values($group_member)) . "')");
             }
         }
         logger('import step 9');
         $_SESSION['import_step'] = 9;
     }
     if (is_array($data['obj'])) {
         import_objs($channel, $data['obj']);
     }
     if (is_array($data['likes'])) {
         import_likes($channel, $data['likes']);
     }
     if (is_array($data['app'])) {
         import_apps($channel, $data['app']);
     }
     if (is_array($data['chatroom'])) {
         import_chatrooms($channel, $data['chatroom']);
     }
     if (is_array($data['conv'])) {
         import_conv($channel, $data['conv']);
     }
     if (is_array($data['mail'])) {
         import_mail($channel, $data['mail']);
     }
     if (is_array($data['event'])) {
         import_events($channel, $data['event']);
     }
     if (is_array($data['event_item'])) {
         import_items($channel, $data['event_item'], false, $relocate);
     }
     if (is_array($data['menu'])) {
         import_menus($channel, $data['menu']);
     }
     $addon = array('channel' => $channel, 'data' => $data);
     call_hooks('import_channel', $addon);
     $saved_notification_flags = notifications_off($channel['channel_id']);
     if ($import_posts && array_key_exists('item', $data) && $data['item']) {
         import_items($channel, $data['item'], false, $relocate);
     }
     notifications_on($channel['channel_id'], $saved_notification_flags);
     if (array_key_exists('item_id', $data) && $data['item_id']) {
         import_item_ids($channel, $data['item_id']);
     }
     // FIXME - ensure we have a self entry if somebody is trying to pull a fast one
     // send out refresh requests
     // notify old server that it may no longer be primary.
     \Zotlabs\Daemon\Master::Summon(array('Notifier', 'location', $channel['channel_id']));
     // This will indirectly perform a refresh_all *and* update the directory
     \Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));
     notice(t('Import completed.') . EOL);
     change_channel($channel['channel_id']);
     unset($_SESSION['import_step']);
     goaway(z_root() . '/network');
 }
Beispiel #21
0
/**
 * @brief Create an array representing the important channel information
 * which would be necessary to create a nomadic identity clone. This includes
 * most channel resources and connection information with the exception of content.
 *
 * @param int $channel_id
 *     Channel_id to export
 * @param boolean $items
 *     Include channel posts (wall items), default false
 *
 * @returns array
 *     See function for details
 */
function identity_basic_export($channel_id, $items = false)
{
    /*
     * Red basic channel export
     */
    $ret = array();
    $ret['compatibility'] = array('project' => PLATFORM_NAME, 'version' => RED_VERSION, 'database' => DB_UPDATE_VERSION);
    $r = q("select * from channel where channel_id = %d limit 1", intval($channel_id));
    if ($r) {
        $ret['channel'] = $r[0];
    }
    $r = q("select * from profile where uid = %d", intval($channel_id));
    if ($r) {
        $ret['profile'] = $r;
    }
    $xchans = array();
    $r = q("select * from abook where abook_channel = %d ", intval($channel_id));
    if ($r) {
        $ret['abook'] = $r;
        foreach ($r as $rr) {
            $xchans[] = $rr['abook_xchan'];
        }
        stringify_array_elms($xchans);
    }
    if ($xchans) {
        $r = q("select * from xchan where xchan_hash in ( " . implode(',', $xchans) . " ) ");
        if ($r) {
            $ret['xchan'] = $r;
        }
        $r = q("select * from hubloc where hubloc_hash in ( " . implode(',', $xchans) . " ) ");
        if ($r) {
            $ret['hubloc'] = $r;
        }
    }
    $r = q("select * from `groups` where uid = %d ", intval($channel_id));
    if ($r) {
        $ret['group'] = $r;
    }
    $r = q("select * from group_member where uid = %d ", intval($channel_id));
    if ($r) {
        $ret['group_member'] = $r;
    }
    $r = q("select * from pconfig where uid = %d", intval($channel_id));
    if ($r) {
        $ret['config'] = $r;
    }
    $r = q("select type, data, os_storage from photo where scale = 4 and profile = 1 and uid = %d limit 1", intval($channel_id));
    if ($r) {
        $ret['photo'] = array('type' => $r[0]['type'], 'data' => $r[0]['os_storage'] ? base64url_encode(file_get_contents($r[0]['data'])) : base64url_encode($r[0]['data']));
    }
    // All other term types will be included in items, if requested.
    $r = q("select * from term where type in (%d,%d) and uid = %d", intval(TERM_SAVEDSEARCH), intval(TERM_THING), intval($channel_id));
    if ($r) {
        $ret['term'] = $r;
    }
    // add psuedo-column obj_baseurl to aid in relocations
    $r = q("select obj.*, '%s' as obj_baseurl from obj where obj_channel = %d", dbesc(z_root()), intval($channel_id));
    if ($r) {
        $ret['obj'] = $r;
    }
    $r = q("select * from app where app_channel = %d", intval($channel_id));
    if ($r) {
        $ret['app'] = $r;
    }
    $r = q("select * from chatroom where cr_uid = %d", intval($channel_id));
    if ($r) {
        $ret['chatroom'] = $r;
    }
    $r = q("select * from event where uid = %d", intval($channel_id));
    if ($r) {
        $ret['event'] = $r;
    }
    $r = q("select * from item where resource_type = 'event' and uid = %d", intval($channel_id));
    if ($r) {
        $ret['event_item'] = array();
        xchan_query($r);
        $r = fetch_post_tags($r, true);
        foreach ($r as $rr) {
            $ret['event_item'][] = encode_item($rr, true);
        }
    }
    $x = menu_list($channel_id);
    if ($x) {
        $ret['menu'] = array();
        for ($y = 0; $y < count($x); $y++) {
            $m = menu_fetch($x[$y]['menu_name'], $channel_id, $ret['channel']['channel_hash']);
            if ($m) {
                $ret['menu'][] = menu_element($m);
            }
        }
    }
    $x = menu_list($channel_id);
    if ($x) {
        $ret['menu'] = array();
        for ($y = 0; $y < count($x); $y++) {
            $m = menu_fetch($x[$y]['menu_name'], $channel_id, $ret['channel']['channel_hash']);
            if ($m) {
                $ret['menu'][] = menu_element($m);
            }
        }
    }
    $addon = array('channel_id' => $channel_id, 'data' => $ret);
    call_hooks('identity_basic_export', $addon);
    $ret = $addon['data'];
    if (!$items) {
        return $ret;
    }
    $r = q("select * from likes where channel_id = %d", intval($channel_id));
    if ($r) {
        $ret['likes'] = $r;
    }
    $r = q("select * from conv where uid = %d", intval($channel_id));
    if ($r) {
        for ($x = 0; $x < count($r); $x++) {
            $r[$x]['subject'] = base64url_decode(str_rot47($r[$x]['subject']));
        }
        $ret['conv'] = $r;
    }
    $r = q("select * from mail where mail.uid = %d", intval($channel_id));
    if ($r) {
        $m = array();
        foreach ($r as $rr) {
            xchan_mail_query($rr);
            $m[] = mail_encode($rr, true);
        }
        $ret['mail'] = $m;
    }
    $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d", intval($channel_id));
    if ($r) {
        $ret['item_id'] = $r;
    }
    //$key = get_config('system','prvkey');
    /** @warning this may run into memory limits on smaller systems */
    /** export three months of posts. If you want to export and import all posts you have to start with 
     * the first year and export/import them in ascending order. 
     *
     * Don't export linked resource items. we'll have to pull those out separately.
     */
    $r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d and created > %s - INTERVAL %s and resource_type = '' order by created", intval($channel_id), db_utcnow(), db_quoteinterval('3 MONTH'));
    if ($r) {
        $ret['item'] = array();
        xchan_query($r);
        $r = fetch_post_tags($r, true);
        foreach ($r as $rr) {
            $ret['item'][] = encode_item($rr, true);
        }
    }
    return $ret;
}
<?php

$paramString = base64url_encode(serialize($config));
$onclick = "javascript:org.Common.uploaddialog('{$config['id']}_dialog', '上传文件','{$config['id']}',{$config['callback']},'{$paramString}','{$authkey}', '{$config['uploadUrl']}')";
?>
<a class="btn btn-primary btn-sm" id="swf-upload-btn" style="font-size: 12px;" onclick="<?php 
echo $onclick;
?>
" >
  <i class="fa fa-upload"></i>
  上传
</a>
Beispiel #23
0
function send_message($uid = 0, $recipient = '', $body = '', $subject = '', $replyto = '', $expires = '')
{
    $ret = array('success' => false);
    $a = get_app();
    if (!$recipient) {
        $ret['message'] = t('No recipient provided.');
        return $ret;
    }
    if (!strlen($subject)) {
        $subject = t('[no subject]');
    }
    //	if(! $expires)
    //		$expires = NULL_DATE;
    //	else
    //		$expires = datetime_convert(date_default_timezone_get(),'UTC',$expires);
    if ($uid) {
        $r = q("select * from channel where channel_id = %d limit 1", intval($uid));
        if ($r) {
            $channel = $r[0];
        }
    } else {
        $channel = get_app()->get_channel();
    }
    if (!$channel) {
        $ret['message'] = t('Unable to determine sender.');
        return $ret;
    }
    // look for any existing conversation structure
    $conv_guid = '';
    if (strlen($replyto)) {
        $r = q("select conv_guid from mail where channel_id = %d and ( mid = '%s' or parent_mid = '%s' ) limit 1", intval(local_channel()), dbesc($replyto), dbesc($replyto));
        if ($r) {
            $conv_guid = $r[0]['conv_guid'];
        }
    }
    if (!$conv_guid) {
        // create a new conversation
        $conv_guid = random_string();
        $recip = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($recipient));
        if ($recip) {
            $recip_handle = $recip[0]['xchan_addr'];
        }
        $sender_handle = $channel['channel_address'] . '@' . get_app()->get_hostname();
        $handles = $recip_handle . ';' . $sender_handle;
        if ($subject) {
            $nsubject = str_rot47(base64url_encode($subject));
        }
        $r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ", intval(local_channel()), dbesc($conv_guid), dbesc($sender_handle), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($nsubject), dbesc($handles));
        $r = q("select * from conv where guid = '%s' and uid = %d limit 1", dbesc($conv_guid), intval(local_channel()));
        if ($r) {
            $retconv = $r[0];
            $retconv['subject'] = base64url_decode(str_rot47($retconv['subject']));
        }
    }
    if (!$retconv) {
        $r = q("select * from conv where guid = '%s' and uid = %d limit 1", dbesc($conv_guid), intval(local_channel()));
        if ($r) {
            $retconv = $r[0];
            $retconv['subject'] = base64url_decode(str_rot47($retconv['subject']));
        }
    }
    if (!$retconv) {
        $ret['message'] = 'conversation not found';
        return $ret;
    }
    // generate a unique message_id
    do {
        $dups = false;
        $hash = random_string();
        $mid = $hash . '@' . get_app()->get_hostname();
        $r = q("SELECT id FROM mail WHERE mid = '%s' LIMIT 1", dbesc($mid));
        if (count($r)) {
            $dups = true;
        }
    } while ($dups == true);
    if (!strlen($replyto)) {
        $replyto = $mid;
    }
    /**
     *
     * 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;
    $images = null;
    if (preg_match_all("/\\[zmg\\](.*?)\\[\\/zmg\\]/", strpos($body, '[/crypt]') ? $_POST['media_str'] : $body, $match)) {
        $images = $match[1];
    }
    $match = false;
    if (preg_match_all("/\\[attachment\\](.*?)\\[\\/attachment\\]/", strpos($body, '[/crypt]') ? $_POST['media_str'] : $body, $match)) {
        $attaches = $match[1];
    }
    $attachments = '';
    if (preg_match_all('/(\\[attachment\\](.*?)\\[\\/attachment\\])/', $body, $match)) {
        $attachments = array();
        foreach ($match[2] as $mtch) {
            $hash = substr($mtch, 0, strpos($mtch, ','));
            $rev = intval(substr($mtch, strpos($mtch, ',')));
            $r = attach_by_hash_nodata($hash, $rev);
            if ($r['success']) {
                $attachments[] = array('href' => $a->get_baseurl() . '/attach/' . $r['data']['hash'], 'length' => $r['data']['filesize'], 'type' => $r['data']['filetype'], 'title' => urlencode($r['data']['filename']), 'revision' => $r['data']['revision']);
            }
            $body = str_replace($match[1], '', $body);
        }
    }
    $jattach = $attachments ? json_encode($attachments) : '';
    if ($subject) {
        $subject = str_rot47(base64url_encode($subject));
    }
    if ($body) {
        $body = str_rot47(base64url_encode($body));
    }
    $r = q("INSERT INTO mail ( account_id, conv_guid, mail_obscured, channel_id, from_xchan, to_xchan, title, body, attach, mid, parent_mid, created, expires )\n\t\tVALUES ( %d, '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )", intval($channel['channel_account_id']), dbesc($conv_guid), intval(1), intval($channel['channel_id']), dbesc($channel['channel_hash']), dbesc($recipient), dbesc($subject), dbesc($body), dbesc($jattach), dbesc($mid), dbesc($replyto), dbesc(datetime_convert()), dbescdate($expires));
    // verify the save
    $r = q("SELECT * FROM mail WHERE mid = '%s' and channel_id = %d LIMIT 1", dbesc($mid), intval($channel['channel_id']));
    if ($r) {
        $post_id = $r[0]['id'];
        $retmail = $r[0];
        xchan_mail_query($retmail);
    } else {
        $ret['message'] = t('Stored post could not be verified.');
        return $ret;
    }
    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, '-'));
            $r = q("UPDATE photo SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d and allow_cid = '%s'", dbesc('<' . $recipient . '>'), dbesc($image_uri), intval($channel['channel_id']), dbesc('<' . $channel['channel_hash'] . '>'));
            $r = q("UPDATE attach SET allow_cid = '%s' WHERE hash = '%s' AND is_photo = 1 and uid = %d and allow_cid = '%s'", dbesc('<' . $recipient . '>'), dbesc($image_uri), intval($channel['channel_id']), dbesc('<' . $channel['channel_hash'] . '>'));
        }
    }
    if ($attaches) {
        foreach ($attaches as $attach) {
            $hash = substr($attach, 0, strpos($attach, ','));
            $rev = intval(substr($attach, strpos($attach, ',')));
            attach_store($channel, $observer_hash, $options = 'update', array('hash' => $hash, 'revision' => $rev, 'allow_cid' => '<' . $recipient . '>'));
        }
    }
    proc_run('php', 'include/notifier.php', 'mail', $post_id);
    $ret['success'] = true;
    $ret['message_item'] = intval($post_id);
    $ret['conv'] = $retconv;
    $ret['mail'] = $retmail;
    return $ret;
}
Beispiel #24
0
function oembed_iframe($src, $width, $height)
{
    if (!$width || strstr($width, '%')) {
        $width = '640';
    }
    if (!$height || strstr($height, '%')) {
        $height = '300';
        $resize = 'onload="resizeIframe(this);"';
    } else {
        $resize = '';
    }
    // try and leave some room for the description line.
    $height = intval($height) + 80;
    $width = intval($width) + 40;
    $a = get_app();
    $s = $a->get_baseurl() . "/oembed/" . base64url_encode($src);
    return '<iframe ' . $resize . ' class="embed_rich" height="' . $height . '" width="' . $width . '" src="' . $s . '" frameborder="no">' . t('Embedded content') . '</iframe>';
}
function send_response($username, $authorize = false)
{
    $GET = $_SESSION['get'];
    $rpfA = $_SESSION['rpfA'];
    $rpep = $GET['redirect_uri'];
    $state = isset($GET['state']) ? $GET['state'] : NULL;
    $error_page = isset($GET['redirect_uri']) ? $GET['redirect_uri'] : OP_INDEX_PAGE;
    $response_mode = get_response_mode($GET);
    try {
        $client_id = $GET['client_id'];
        $response_types = explode(' ', $GET['response_type']);
        $scopes = explode(' ', $GET['scope']);
        $prompts = explode(' ', $GET['prompt']);
        $is_code_flow = in_array('code', $response_types);
        $is_token_flow = in_array('token', $response_types);
        $is_id_token = in_array('id_token', $response_types);
        $offline_access = $is_code_flow && !$is_token_flow && in_array('consent', $prompts) && in_array('offline_access', $scopes);
        $issue_at = strftime('%G-%m-%d %T');
        $expiration_at = strftime('%G-%m-%d %T', time() + 2 * 60);
        $response_params = array();
        if (!$authorize) {
            throw new OidcException('access_denied', 'User denied access');
        }
        $rpfA['session_id'] = session_id();
        $rpfA['auth_time'] = $_SESSION['auth_time'];
        $confirmed_attribute_list = get_all_requested_claims($rpfA, $GET['scope']);
        if ($is_code_flow) {
            $code_info = create_token_info($username, $confirmed_attribute_list, $GET, $rpfA);
            $code = $code_info['name'];
            unset($code_info['name']);
            $fields = array('client' => $GET['client_id'], 'issued_at' => $issue_at, 'expiration_at' => $expiration_at, 'token' => $code, 'details' => '', 'token_type' => TOKEN_TYPE_AUTH_CODE, 'info' => json_encode($code_info));
            db_save_user_token($username, $code, $fields);
        }
        if ($is_token_flow) {
            $code_info = create_token_info($username, $confirmed_attribute_list, $GET, $rpfA);
            $token = $code_info['name'];
            unset($code_info['name']);
            $issue_at = strftime('%G-%m-%d %T');
            $expiration_at = strftime('%G-%m-%d %T', time() + 2 * 60);
            $fields = array('client' => $GET['client_id'], 'issued_at' => $issue_at, 'expiration_at' => $expiration_at, 'token' => $token, 'details' => '', 'token_type' => TOKEN_TYPE_ACCESS, 'info' => json_encode($code_info));
            db_save_user_token($username, $token, $fields);
        }
        if ($offline_access) {
            while (true) {
                $refresh_token_name = base64url_encode(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
                if (!db_find_token($refresh_token_name)) {
                    break;
                }
            }
            $fields = array('client' => $GET['client_id'], 'issued_at' => $issue_at, 'expiration_at' => $expiration_at, 'token' => $refresh_token_name, 'details' => '', 'token_type' => TOKEN_TYPE_REFRESH, 'info' => json_encode($code_info));
            $fields['expiration_at'] = strftime('%G-%m-%d %T', time() + 24 * 60 * 60);
            db_save_user_token($username, $refresh_token_name, $fields);
        }
        // Handle response_type for code or token
        if (isset($GET['state'])) {
            $response_params['state'] = $GET['state'];
        }
        if ($is_token_flow || $is_id_token) {
            if (isset($token)) {
                $response_params['access_token'] = $token;
                $response_params['token_type'] = 'Bearer';
                if ($offline_access) {
                    $response_params['refresh_token'] = $refresh_token_name;
                }
                $response_params['expires_in'] = '3600';
            }
        }
        if ($is_id_token) {
            $client_secret = null;
            $nonce = isset($GET['nonce']) ? $GET['nonce'] : null;
            $c_hash = null;
            $at_hash = null;
            $ops = null;
            $auth_time = null;
            $acr = null;
            $idt_claims = array();
            $sig = null;
            $alg = null;
            $enc = null;
            $client_secret = null;
            $jwk_uri = null;
            $db_client = db_get_client($client_id);
            if ($db_client) {
                $sig = $db_client['id_token_signed_response_alg'];
                if (!isset($sig)) {
                    $sig = 'RS256';
                }
                $alg = $db_client['id_token_encrypted_response_alg'];
                $enc = $db_client['id_token_encrypted_response_enc'];
                $client_secret = $db_client['client_secret'];
                $jwk_uri = $db_client['jwks_uri'];
                $jwks = $db_client['jwks'];
            }
            if (isset($rpfA['claims']) && isset($rpfA['claims']['id_token'])) {
                if (array_key_exists('auth_time', $rpfA['claims']['id_token'])) {
                    $auth_time = (int) $_SESSION['auth_time'];
                }
                if (array_key_exists('acr', $rpfA['claims']['id_token'])) {
                    if (array_key_exists('values', $rpfA['claims']['id_token']['acr'])) {
                        if (is_array($rpfA['claims']['id_token']['acr']['values']) && count($rpfA['claims']['id_token']['acr']['values'])) {
                            $acr = $rpfA['claims']['id_token']['acr']['values'][0];
                        }
                    } else {
                        $acr = '0';
                    }
                }
            }
            if ($sig) {
                $bit_length = substr($sig, 2);
                switch ($bit_length) {
                    case '384':
                        $hash_alg = 'sha384';
                        break;
                    case '512':
                        $hash_alg = 'sha512';
                        break;
                    case '256':
                    default:
                        $hash_alg = 'sha256';
                        break;
                }
                $hash_length = (int) ((int) $bit_length / 2) / 8;
                if ($code) {
                    $c_hash = base64url_encode(substr(hash($hash_alg, $code, true), 0, $hash_length));
                }
                if ($token) {
                    $at_hash = base64url_encode(substr(hash($hash_alg, $token, true), 0, $hash_length));
                }
            }
            $requested_id_token_claims = get_id_token_claims($rpfA);
            if ($requested_id_token_claims) {
                $db_user = db_get_user($username);
                if ($db_user) {
                    $idt_claims = get_account_claims($db_user, $requested_id_token_claims);
                } else {
                    throw new OidcException('access_denied', 'no such user');
                }
            }
            $id_token_obj = make_id_token(wrap_userid($db_client, $username), SERVER_ID, $client_id, $idt_claims, $nonce, $c_hash, $at_hash, $auth_time, $ops, $acr);
            log_debug('sen_response id_token_obj = %s', print_r($id_token_obj, true));
            $cryptoError = null;
            $id_token = sign_encrypt($id_token_obj, $sig, $alg, $enc, $jwk_uri, $jwks, $client_secret, $cryptoError);
            if (!$id_token) {
                log_error("Unable to sign encrypt response for ID Token %s", $cryptoError);
                throw new OidcException('invalid_request', "idtoken crypto error {$cryptoError}");
            }
            $response_params['id_token'] = $id_token;
        }
        $url_parts = parse_url($rpep);
        $origin = sprintf("%s://%s%s", $url_parts['scheme'], $url_parts['host'], isset($url_parts['port']) ? ':' . $url_parts['port'] : '');
        $salt = bin2hex(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM));
        log_debug("ss = sha256(%s%s%s%s).%s", $client_id, $origin, $_SESSION['ops'], $salt, $salt);
        $session_state = hash('sha256', "{$client_id}{$origin}{$_SESSION['ops']}{$salt}") . '.' . $salt;
        $response_params['session_state'] = $session_state;
        if ($is_code_flow) {
            $response_params['code'] = $code;
        }
        if ($_SESSION['persist'] == 'on') {
            $username = $_SESSION['username'];
            $auth_time = $_SESSION['auth_time'];
            $ops = $_SESSION['ops'];
            $login = $_SESSION['login'];
            clean_session();
            $_SESSION['lastlogin'] = time();
            $_SESSION['username'] = $username;
            $_SESSION['auth_time'] = $auth_time;
            $_SESSION['ops'] = $ops;
            $_SESSION['login'] = $login;
            $_SESSION['persist'] = 'on';
        } else {
            session_destroy();
        }
        send_auth_response($rpep, $response_params, $response_mode);
    } catch (OidcException $e) {
        log_error("handle_auth exception : %s", $e->getTraceAsString());
        send_error($error_page, $e->error_code, $e->desc, NULL, $state, $response_mode);
    } catch (Exception $e) {
        log_error("handle_auth exception : %s", $e->getTraceAsString());
        send_error($error_page, 'invalid_request', $e->getMessage(), NULL, $state, $response_mode);
    }
}
Beispiel #26
0
/**
 *
 * diaspora_decode($importer,$xml)
 *   array $importer -> from user table
 *   string $xml -> urldecoded Diaspora salmon 
 *
 * Returns array
 * 'message' -> decoded Diaspora XML message
 * 'author' -> author diaspora handle
 * 'key' -> author public key (converted to pkcs#8)
 *
 * Author and key are used elsewhere to save a lookup for verifying replies and likes
 */
function diaspora_decode($importer, $xml)
{
    $public = false;
    $basedom = parse_xml_string($xml);
    $children = $basedom->children('https://joindiaspora.com/protocol');
    if ($children->header) {
        $public = true;
        $author_link = str_replace('acct:', '', $children->header->author_id);
    } else {
        $encrypted_header = json_decode(base64_decode($children->encrypted_header));
        $encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key);
        $ciphertext = base64_decode($encrypted_header->ciphertext);
        $outer_key_bundle = '';
        openssl_private_decrypt($encrypted_aes_key_bundle, $outer_key_bundle, $importer['prvkey']);
        $j_outer_key_bundle = json_decode($outer_key_bundle);
        $outer_iv = base64_decode($j_outer_key_bundle->iv);
        $outer_key = base64_decode($j_outer_key_bundle->key);
        $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv);
        $decrypted = pkcs5_unpad($decrypted);
        /**
         * $decrypted now contains something like
         *
         *  <decrypted_header>
         *     <iv>8e+G2+ET8l5BPuW0sVTnQw==</iv>
         *     <aes_key>UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU=</aes_key>
         ***** OBSOLETE
         *     <author>
         *       <name>Ryan Hughes</name>
         *       <uri>acct:galaxor@diaspora.pirateship.org</uri>
         *     </author>
         ***** CURRENT
         *     <author_id>galaxor@diaspora.priateship.org</author_id>
         ***** END DIFFS
         *  </decrypted_header>
         */
        logger('decrypted: ' . $decrypted, LOGGER_DEBUG);
        $idom = parse_xml_string($decrypted, false);
        $inner_iv = base64_decode($idom->iv);
        $inner_aes_key = base64_decode($idom->aes_key);
        $author_link = str_replace('acct:', '', $idom->author_id);
    }
    $dom = $basedom->children(NAMESPACE_SALMON_ME);
    // figure out where in the DOM tree our data is hiding
    if ($dom->provenance->data) {
        $base = $dom->provenance;
    } elseif ($dom->env->data) {
        $base = $dom->env;
    } elseif ($dom->data) {
        $base = $dom;
    }
    if (!$base) {
        logger('mod-diaspora: unable to locate salmon data in xml ');
        http_status_exit(400);
    }
    // Stash the signature away for now. We have to find their key or it won't be good for anything.
    $signature = base64url_decode($base->sig);
    // unpack the  data
    // strip whitespace so our data element will return to one big base64 blob
    $data = str_replace(array(" ", "\t", "\r", "\n"), array("", "", "", ""), $base->data);
    // stash away some other stuff for later
    $type = $base->data[0]->attributes()->type[0];
    $keyhash = $base->sig[0]->attributes()->keyhash[0];
    $encoding = $base->encoding;
    $alg = $base->alg;
    $signed_data = $data . '.' . base64url_encode($type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($alg);
    // decode the data
    $data = base64url_decode($data);
    if ($public) {
        $inner_decrypted = $data;
    } else {
        // Decode the encrypted blob
        $inner_encrypted = base64_decode($data);
        $inner_decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $inner_encrypted, MCRYPT_MODE_CBC, $inner_iv);
        $inner_decrypted = pkcs5_unpad($inner_decrypted);
    }
    if (!$author_link) {
        logger('mod-diaspora: Could not retrieve author URI.');
        http_status_exit(400);
    }
    // Once we have the author URI, go to the web and try to find their public key
    // (first this will look it up locally if it is in the fcontact cache)
    // This will also convert diaspora public key from pkcs#1 to pkcs#8
    logger('mod-diaspora: Fetching key for ' . $author_link);
    $key = get_diaspora_key($author_link);
    if (!$key) {
        logger('mod-diaspora: Could not retrieve author key.');
        http_status_exit(400);
    }
    $verify = rsa_verify($signed_data, $signature, $key);
    if (!$verify) {
        logger('mod-diaspora: Message did not verify. Discarding.');
        http_status_exit(400);
    }
    logger('mod-diaspora: Message verified.');
    return array('message' => $inner_decrypted, 'author' => $author_link, 'key' => $key);
}
Beispiel #27
0
function randpost_fetch(&$a, &$b)
{
    $fort_server = get_config('fortunate', 'server');
    if (!$fort_server) {
        return;
    }
    $r = q("select * from pconfig where cat = 'randpost' and k = 'enable'");
    if ($r) {
        foreach ($r as $rr) {
            if (!$rr['v']) {
                continue;
            }
            //			logger('randpost');
            // cronhooks run every 10-15 minutes typically
            // try to keep from posting frequently.
            $test = mt_rand(0, 100);
            if ($test == 25) {
                $c = q("select * from channel where channel_id = %d limit 1", intval($rr['uid']));
                if (!$c) {
                    continue;
                }
                $mention = '';
                require_once 'include/html2bbcode.php';
                $s = z_fetch_url('http://' . $fort_server . '/cookie.php?numlines=2&equal=1&rand=' . mt_rand());
                if (!$s['success']) {
                    continue;
                }
                $x = array();
                $x['uid'] = $c[0]['channel_id'];
                $x['aid'] = $c[0]['channel_account_id'];
                $x['mid'] = $x['parent_mid'] = item_message_id();
                $x['author_xchan'] = $x['owner_xchan'] = $c[0]['channel_hash'];
                $x['item_thread_top'] = 1;
                $x['item_origin'] = 1;
                $x['item_verified'] = 1;
                $x['item_wall'] = 1;
                // if it might be a quote make it a quote
                if (strpos($s['body'], '--')) {
                    $x['body'] = $mention . '[quote]' . html2bbcode($s['body']) . '[/quote]';
                } else {
                    $x['body'] = $mention . html2bbcode($s['body']);
                }
                $x['sig'] = base64url_encode(rsa_sign($x['body'], $c[0]['channel_prvkey']));
                $post = item_store($x);
                $post_id = $post['item_id'];
                $x['id'] = $post_id;
                call_hooks('post_local_end', $x);
                Zotlabs\Daemon\Master::Summon(array('Notifier', 'wall-new', $post_id));
            }
        }
    }
}
Beispiel #28
0
function zfinger_init(&$a)
{
    require_once 'include/zot.php';
    require_once 'include/crypto.php';
    $ret = array('success' => false);
    $zhash = x($_REQUEST, 'guid_hash') ? $_REQUEST['guid_hash'] : '';
    $zguid = x($_REQUEST, 'guid') ? $_REQUEST['guid'] : '';
    $zguid_sig = x($_REQUEST, 'guid_sig') ? $_REQUEST['guid_sig'] : '';
    $zaddr = x($_REQUEST, 'address') ? $_REQUEST['address'] : '';
    $ztarget = x($_REQUEST, 'target') ? $_REQUEST['target'] : '';
    $zsig = x($_REQUEST, 'target_sig') ? $_REQUEST['target_sig'] : '';
    $zkey = x($_REQUEST, 'key') ? $_REQUEST['key'] : '';
    $mindate = x($_REQUEST, 'mindate') ? $_REQUEST['mindate'] : '';
    $feed = x($_REQUEST, 'feed') ? intval($_REQUEST['feed']) : 0;
    if ($ztarget) {
        if (!$zkey || !$zsig || !rsa_verify($ztarget, base64url_decode($zsig), $zkey)) {
            logger('zfinger: invalid target signature');
            $ret['message'] = t("invalid target signature");
            json_return_and_die($ret);
        }
    }
    // allow re-written domains so bob@foo.example.com can provide an address of bob@example.com
    // The top-level domain also needs to redirect .well-known/zot-info to the sub-domain with a 301 or 308
    // TODO: Make 308 work in include/network.php for zot_fetch_url and zot_post_url
    if ($zaddr && ($s = get_config('system', 'zotinfo_domainrewrite'))) {
        $arr = explode('^', $s);
        if (count($arr) == 2) {
            $zaddr = str_replace($arr[0], $arr[1], $zaddr);
        }
    }
    $r = null;
    if (strlen($zhash)) {
        $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash \n\t\t\twhere channel_hash = '%s' limit 1", dbesc($zhash));
    } elseif (strlen($zguid) && strlen($zguid_sig)) {
        $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash \n\t\t\twhere channel_guid = '%s' and channel_guid_sig = '%s' limit 1", dbesc($zguid), dbesc($zguid_sig));
    } elseif (strlen($zaddr)) {
        if (strpos($zaddr, '[system]') === false) {
            /* normal address lookup */
            $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash\n\t\t\t\twhere ( channel_address = '%s' or xchan_addr = '%s' ) limit 1", dbesc($zaddr), dbesc($zaddr));
        } else {
            /**
             * The special address '[system]' will return a system channel if one has been defined,
             * Or the first valid channel we find if there are no system channels. 
             *
             * This is used by magic-auth if we have no prior communications with this site - and
             * returns an identity on this site which we can use to create a valid hub record so that
             * we can exchange signed messages. The precise identity is irrelevant. It's the hub
             * information that we really need at the other end - and this will return it.
             *
             */
            $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash\n\t\t\t\twhere ( channel_pageflags & %d )>0 order by channel_id limit 1", intval(PAGE_SYSTEM));
            if (!$r) {
                $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash\n\t\t\t\t\twhere not ( channel_pageflags & %d )>0 order by channel_id limit 1", intval(PAGE_REMOVED));
            }
        }
    } else {
        $ret['message'] = 'Invalid request';
        json_return_and_die($ret);
    }
    if (!$r) {
        $ret['message'] = 'Item not found.';
        json_return_and_die($ret);
    }
    $e = $r[0];
    $id = $e['channel_id'];
    $sys_channel = $e['channel_pageflags'] & PAGE_SYSTEM ? true : false;
    $special_channel = $e['channel_pageflags'] & PAGE_PREMIUM ? true : false;
    $adult_channel = $e['channel_pageflags'] & PAGE_ADULT ? true : false;
    $censored = $e['channel_pageflags'] & PAGE_CENSORED ? true : false;
    $searchable = $e['channel_pageflags'] & PAGE_HIDDEN ? false : true;
    $deleted = $e['xchan_flags'] & XCHAN_FLAGS_DELETED ? true : false;
    if ($deleted || $censored || $sys_channel) {
        $searchable = false;
    }
    $public_forum = false;
    $role = get_pconfig($e['channel_id'], 'system', 'permissions_role');
    if ($role === 'forum') {
        $public_forum = true;
    } else {
        // check if it has characteristics of a public forum based on custom permissions.
        $t = q("select abook_my_perms from abook where abook_channel = %d and (abook_flags & %d)>0 limit 1", intval($e['channel_id']), intval(ABOOK_FLAG_SELF));
        if ($t && $t[0]['abook_my_perms'] & PERMS_W_TAGWALL) {
            $public_forum = true;
        }
    }
    //  This is for birthdays and keywords, but must check access permissions
    $p = q("select * from profile where uid = %d and is_default = 1", intval($e['channel_id']));
    $profile = array();
    if ($p) {
        if (!intval($p[0]['publish'])) {
            $searchable = false;
        }
        $profile['description'] = $p[0]['pdesc'];
        $profile['birthday'] = $p[0]['dob'];
        if ($profile['birthday'] != '0000-00-00' && ($bd = z_birthday($p[0]['dob'], $e['channel_timezone'])) !== '') {
            $profile['next_birthday'] = $bd;
        }
        if ($age = age($p[0]['dob'], $e['channel_timezone'], '')) {
            $profile['age'] = $age;
        }
        $profile['gender'] = $p[0]['gender'];
        $profile['marital'] = $p[0]['marital'];
        $profile['sexual'] = $p[0]['sexual'];
        $profile['locale'] = $p[0]['locality'];
        $profile['region'] = $p[0]['region'];
        $profile['postcode'] = $p[0]['postal_code'];
        $profile['country'] = $p[0]['country_name'];
        $profile['about'] = $p[0]['about'];
        $profile['homepage'] = $p[0]['homepage'];
        $profile['hometown'] = $p[0]['hometown'];
        if ($p[0]['keywords']) {
            $tags = array();
            $k = explode(' ', $p[0]['keywords']);
            if ($k) {
                foreach ($k as $kk) {
                    if (trim($kk, " \t\n\r\v,")) {
                        $tags[] = trim($kk, " \t\n\r\v,");
                    }
                }
            }
            if ($tags) {
                $profile['keywords'] = $tags;
            }
        }
    }
    $ret['success'] = true;
    // Communication details
    $ret['guid'] = $e['xchan_guid'];
    $ret['guid_sig'] = $e['xchan_guid_sig'];
    $ret['key'] = $e['xchan_pubkey'];
    $ret['name'] = $e['xchan_name'];
    $ret['name_updated'] = $e['xchan_name_date'];
    $ret['address'] = $e['xchan_addr'];
    $ret['photo_mimetype'] = $e['xchan_photo_mimetype'];
    $ret['photo'] = $e['xchan_photo_l'];
    $ret['photo_updated'] = $e['xchan_photo_date'];
    $ret['url'] = $e['xchan_url'];
    $ret['connections_url'] = $e['xchan_connurl'] ? $e['xchan_connurl'] : z_root() . '/poco/' . $e['channel_address'];
    $ret['target'] = $ztarget;
    $ret['target_sig'] = $zsig;
    $ret['searchable'] = $searchable;
    $ret['adult_content'] = $adult_channel;
    $ret['public_forum'] = $public_forum;
    if ($deleted) {
        $ret['deleted'] = $deleted;
    }
    // premium or other channel desiring some contact with potential followers before connecting.
    // This is a template - %s will be replaced with the follow_url we discover for the return channel.
    if ($special_channel) {
        $ret['connect_url'] = z_root() . '/connect/' . $e['channel_address'];
    }
    // This is a template for our follow url, %s will be replaced with a webbie
    $ret['follow_url'] = z_root() . '/follow?f=&url=%s';
    $ztarget_hash = $ztarget && $zsig ? make_xchan_hash($ztarget, $zsig) : '';
    $permissions = get_all_perms($e['channel_id'], $ztarget_hash, false);
    if ($ztarget_hash) {
        $permissions['connected'] = false;
        $b = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc($ztarget_hash), intval($e['channel_id']));
        if ($b) {
            $permissions['connected'] = true;
        }
    }
    $ret['permissions'] = $ztarget && $zkey ? crypto_encapsulate(json_encode($permissions), $zkey) : $permissions;
    if ($permissions['view_profile']) {
        $ret['profile'] = $profile;
    }
    // array of (verified) hubs this channel uses
    $x = zot_encode_locations($e);
    if ($x) {
        $ret['locations'] = $x;
    }
    $ret['site'] = array();
    $ret['site']['url'] = z_root();
    $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(), $e['channel_prvkey']));
    $dirmode = get_config('system', 'directory_mode');
    if ($dirmode === false || $dirmode == DIRECTORY_MODE_NORMAL) {
        $ret['site']['directory_mode'] = 'normal';
    }
    if ($dirmode == DIRECTORY_MODE_PRIMARY) {
        $ret['site']['directory_mode'] = 'primary';
    } elseif ($dirmode == DIRECTORY_MODE_SECONDARY) {
        $ret['site']['directory_mode'] = 'secondary';
    } elseif ($dirmode == DIRECTORY_MODE_STANDALONE) {
        $ret['site']['directory_mode'] = 'standalone';
    }
    if ($dirmode != DIRECTORY_MODE_NORMAL) {
        $ret['site']['directory_url'] = z_root() . '/dirsearch';
    }
    // hide detailed site information if you're off the grid
    if ($dirmode != DIRECTORY_MODE_STANDALONE) {
        $register_policy = intval(get_config('system', 'register_policy'));
        if ($register_policy == REGISTER_CLOSED) {
            $ret['site']['register_policy'] = 'closed';
        }
        if ($register_policy == REGISTER_APPROVE) {
            $ret['site']['register_policy'] = 'approve';
        }
        if ($register_policy == REGISTER_OPEN) {
            $ret['site']['register_policy'] = 'open';
        }
        $access_policy = intval(get_config('system', 'access_policy'));
        if ($access_policy == ACCESS_PRIVATE) {
            $ret['site']['access_policy'] = 'private';
        }
        if ($access_policy == ACCESS_PAID) {
            $ret['site']['access_policy'] = 'paid';
        }
        if ($access_policy == ACCESS_FREE) {
            $ret['site']['access_policy'] = 'free';
        }
        if ($access_policy == ACCESS_TIERED) {
            $ret['site']['access_policy'] = 'tiered';
        }
        $ret['site']['accounts'] = account_total();
        require_once 'include/identity.php';
        $ret['site']['channels'] = channel_total();
        $ret['site']['version'] = PLATFORM_NAME . ' ' . RED_VERSION . '[' . DB_UPDATE_VERSION . ']';
        $ret['site']['admin'] = get_config('system', 'admin_email');
        $visible_plugins = array();
        if (is_array($a->plugins) && count($a->plugins)) {
            $r = q("select * from addon where hidden = 0");
            if ($r) {
                foreach ($r as $rr) {
                    $visible_plugins[] = $rr['name'];
                }
            }
        }
        $ret['site']['plugins'] = $visible_plugins;
        $ret['site']['sitehash'] = get_config('system', 'location_hash');
        $ret['site']['sitename'] = get_config('system', 'sitename');
        $ret['site']['sellpage'] = get_config('system', 'sellpage');
        $ret['site']['location'] = get_config('system', 'site_location');
        $ret['site']['realm'] = get_directory_realm();
    }
    call_hooks('zot_finger', $ret);
    json_return_and_die($ret);
}
Beispiel #29
0
function slapper($owner, $url, $slap)
{
    // does contact have a salmon endpoint?
    if (!strlen($url)) {
        return;
    }
    if (!$owner['channel_prvkey']) {
        logger(sprintf("channel '%s' (%d) does not have a salmon private key. Send failed.", $owner['channel_address'], $owner['channel_id']));
        return;
    }
    logger('slapper called for ' . $url . '. Data: ' . $slap, LOGGER_DATA, LOG_DEBUG);
    // create a magic envelope
    $data = base64url_encode($slap, false);
    // do not strip padding
    $data_type = 'application/atom+xml';
    $encoding = 'base64url';
    $algorithm = 'RSA-SHA256';
    $keyhash = base64url_encode(hash('sha256', salmon_key($owner['channel_pubkey'])), true);
    $data = str_replace(array(" ", "\t", "\r", "\n"), array("", "", "", ""), $data);
    // precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
    $precomputed = '.YXBwbGljYXRpb24vYXRvbSt4bWw=.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
    $signature = base64url_encode(rsa_sign($data . $precomputed, $owner['channel_prvkey']));
    $salmon_tpl = get_markup_template('magicsig.tpl', 'addon/gnusoc/');
    $salmon = replace_macros($salmon_tpl, array('$data' => $data, '$encoding' => $encoding, '$algorithm' => $algorithm, '$keyhash' => $keyhash, '$signature' => $signature));
    logger('salmon: ' . $salmon, LOGGER_DATA);
    $hash = random_string();
    queue_insert(array('hash' => $hash, 'account_id' => $owner['channel_account_id'], 'channel_id' => $owner['channel_id'], 'driver' => 'slap', 'posturl' => $url, 'notify' => '', 'msg' => $salmon));
    return $hash;
}
Beispiel #30
0
function item_post(&$a)
{
    // This will change. Figure out who the observer is and whether or not
    // they have permission to post here. Else ignore the post.
    if (!local_channel() && !remote_channel() && !x($_REQUEST, 'commenter')) {
        return;
    }
    require_once 'include/security.php';
    $uid = local_channel();
    $channel = null;
    $observer = null;
    /**
     * Is this a reply to something?
     */
    $parent = x($_REQUEST, 'parent') ? intval($_REQUEST['parent']) : 0;
    $parent_mid = x($_REQUEST, 'parent_mid') ? trim($_REQUEST['parent_mid']) : '';
    $remote_xchan = x($_REQUEST, 'remote_xchan') ? trim($_REQUEST['remote_xchan']) : false;
    $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($remote_xchan));
    if ($r) {
        $remote_observer = $r[0];
    } else {
        $remote_xchan = $remote_observer = false;
    }
    $profile_uid = x($_REQUEST, 'profile_uid') ? intval($_REQUEST['profile_uid']) : 0;
    require_once 'include/identity.php';
    $sys = get_sys_channel();
    if ($sys && $profile_uid && $sys['channel_id'] == $profile_uid && is_site_admin()) {
        $uid = intval($sys['channel_id']);
        $channel = $sys;
        $observer = $sys;
    }
    if (x($_REQUEST, 'dropitems')) {
        require_once 'include/items.php';
        $arr_drop = explode(',', $_REQUEST['dropitems']);
        drop_items($arr_drop);
        $json = array('success' => 1);
        echo json_encode($json);
        killme();
    }
    call_hooks('post_local_start', $_REQUEST);
    //	 logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
    $api_source = x($_REQUEST, 'api_source') && $_REQUEST['api_source'] ? true : false;
    $consensus = intval($_REQUEST['consensus']);
    // 'origin' (if non-zero) indicates that this network is where the message originated,
    // for the purpose of relaying comments to other conversation members.
    // If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset.
    // If the API is used from another network with its own distribution
    // and deliveries, you may wish to set origin to 0 or false and allow the other
    // network to relay comments.
    // If you are unsure, it is prudent (and important) to leave it unset.
    $origin = $api_source && array_key_exists('origin', $_REQUEST) ? intval($_REQUEST['origin']) : 1;
    // To represent message-ids on other networks - this will create an item_id record
    $namespace = $api_source && array_key_exists('namespace', $_REQUEST) ? strip_tags($_REQUEST['namespace']) : '';
    $remote_id = $api_source && array_key_exists('remote_id', $_REQUEST) ? strip_tags($_REQUEST['remote_id']) : '';
    $owner_hash = null;
    $message_id = x($_REQUEST, 'message_id') && $api_source ? strip_tags($_REQUEST['message_id']) : '';
    $created = x($_REQUEST, 'created') ? datetime_convert('UTC', 'UTC', $_REQUEST['created']) : datetime_convert();
    $post_id = x($_REQUEST, 'post_id') ? intval($_REQUEST['post_id']) : 0;
    $app = x($_REQUEST, 'source') ? strip_tags($_REQUEST['source']) : '';
    $return_path = x($_REQUEST, 'return') ? $_REQUEST['return'] : '';
    $preview = x($_REQUEST, 'preview') ? intval($_REQUEST['preview']) : 0;
    $categories = x($_REQUEST, 'category') ? escape_tags($_REQUEST['category']) : '';
    $webpage = x($_REQUEST, 'webpage') ? intval($_REQUEST['webpage']) : 0;
    $pagetitle = x($_REQUEST, 'pagetitle') ? escape_tags(urlencode($_REQUEST['pagetitle'])) : '';
    $layout_mid = x($_REQUEST, 'layout_mid') ? escape_tags($_REQUEST['layout_mid']) : '';
    $plink = x($_REQUEST, 'permalink') ? escape_tags($_REQUEST['permalink']) : '';
    $obj_type = x($_REQUEST, 'obj_type') ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE;
    // allow API to bulk load a bunch of imported items with sending out a bunch of posts.
    $nopush = x($_REQUEST, 'nopush') ? intval($_REQUEST['nopush']) : 0;
    /*
     * Check service class limits
     */
    if ($uid && !x($_REQUEST, 'parent') && !x($_REQUEST, 'post_id')) {
        $ret = item_check_service_class($uid, $_REQUEST['webpage'] == ITEM_WEBPAGE ? true : false);
        if (!$ret['success']) {
            notice(t($ret['message']) . EOL);
            if (x($_REQUEST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
    }
    if ($pagetitle) {
        require_once 'library/urlify/URLify.php';
        $pagetitle = strtolower(URLify::transliterate($pagetitle));
    }
    $item_flags = $item_restrict = 0;
    $route = '';
    $parent_item = null;
    $parent_contact = null;
    $thr_parent = '';
    $parid = 0;
    $r = false;
    if ($parent || $parent_mid) {
        if (!x($_REQUEST, 'type')) {
            $_REQUEST['type'] = 'net-comment';
        }
        if ($obj_type == ACTIVITY_OBJ_POST) {
            $obj_type = ACTIVITY_OBJ_COMMENT;
        }
        if ($parent) {
            $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent));
        } elseif ($parent_mid && $uid) {
            // This is coming from an API source, and we are logged in
            $r = q("SELECT * FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_mid), intval($uid));
        }
        // if this isn't the real parent of the conversation, find it
        if ($r !== false && count($r)) {
            $parid = $r[0]['parent'];
            $parent_mid = $r[0]['mid'];
            if ($r[0]['id'] != $r[0]['parent']) {
                $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1", intval($parid));
            }
        }
        if ($r === false || !count($r)) {
            notice(t('Unable to locate original post.') . EOL);
            if (x($_REQUEST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
        // can_comment_on_post() needs info from the following xchan_query
        xchan_query($r);
        $parent_item = $r[0];
        $parent = $r[0]['id'];
        // multi-level threading - preserve the info but re-parent to our single level threading
        $thr_parent = $parent_mid;
        $route = $parent_item['route'];
    }
    if (!$observer) {
        $observer = $a->get_observer();
    }
    if ($parent) {
        logger('mod_item: item_post parent=' . $parent);
        $can_comment = false;
        if (array_key_exists('owner', $parent_item) && $parent_item['owner']['abook_flags'] & ABOOK_FLAG_SELF) {
            $can_comment = perm_is_allowed($profile_uid, $observer['xchan_hash'], 'post_comments');
        } else {
            $can_comment = can_comment_on_post($observer['xchan_hash'], $parent_item);
        }
        if (!$can_comment) {
            notice(t('Permission denied.') . EOL);
            if (x($_REQUEST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
    } else {
        if (!perm_is_allowed($profile_uid, $observer['xchan_hash'], 'post_wall')) {
            notice(t('Permission denied.') . EOL);
            if (x($_REQUEST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
    }
    // is this an edited post?
    $orig_post = null;
    if ($namespace && $remote_id) {
        // It wasn't an internally generated post - see if we've got an item matching this remote service id
        $i = q("select iid from item_id where service = '%s' and sid = '%s' limit 1", dbesc($namespace), dbesc($remote_id));
        if ($i) {
            $post_id = $i[0]['iid'];
        }
    }
    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];
    }
    if (!$channel) {
        if ($uid && $uid == $profile_uid) {
            $channel = $a->get_channel();
        } else {
            // posting as yourself but not necessarily to a channel you control
            $r = q("select * from channel left join account on channel_account_id = account_id where channel_id = %d LIMIT 1", intval($profile_uid));
            if ($r) {
                $channel = $r[0];
            }
        }
    }
    if (!$channel) {
        logger("mod_item: no channel.");
        if (x($_REQUEST, 'return')) {
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        killme();
    }
    $owner_xchan = null;
    $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($channel['channel_hash']));
    if ($r && count($r)) {
        $owner_xchan = $r[0];
    } else {
        logger("mod_item: no owner.");
        if (x($_REQUEST, 'return')) {
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        killme();
    }
    $walltowall = false;
    $walltowall_comment = false;
    if ($remote_xchan) {
        $observer = $remote_observer;
    }
    if ($observer) {
        logger('mod_item: post accepted from ' . $observer['xchan_name'] . ' for ' . $owner_xchan['xchan_name'], LOGGER_DEBUG);
        // wall-to-wall detection.
        // For top-level posts, if the author and owner are different it's a wall-to-wall
        // For comments, We need to additionally look at the parent and see if it's a wall post that originated locally.
        if ($observer['xchan_name'] != $owner_xchan['xchan_name']) {
            if ($parent_item && ($parent_item['item_flags'] & (ITEM_WALL | ITEM_ORIGIN)) == (ITEM_WALL | ITEM_ORIGIN)) {
                $walltowall_comment = true;
                $walltowall = true;
            }
            if (!$parent) {
                $walltowall = true;
            }
        }
    }
    $public_policy = x($_REQUEST, 'public_policy') ? escape_tags($_REQUEST['public_policy']) : map_scope($channel['channel_r_stream'], true);
    if ($webpage) {
        $public_policy = '';
    }
    if ($public_policy) {
        $private = 1;
    }
    if ($orig_post) {
        $private = 0;
        // webpages are allowed to change ACLs after the fact. Normal conversation items aren't.
        if ($webpage) {
            $str_group_allow = perms2str($_REQUEST['group_allow']);
            $str_contact_allow = perms2str($_REQUEST['contact_allow']);
            $str_group_deny = perms2str($_REQUEST['group_deny']);
            $str_contact_deny = perms2str($_REQUEST['contact_deny']);
        } else {
            $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'];
            $public_policy = $orig_post['public_policy'];
            $private = $orig_post['item_private'];
        }
        if (strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) || strlen($public_policy) || $private) {
            $private = 1;
        }
        $location = $orig_post['location'];
        $coord = $orig_post['coord'];
        $verb = $orig_post['verb'];
        $app = $orig_post['app'];
        $title = escape_tags(trim($_REQUEST['title']));
        $body = trim($_REQUEST['body']);
        $item_flags = $orig_post['item_flags'];
        // force us to recalculate if we need to obscure this post
        if ($item_flags & ITEM_OBSCURED) {
            $item_flags = $item_flags ^ ITEM_OBSCURED;
        }
        $item_restrict = $orig_post['item_restrict'];
        $postopts = $orig_post['postopts'];
        $created = $orig_post['created'];
        $mid = $orig_post['mid'];
        $parent_mid = $orig_post['parent_mid'];
        $plink = $orig_post['plink'];
    } else {
        // if coming from the API and no privacy settings are set,
        // use the user default permissions - as they won't have
        // been supplied via a form.
        if ($api_source && !array_key_exists('contact_allow', $_REQUEST) && !array_key_exists('group_allow', $_REQUEST) && !array_key_exists('contact_deny', $_REQUEST) && !array_key_exists('group_deny', $_REQUEST)) {
            $str_group_allow = $channel['channel_allow_gid'];
            $str_contact_allow = $channel['channel_allow_cid'];
            $str_group_deny = $channel['channel_deny_gid'];
            $str_contact_deny = $channel['channel_deny_cid'];
        } elseif ($walltowall) {
            // use the channel owner's default permissions
            $str_group_allow = $channel['channel_allow_gid'];
            $str_contact_allow = $channel['channel_allow_cid'];
            $str_group_deny = $channel['channel_deny_gid'];
            $str_contact_deny = $channel['channel_deny_cid'];
        } else {
            // use the posted permissions
            $str_group_allow = perms2str($_REQUEST['group_allow']);
            $str_contact_allow = perms2str($_REQUEST['contact_allow']);
            $str_group_deny = perms2str($_REQUEST['group_deny']);
            $str_contact_deny = perms2str($_REQUEST['contact_deny']);
        }
        $location = notags(trim($_REQUEST['location']));
        $coord = notags(trim($_REQUEST['coord']));
        $verb = notags(trim($_REQUEST['verb']));
        $title = escape_tags(trim($_REQUEST['title']));
        $body = trim($_REQUEST['body']);
        $body .= trim($_REQUEST['attachment']);
        $postopts = '';
        $private = strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny) || strlen($public_policy) ? 1 : 0;
        // If this is a comment, set the permissions from the parent.
        if ($parent_item) {
            $private = 0;
            if ($parent_item['item_private'] || strlen($parent_item['allow_cid']) || strlen($parent_item['allow_gid']) || strlen($parent_item['deny_cid']) || strlen($parent_item['deny_gid']) || strlen($parent_item['public_policy'])) {
                $private = $parent_item['item_private'] ? $parent_item['item_private'] : 1;
            }
            $public_policy = $parent_item['public_policy'];
            $str_contact_allow = $parent_item['allow_cid'];
            $str_group_allow = $parent_item['allow_gid'];
            $str_contact_deny = $parent_item['deny_cid'];
            $str_group_deny = $parent_item['deny_gid'];
            $owner_hash = $parent_item['owner_xchan'];
        }
        if (!strlen($body)) {
            if ($preview) {
                killme();
            }
            info(t('Empty post discarded.') . EOL);
            if (x($_REQUEST, 'return')) {
                goaway($a->get_baseurl() . "/" . $return_path);
            }
            killme();
        }
    }
    $expires = NULL_DATE;
    if (feature_enabled($profile_uid, 'content_expire')) {
        if (x($_REQUEST, 'expire')) {
            $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['expire']);
            if ($expires <= datetime_convert()) {
                $expires = NULL_DATE;
            }
        }
    }
    $mimetype = notags(trim($_REQUEST['mimetype']));
    if (!$mimetype) {
        $mimetype = 'text/bbcode';
    }
    if ($preview) {
        $body = z_input_filter($profile_uid, $body, $mimetype);
    }
    // Verify ability to use html or php!!!
    $execflag = false;
    if ($mimetype === 'application/x-php') {
        $z = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1", intval($profile_uid));
        if ($z && ($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE || $z[0]['channel_pageflags'] & PAGE_ALLOWCODE)) {
            if ($uid && get_account_id() == $z[0]['account_id']) {
                $execflag = true;
            } else {
                notice(t('Executable content type not permitted to this channel.') . EOL);
                if (x($_REQUEST, 'return')) {
                    goaway($a->get_baseurl() . "/" . $return_path);
                }
                killme();
            }
        }
    }
    if ($mimetype === 'text/bbcode') {
        require_once 'include/text.php';
        if ($uid && $uid == $profile_uid && feature_enabled($uid, 'markdown')) {
            require_once 'include/bb2diaspora.php';
            $body = escape_tags($body);
            $body = preg_replace_callback('/\\[share(.*?)\\]/ism', 'share_shield', $body);
            $body = diaspora2bb($body, true);
            $body = preg_replace_callback('/\\[share(.*?)\\]/ism', 'share_unshield', $body);
        }
        // BBCODE alert: the following functions assume bbcode input
        // and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
        // we may need virtual or template classes to implement the possible alternatives
        // Work around doubled linefeeds in Tinymce 3.5b2
        // First figure out if it's a status post that would've been
        // created using tinymce. Otherwise leave it alone.
        $plaintext = true;
        //		$plaintext = ((feature_enabled($profile_uid,'richtext')) ? false : true);
        //		if((! $parent) && (! $api_source) && (! $plaintext)) {
        //			$body = fix_mce_lf($body);
        //		}
        // If we're sending a private top-level message with a single @-taggable channel as a recipient, @-tag it, if our pconfig is set.
        if (!$parent && get_pconfig($profile_uid, 'system', 'tagifonlyrecip') && substr_count($str_contact_allow, '<') == 1 && $str_group_allow == '' && $str_contact_deny == '' && $str_group_deny == '') {
            $x = q("select abook_id, abook_their_perms from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc(str_replace(array('<', '>'), array('', ''), $str_contact_allow)), intval($profile_uid));
            if ($x && $x[0]['abook_their_perms'] & PERMS_W_TAGWALL) {
                $body .= "\n\n@group+" . $x[0]['abook_id'] . "\n";
            }
        }
        /**
         * fix naked links by passing through a callback to see if this is a red site
         * (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both.
         * First protect any url inside certain bbcode tags so we don't double link it.
         */
        $body = preg_replace_callback('/\\[code(.*?)\\[\\/(code)\\]/ism', 'red_escape_codeblock', $body);
        $body = preg_replace_callback('/\\[url(.*?)\\[\\/(url)\\]/ism', 'red_escape_codeblock', $body);
        $body = preg_replace_callback('/\\[zrl(.*?)\\[\\/(zrl)\\]/ism', 'red_escape_codeblock', $body);
        $body = preg_replace_callback("/([^\\]\\='" . '"' . "\\/]|^|\\#\\^)(https?\\:\\/\\/[a-zA-Z0-9\\:\\/\\-\\?\\&\\;\\.\\=\\@\\_\\~\\#\\%\$\\!\\+\\,]+)/ism", 'red_zrl_callback', $body);
        $body = preg_replace_callback('/\\[\\$b64zrl(.*?)\\[\\/(zrl)\\]/ism', 'red_unescape_codeblock', $body);
        $body = preg_replace_callback('/\\[\\$b64url(.*?)\\[\\/(url)\\]/ism', 'red_unescape_codeblock', $body);
        $body = preg_replace_callback('/\\[\\$b64code(.*?)\\[\\/(code)\\]/ism', 'red_unescape_codeblock', $body);
        // fix any img tags that should be zmg
        $body = preg_replace_callback('/\\[img(.*?)\\](.*?)\\[\\/img\\]/ism', 'red_zrlify_img_callback', $body);
        $body = bb_translate_video($body);
        /**
         * Fold multi-line [code] sequences
         */
        $body = preg_replace('/\\[\\/code\\]\\s*\\[code\\]/ism', "\n", $body);
        $body = scale_external_images($body, false);
        // Look for tags and linkify them
        $results = linkify_tags($a, $body, $uid ? $uid : $profile_uid);
        if ($results) {
            // Set permissions based on tag replacements
            set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private);
            $post_tags = array();
            foreach ($results as $result) {
                $success = $result['success'];
                if ($success['replaced']) {
                    $post_tags[] = array('uid' => $profile_uid, 'type' => $success['termtype'], 'otype' => TERM_OBJ_POST, 'term' => $success['term'], 'url' => $success['url']);
                }
            }
        }
        /**
         *
         * 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 photos and attachments that are in the
         * post and set them to the same permissions as the post itself.
         *
         * If the post was end-to-end encrypted we can't find images and attachments in the body,
         * use our media_str input instead which only contains these elements - but only do this
         * when encrypted content exists because the photo/attachment may have been removed from 
         * the post and we should keep it private. If it's encrypted we have no way of knowing
         * so we'll set the permissions regardless and realise that the media may not be 
         * referenced in the post. 
         *
         * What is preventing us from being able to upload photos into comments is dealing with
         * the photo and attachment permissions, since we don't always know who was in the 
         * distribution for the top level post.
         * 
         * We might be able to provide this functionality with a lot of fiddling:
         * - if the top level post is public (make the photo public)
         * - if the top level post was written by us or a wall post that belongs to us (match the top level post)
         * - if the top level post has privacy mentions, add those to the permissions.
         * - otherwise disallow the photo *or* make the photo public. This is the part that gets messy. 
         */
        if (!$preview) {
            fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], strpos($body, '[/crypt]') ? $_POST['media_str'] : $body, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
            fix_attached_file_permissions($channel, $observer['xchan_hash'], strpos($body, '[/crypt]') ? $_POST['media_str'] : $body, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
        }
        $attachments = '';
        $match = false;
        if (preg_match_all('/(\\[attachment\\](.*?)\\[\\/attachment\\])/', $body, $match)) {
            $attachments = array();
            foreach ($match[2] as $mtch) {
                $hash = substr($mtch, 0, strpos($mtch, ','));
                $rev = intval(substr($mtch, strpos($mtch, ',')));
                $r = attach_by_hash_nodata($hash, $rev);
                if ($r['success']) {
                    $attachments[] = array('href' => $a->get_baseurl() . '/attach/' . $r['data']['hash'], 'length' => $r['data']['filesize'], 'type' => $r['data']['filetype'], 'title' => urlencode($r['data']['filename']), 'revision' => $r['data']['revision']);
                }
                $body = str_replace($match[1], '', $body);
            }
        }
    }
    // BBCODE end alert
    if (strlen($categories)) {
        $cats = explode(',', $categories);
        foreach ($cats as $cat) {
            $post_tags[] = array('uid' => $profile_uid, 'type' => TERM_CATEGORY, 'otype' => TERM_OBJ_POST, 'term' => trim($cat), 'url' => $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat)));
        }
    }
    $item_unseen = 1;
    // determine if this is a wall post
    if ($parent) {
        if ($parent_item['item_flags'] & ITEM_WALL) {
            $item_flags = $item_flags | ITEM_WALL;
        }
    } else {
        if (!$webpage) {
            $item_flags = $item_flags | ITEM_WALL;
        }
    }
    if ($origin) {
        $item_flags = $item_flags | ITEM_ORIGIN;
    }
    if ($moderated) {
        $item_restrict = $item_restrict | ITEM_MODERATED;
    }
    if ($webpage) {
        $item_restrict = $item_restrict | $webpage;
    }
    if (!strlen($verb)) {
        $verb = ACTIVITY_POST;
    }
    $notify_type = $parent ? 'comment-new' : 'wall-new';
    if (!$mid) {
        $mid = $message_id ? $message_id : item_message_id();
    }
    if (!$parent_mid) {
        $parent_mid = $mid;
    }
    if ($parent_item) {
        $parent_mid = $parent_item['mid'];
    }
    // Fallback so that we alway have a thr_parent
    if (!$thr_parent) {
        $thr_parent = $mid;
    }
    $datarray = array();
    if (!$parent) {
        $item_flags = $item_flags | ITEM_THREAD_TOP;
    }
    if ($consensus) {
        $item_flags |= ITEM_CONSENSUS;
    }
    if (!$plink && $item_flags & ITEM_THREAD_TOP) {
        $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $mid;
    }
    $datarray['aid'] = $channel['channel_account_id'];
    $datarray['uid'] = $profile_uid;
    $datarray['owner_xchan'] = $owner_hash ? $owner_hash : $owner_xchan['xchan_hash'];
    $datarray['author_xchan'] = $observer['xchan_hash'];
    $datarray['created'] = $created;
    $datarray['edited'] = $orig_post ? datetime_convert() : $created;
    $datarray['expires'] = $expires;
    $datarray['commented'] = $orig_post ? datetime_convert() : $created;
    $datarray['received'] = $orig_post ? datetime_convert() : $created;
    $datarray['changed'] = $orig_post ? datetime_convert() : $created;
    $datarray['mid'] = $mid;
    $datarray['parent_mid'] = $parent_mid;
    $datarray['mimetype'] = $mimetype;
    $datarray['title'] = $title;
    $datarray['body'] = $body;
    $datarray['app'] = $app;
    $datarray['location'] = $location;
    $datarray['coord'] = $coord;
    $datarray['verb'] = $verb;
    $datarray['obj_type'] = $obj_type;
    $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['item_private'] = $private;
    $datarray['attach'] = $attachments;
    $datarray['thr_parent'] = $thr_parent;
    $datarray['postopts'] = $postopts;
    $datarray['item_restrict'] = $item_restrict;
    $datarray['item_flags'] = $item_flags;
    $datarray['layout_mid'] = $layout_mid;
    $datarray['public_policy'] = $public_policy;
    $datarray['comment_policy'] = map_scope($channel['channel_w_comment']);
    $datarray['term'] = $post_tags;
    $datarray['plink'] = $plink;
    $datarray['route'] = $route;
    $datarray['item_unseen'] = $item_unseen;
    // preview mode - prepare the body for display and send it via json
    if ($preview) {
        require_once 'include/conversation.php';
        $datarray['owner'] = $owner_xchan;
        $datarray['author'] = $observer;
        $datarray['attach'] = json_encode($datarray['attach']);
        $o = conversation($a, array($datarray), 'search', false, 'preview');
        //		logger('preview: ' . $o, LOGGER_DEBUG);
        echo json_encode(array('preview' => $o));
        killme();
    }
    if ($orig_post) {
        $datarray['edit'] = true;
    }
    call_hooks('post_local', $datarray);
    if (x($datarray, 'cancel')) {
        logger('mod_item: post cancelled by plugin.');
        if ($return_path) {
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        $json = array('cancel' => 1);
        if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) {
            $json['reload'] = $a->get_baseurl() . '/' . $_REQUEST['jsreload'];
        }
        echo json_encode($json);
        killme();
    }
    if (mb_strlen($datarray['title']) > 255) {
        $datarray['title'] = mb_substr($datarray['title'], 0, 255);
    }
    if (array_key_exists('item_private', $datarray) && $datarray['item_private']) {
        $datarray['body'] = trim(z_input_filter($datarray['uid'], $datarray['body'], $datarray['mimetype']));
        if ($uid) {
            if ($channel['channel_hash'] === $datarray['author_xchan']) {
                $datarray['sig'] = base64url_encode(rsa_sign($datarray['body'], $channel['channel_prvkey']));
                $datarray['item_flags'] = $datarray['item_flags'] | ITEM_VERIFIED;
            }
        }
        logger('Encrypting local storage');
        $key = get_config('system', 'pubkey');
        $datarray['item_flags'] = $datarray['item_flags'] | ITEM_OBSCURED;
        if ($datarray['title']) {
            $datarray['title'] = json_encode(crypto_encapsulate($datarray['title'], $key));
        }
        if ($datarray['body']) {
            $datarray['body'] = json_encode(crypto_encapsulate($datarray['body'], $key));
        }
    }
    if ($orig_post) {
        $datarray['id'] = $post_id;
        item_store_update($datarray, $execflag);
        update_remote_id($channel, $post_id, $webpage, $pagetitle, $namespace, $remote_id, $mid);
        if (!$nopush) {
            proc_run('php', "include/notifier.php", 'edit_post', $post_id);
        }
        if (x($_REQUEST, 'return') && strlen($return_path)) {
            logger('return: ' . $return_path);
            goaway($a->get_baseurl() . "/" . $return_path);
        }
        killme();
    } else {
        $post_id = 0;
    }
    $post = item_store($datarray, $execflag);
    $post_id = $post['item_id'];
    if ($post_id) {
        logger('mod_item: saved item ' . $post_id);
        if ($parent) {
            // only send comment notification if this is a wall-to-wall comment,
            // otherwise it will happen during delivery
            if ($datarray['owner_xchan'] != $datarray['author_xchan'] && $parent_item['item_flags'] & ITEM_WALL) {
                notification(array('type' => NOTIFY_COMMENT, 'from_xchan' => $datarray['author_xchan'], 'to_xchan' => $datarray['owner_xchan'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . $datarray['mid'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, 'parent_mid' => $parent_item['mid']));
            }
        } else {
            $parent = $post_id;
            if ($datarray['owner_xchan'] != $datarray['author_xchan']) {
                notification(array('type' => NOTIFY_WALL, 'from_xchan' => $datarray['author_xchan'], 'to_xchan' => $datarray['owner_xchan'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . $datarray['mid'], 'verb' => ACTIVITY_POST, 'otype' => 'item'));
            }
            if ($uid && $uid == $profile_uid && !$datarray['item_restrict']) {
                q("update channel set channel_lastpost = '%s' where channel_id = %d", dbesc(datetime_convert()), intval($uid));
            }
        }
        // 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['item_restrict'] & ITEM_HIDDEN) {
            $r = q("UPDATE `item` SET `item_restrict` = %d WHERE `id` = %d", intval($parent_item['item_restrict'] - ITEM_HIDDEN), intval($parent_item['id']));
        }
    } else {
        logger('mod_item: unable to retrieve post that was just stored.');
        notice(t('System error. Post not saved.') . EOL);
        goaway($a->get_baseurl() . "/" . $return_path);
        // NOTREACHED
    }
    if ($parent) {
        // Store the comment signature information in case we need to relay to Diaspora
        $ditem = $datarray;
        $ditem['author'] = $observer;
        store_diaspora_comment_sig($ditem, $channel, $parent_item, $post_id, $walltowall_comment ? 1 : 0);
    }
    update_remote_id($channel, $post_id, $webpage, $pagetitle, $namespace, $remote_id, $mid);
    $datarray['id'] = $post_id;
    $datarray['llink'] = $a->get_baseurl() . '/display/' . $channel['channel_address'] . '/' . $post_id;
    call_hooks('post_local_end', $datarray);
    if (!$nopush) {
        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 $post;
    }
    if ($return_path) {
        goaway($a->get_baseurl() . "/" . $return_path);
    }
    $json = array('success' => 1);
    if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) {
        $json['reload'] = $a->get_baseurl() . '/' . $_REQUEST['jsreload'];
    }
    logger('post_json: ' . print_r($json, true), LOGGER_DEBUG);
    echo json_encode($json);
    killme();
    // NOTREACHED
}