示例#1
0
function p_init(&$a)
{
    if (argc() < 2) {
        http_status_exit(401);
    }
    $mid = str_replace('.xml', '', argv(1));
    $r = q("select * from item where mid = '%s' and item_wall = 1 and item_private = 0 limit 1", dbesc($mid));
    if (!$r || !perm_is_allowed($r[0]['uid'], '', 'view_stream')) {
        http_status_exit(404);
    }
    $c = q("select * from channel where channel_id = %d limit 1", intval($r[0]['uid']));
    if (!$c) {
        http_status_exit(404);
    }
    $myaddr = channel_reddress($c[0]);
    $item = $r[0];
    $title = $item['title'];
    $body = bb2diaspora_itembody($item);
    $created = datetime_convert('UTC', 'UTC', $item['created'], 'Y-m-d H:i:s \\U\\T\\C');
    $tpl = get_markup_template('diaspora_post.tpl', 'addon/diaspora');
    $msg = replace_macros($tpl, array('$body' => xmlify($body), '$guid' => $item['mid'], '$handle' => xmlify($myaddr), '$public' => 'true', '$created' => $created, '$provider' => $item['app'] ? $item['app'] : t('$projectname')));
    header('Content-type: text/xml');
    echo $msg;
    killme();
}
示例#2
0
文件: Xrd.php 项目: phellmes/hubzilla
 function init()
 {
     $uri = urldecode(notags(trim($_GET['uri'])));
     logger('xrd: ' . $uri, LOGGER_DEBUG);
     $resource = $uri;
     if (substr($uri, 0, 4) === 'http') {
         $uri = str_replace('~', '', $uri);
         $name = basename($uri);
     } else {
         $local = str_replace('acct:', '', $uri);
         if (substr($local, 0, 2) == '//') {
             $local = substr($local, 2);
         }
         $name = substr($local, 0, strpos($local, '@'));
     }
     $r = q("SELECT * FROM channel WHERE channel_address = '%s' LIMIT 1", dbesc($name));
     if (!$r) {
         killme();
     }
     $dspr = replace_macros(get_markup_template('xrd_diaspora.tpl'), array('$baseurl' => z_root(), '$dspr_guid' => $r[0]['channel_guid'] . str_replace('.', '', \App::get_hostname()), '$dspr_key' => base64_encode(pemtorsa($r[0]['channel_pubkey']))));
     $salmon_key = salmon_key($r[0]['channel_pubkey']);
     header('Access-Control-Allow-Origin: *');
     header("Content-type: application/xrd+xml");
     $aliases = array('acct:' . channel_reddress($r[0]), z_root() . '/channel/' . $r[0]['channel_address'], z_root() . '/~' . $r[0]['channel_address']);
     for ($x = 0; $x < count($aliases); $x++) {
         if ($aliases[$x] === $resource) {
             unset($aliases[$x]);
         }
     }
     $o = replace_macros(get_markup_template('xrd_person.tpl'), array('$nick' => $r[0]['channel_address'], '$accturi' => $resource, '$aliases' => $aliases, '$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'], '$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'], '$atom' => z_root() . '/feed/' . $r[0]['channel_address'], '$zot_post' => z_root() . '/post/' . $r[0]['channel_address'], '$poco_url' => z_root() . '/poco/' . $r[0]['channel_address'], '$photo' => z_root() . '/photo/profile/l/' . $r[0]['channel_id'], '$dspr' => $dspr, '$modexp' => 'data:application/magic-public-key,' . $salmon_key, '$subscribe' => z_root() . '/follow?url={uri}', '$bigkey' => salmon_key($r[0]['channel_pubkey'])));
     $arr = array('user' => $r[0], 'xml' => $o);
     call_hooks('personal_xrd', $arr);
     echo $arr['xml'];
     killme();
 }
示例#3
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 = channel_reddress($rr['channel']);
             $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(channel_reddress($rr)), 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;
     }
 }
示例#4
0
 function post()
 {
     if (!array_key_exists('channel', \App::$data)) {
         return;
     }
     $edit = local_channel() && local_channel() == \App::$data['channel']['channel_id'] ? true : false;
     if ($edit) {
         $has_premium = \App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM ? 1 : 0;
         $premium = $_POST['premium'] ? intval($_POST['premium']) : 0;
         $text = escape_tags($_POST['text']);
         if ($has_premium != $premium) {
             $r = q("update channel set channel_pageflags = ( channel_pageflags %s %d ) where channel_id = %d", db_getfunc('^'), intval(PAGE_PREMIUM), intval(local_channel()));
             \Zotlabs\Daemon\Master::Summon(array('Notifier', 'refresh_all', \App::$data['channel']['channel_id']));
         }
         set_pconfig(\App::$data['channel']['channel_id'], 'system', 'selltext', $text);
         // reload the page completely to get fresh data
         goaway(z_root() . '/' . \App::$query_string);
     }
     $url = '';
     $observer = \App::get_observer();
     if ($observer && $_POST['submit'] === t('Continue')) {
         if ($observer['xchan_follow']) {
             $url = sprintf($observer['xchan_follow'], urlencode(channel_reddress(\App::$data['channel'])));
         }
         if (!$url) {
             $r = q("select * from hubloc where hubloc_hash = '%s' order by hubloc_id desc limit 1", dbesc($observer['xchan_hash']));
             if ($r) {
                 $url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(channel_reddress(\App::$data['channel']));
             }
         }
     }
     if ($url) {
         goaway($url . '&confirm=1');
     } else {
         notice('Unable to connect to your home hub location.');
     }
 }
示例#5
0
 function exec()
 {
     $opts = $this->curlopts;
     $url = $this->url;
     if ($this->auth) {
         $opts['http_auth'] = $this->auth;
     }
     if ($this->magicauth) {
         $opts['cookiejar'] = 'store/[data]/cookie_' . $this->magicauth;
         $opts['cookiefile'] = 'store/[data]/cookie_' . $this->magicauth;
         $opts['cookie'] = 'PHPSESSID=' . trim(file_get_contents('store/[data]/cookien_' . $this->magicauth));
         $c = channelx_by_n($this->magicauth);
         if ($c) {
             $url = zid($this->url, channel_reddress($c));
         }
     }
     if ($this->custom) {
         $opts['custom'] = $this->custom;
     }
     if ($this->headers) {
         $opts['headers'] = $this->headers;
     }
     if ($this->upload) {
         $opts['upload'] = true;
         $opts['infile'] = $this->filehandle;
         $opts['infilesize'] = strlen($this->request_data);
         $opts['readfunc'] = [$this, 'curl_read'];
     }
     $recurse = 0;
     return z_fetch_url($this->url, true, $recurse, $opts ? $opts : null);
 }
示例#6
0
function diaspora_post_local(&$a, &$item)
{
    /**
     * If all the conditions are met, generate an instance of the Diaspora Comment Virus
     *
     * Previously all comments from any Hubzilla source (including those who have not opted in to
     * Diaspora federation), were required to locally generate a Diaspora comment signature.
     * The only exception was wall-to-wall posts which have no local signing authority.
     *
     * Going forward, if we are asked to propagate the virus and it is not present (due to the post author
     * not opting in to Diaspora federation); we will generate a "wall-to-wall" comment and not require 
     * a source signature. This allows hubs and communities to opt-out of Diaspora federation and not be
     * forced to generate the comment virus regardless. This is necessary because Diaspora now requires
     * the virus not just to provide a stored signature and Diaspora formatted text body, but must also 
     * include all XML fields presented by the Diaspora protocol when transmitting the comment, while
     * maintaining their source order. This is fine for federated communities using UNO, but it makes 
     * no sense to require this low-level baggage in channels and communities that have chosen not to use
     * the Diaspora protocol and services.
     *   
     */
    require_once 'include/bb2diaspora.php';
    if ($item['mid'] === $item['parent_mid']) {
        return;
    }
    if ($item['created'] != $item['edited']) {
        return;
    }
    $meta = null;
    $author = channelx_by_hash($item['author_xchan']);
    if ($author) {
        // The author has a local channel, If they have this connector installed,
        // sign the comment and create a Diaspora Comment Virus.
        $dspr_allowed = get_pconfig($author['channel_id'], 'system', 'diaspora_allowed');
        if (!$dspr_allowed) {
            return;
        }
        $handle = channel_reddress($author);
        if ($item['verb'] === ACTIVITY_LIKE) {
            if ($item['thr_parent'] == $item['parent_mid'] && $item['obj_type'] == ACTIVITY_OBJ_NOTE) {
                $meta = ['positive' => 'true', 'guid' => $item['mid'], 'target_type' => 'Post', 'parent_guid' => $item['parent_mid'], 'diaspora_handle' => $handle];
            }
        } else {
            $body = bb2diaspora_itembody($item, true, true);
            $meta = ['guid' => $item['mid'], 'parent_guid' => $item['parent_mid'], 'text' => $body, 'diaspora_handle' => $handle];
        }
        $meta['author_signature'] = diaspora_sign_fields($meta, $author['channel_prvkey']);
        if ($item['author_xchan'] === $item['owner_xchan']) {
            $meta['parent_author_signature'] = diaspora_sign_fields($meta, $author['channel_prvkey']);
        }
    }
    if (!$meta && $item['author_xchan'] !== $item['owner_xchan']) {
        // A local comment arrived but the commenter does not have a local channel
        // or the commenter doesn't have the Diaspora plugin enabled.
        // The owner *should* have a local channel
        // Find the owner and if the owner has this addon installed, turn the comment into
        // a 'wall-to-wall' message containing the author attribution,
        // with the comment signed by the owner.
        $owner = channelx_by_hash($item['owner_xchan']);
        if (!$owner) {
            return;
        }
        $dspr_allowed = get_pconfig($owner['channel_id'], 'system', 'diaspora_allowed');
        if (!$dspr_allowed) {
            return;
        }
        $handle = channel_reddress($owner);
        if ($item['verb'] === ACTIVITY_LIKE) {
            if ($item['thr_parent'] == $item['parent_mid'] && $item['obj_type'] == ACTIVITY_OBJ_NOTE) {
                $meta = ['positive' => 'true', 'guid' => $item['mid'], 'target_type' => 'Post', 'parent_guid' => $item['parent_mid'], 'diaspora_handle' => $handle];
            }
        } else {
            $body = bb2diaspora_itembody($item, true, false);
            $meta = ['guid' => $item['mid'], 'parent_guid' => $item['parent_mid'], 'text' => $body, 'diaspora_handle' => $handle];
        }
        $meta['author_signature'] = diaspora_sign_fields($meta, $owner['channel_prvkey']);
        $meta['parent_author_signature'] = diaspora_sign_fields($meta, $owner['channel_prvkey']);
    }
    if ($meta) {
        set_iconfig($item, 'diaspora', 'fields', $meta, true);
    }
    // otherwise, neither the author or owner have this plugin installed. Do nothing.
    // 	logger('ditem: ' . print_r($item,true));
}
示例#7
0
function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, $walltowall = false)
{
    // We won't be able to sign Diaspora comments for authenticated visitors
    // - we don't have their private key
    // since Diaspora doesn't handle edits we can only do this for the original text and not update it.
    require_once 'include/bb2diaspora.php';
    $signed_body = bb2diaspora_itembody($datarray, $walltowall);
    if ($walltowall) {
        logger('wall to wall comment', LOGGER_DEBUG);
        // post will come across with the owner's identity. Throw a preamble onto the post to indicate the true author.
        $signed_body = "\n\n" . '![' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_photo_m'] . ')' . '[' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_url'] . ')' . "\n\n" . $signed_body;
    }
    logger('storing diaspora comment signature', LOGGER_DEBUG);
    $diaspora_handle = channel_reddress($channel);
    $signed_text = $datarray['mid'] . ';' . $parent_item['mid'] . ';' . $signed_body . ';' . $diaspora_handle;
    if ($channel && $channel['channel_prvkey']) {
        $authorsig = base64_encode(rsa_sign($signed_text, $channel['channel_prvkey'], 'sha256'));
    } else {
        $authorsig = '';
    }
    $x = array('signer' => $diaspora_handle, 'body' => $signed_body, 'signed_text' => $signed_text, 'signature' => $authorsig);
    $y = json_encode($x);
    $r = q("update item set diaspora_meta = '%s' where id = %d", dbesc($y), intval($post_id));
    if (!$r) {
        logger('store_diaspora_comment_sig: DB write failed');
    }
    return;
}
示例#8
0
function get_zcard_embed($channel, $observer_hash = '', $args = array())
{
    logger('get_zcard_embed');
    $maxwidth = $args['width'] ? intval($args['width']) : 0;
    $maxheight = $args['height'] ? intval($args['height']) : 0;
    if ($maxwidth > 1200 || $maxwidth < 1) {
        $maxwidth = 1200;
    }
    if ($maxwidth <= 425) {
        $width = 425;
        $size = 'hz_small';
        $cover_size = PHOTO_RES_COVER_425;
        $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 80, 'height' => 80, 'href' => $channel['xchan_photo_m']);
    } elseif ($maxwidth <= 900) {
        $width = 900;
        $size = 'hz_medium';
        $cover_size = PHOTO_RES_COVER_850;
        $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 160, 'height' => 160, 'href' => $channel['xchan_photo_l']);
    } elseif ($maxwidth <= 1200) {
        $width = 1200;
        $size = 'hz_large';
        $cover_size = PHOTO_RES_COVER_1200;
        $pphoto = array('mimetype' => $channel['xchan_photo_mimetype'], 'width' => 300, 'height' => 300, 'href' => $channel['xchan_photo_l']);
    }
    $channel['channel_addr'] = channel_reddress($channel);
    $zcard = array('chan' => $channel);
    $r = q("select height, width, resource_id, imgscale, mimetype from photo where uid = %d and imgscale = %d and photo_usage = %d", intval($channel['channel_id']), intval($cover_size), intval(PHOTO_COVER));
    if ($r) {
        $cover = $r[0];
        $cover['href'] = z_root() . '/photo/' . $r[0]['resource_id'] . '-' . $r[0]['imgscale'];
    } else {
        $cover = $pphoto;
    }
    $o .= replace_macros(get_markup_template('zcard_embed.tpl'), array('$maxwidth' => $maxwidth, '$scale' => $scale, '$translate' => $translate, '$size' => $size, '$cover' => $cover, '$pphoto' => $pphoto, '$zcard' => $zcard));
    return $o;
}
示例#9
0
function diaspora_build_status($item, $owner)
{
    $myaddr = channel_reddress($owner);
    if (intval($item['id']) != intval($item['parent'])) {
        logger('attempted to send a comment as a top-level post');
        return;
    }
    $images = array();
    $title = $item['title'];
    $body = bb2diaspora_itembody($item, true);
    $poll = '';
    $public = $item['item_private'] ? 'false' : 'true';
    $created = datetime_convert('UTC', 'UTC', $item['created'], 'Y-m-d H:i:s \\U\\T\\C');
    // Detect a share element and do a reshare
    if (!$item['item_private'] && ($ret = diaspora_is_reshare($item['body']))) {
        $msg = replace_macros(get_markup_template('diaspora_reshare.tpl', 'addon/diaspora'), ['$root_handle' => xmlify($ret['root_handle']), '$root_guid' => $ret['root_guid'], '$guid' => $item['mid'], '$handle' => xmlify($myaddr), '$public' => $public, '$created' => $created, '$provider' => $item['app'] ? $item['app'] : t('$projectname')]);
    } else {
        $msg = replace_macros(get_markup_template('diaspora_post.tpl', 'addon/diaspora'), ['$body' => xmlify($body), '$guid' => $item['mid'], '$poll' => $poll, '$handle' => xmlify($myaddr), '$public' => $public, '$created' => $created, '$provider' => $item['app'] ? $item['app'] : t('$projectname')]);
    }
    return $msg;
}
示例#10
0
/**
 * @brief Change to another channel with current logged-in account.
 *
 * @param int $change_channel The channel_id of the channel you want to change to
 *
 * @return bool|array false or channel record of the new channel
 */
function change_channel($change_channel)
{
    $ret = false;
    if ($change_channel) {
        $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel_id = %d and channel_account_id = %d and channel_removed = 0 limit 1", intval($change_channel), intval(get_account_id()));
        // It's not there.  Is this an administrator, and is this the sys channel?
        if (is_developer()) {
            if (!$r) {
                if (is_site_admin()) {
                    $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel_id = %d and channel_system = 1 and channel_removed = 0 limit 1", intval($change_channel));
                }
            }
        }
        if ($r) {
            $hash = $r[0]['channel_hash'];
            $_SESSION['uid'] = intval($r[0]['channel_id']);
            App::set_channel($r[0]);
            $_SESSION['theme'] = $r[0]['channel_theme'];
            $_SESSION['mobile_theme'] = get_pconfig(local_channel(), 'system', 'mobile_theme');
            date_default_timezone_set($r[0]['channel_timezone']);
            $ret = $r[0];
        }
        $x = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($hash));
        if ($x) {
            $_SESSION['my_url'] = $x[0]['xchan_url'];
            $_SESSION['my_address'] = channel_reddress($r[0]);
            App::set_observer($x[0]);
            App::set_perms(get_all_perms(local_channel(), $hash));
        }
        if (!is_dir('store/' . $r[0]['channel_address'])) {
            @os_mkdir('store/' . $r[0]['channel_address'], STORAGE_DEFAULT_PERMISSIONS, true);
        }
        $arr = ['channel_id' => $change_channel, 'chanx' => $ret];
        call_hooks('change_channel', $arr);
    }
    return $ret;
}
示例#11
0
function diaspora_profile_change($channel, $recip, $public_batch = false)
{
    $channel_id = $channel['channel_id'];
    $r = q("SELECT profile.uid AS profile_uid, profile.* , channel.* FROM profile\n\t\tleft join channel on profile.uid = channel.channel_id\n\t\tWHERE channel.channel_id = %d and profile.is_default = 1 ", intval($channel_id));
    $profile_visible = perm_is_allowed($channel_id, '', 'view_profile');
    if (!$r) {
        return;
    }
    $profile = $r[0];
    $handle = xmlify(channel_reddress($channel));
    $first = xmlify(strpos($profile['channel_name'], ' ') ? trim(substr($profile['channel_name'], 0, strpos($profile['channel_name'], ' '))) : $profile['channel_name']);
    $last = xmlify($first === $profile['channel_name'] ? '' : trim(substr($profile['channel_name'], strlen($first))));
    $large = xmlify(z_root() . '/photo/profile/300/' . $profile['profile_uid'] . '.jpg');
    $medium = xmlify(z_root() . '/photo/profile/100/' . $profile['profile_uid'] . '.jpg');
    $small = xmlify(z_root() . '/photo/profile/50/' . $profile['profile_uid'] . '.jpg');
    $searchable = xmlify($profile_visible ? 'true' : 'false');
    $nsfw = $channel['channel_pageflags'] & (PAGE_ADULT | PAGE_CENSORED) ? 'true' : 'false';
    if ($searchable === 'true') {
        $dob = '1000-00-00';
        if ($profile['dob'] && $profile['dob'] != '0000-00-00') {
            $dob = (intval($profile['dob']) ? intval($profile['dob']) : '1000') . '-' . datetime_convert('UTC', 'UTC', $profile['dob'], 'm-d');
        }
        if ($dob === '1000-00-00') {
            $dob = '';
        }
        $gender = xmlify($profile['gender']);
        $about = $profile['about'];
        require_once 'include/bbcode.php';
        $about = xmlify(strip_tags(bbcode($about)));
        $location = '';
        if ($profile['locality']) {
            $location .= $profile['locality'];
        }
        if ($profile['region']) {
            if ($location) {
                $location .= ', ';
            }
            $location .= $profile['region'];
        }
        if ($profile['country_name']) {
            if ($location) {
                $location .= ', ';
            }
            $location .= $profile['country_name'];
        }
        $location = xmlify($location);
        $tags = '';
        if ($profile['keywords']) {
            $kw = str_replace(',', ' ', $profile['keywords']);
            $kw = str_replace('  ', ' ', $kw);
            $arr = explode(' ', $profile['keywords']);
            if (count($arr)) {
                for ($x = 0; $x < 5; $x++) {
                    if (trim($arr[$x])) {
                        $tags .= '#' . trim($arr[$x]) . ' ';
                    }
                }
            }
        }
        $tags = xmlify(trim($tags));
    }
    $tpl = get_markup_template('diaspora_profile.tpl', 'addon/diaspora');
    $msg = replace_macros($tpl, array('$handle' => $handle, '$first' => $first, '$last' => $last, '$large' => $large, '$medium' => $medium, '$small' => $small, '$dob' => $dob, '$gender' => $gender, '$about' => $about, '$location' => $location, '$searchable' => $searchable, '$nsfw' => $nsfw, '$tags' => $tags));
    logger('profile_change: ' . $msg, LOGGER_ALL, LOG_DEBUG);
    $slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg, $channel, $recip, $channel['channel_prvkey'], $recip['xchan_pubkey'], $public_batch)));
    return diaspora_queue($channel, $recip, $slap, $public_batch);
}
示例#12
0
 function init()
 {
     $ret = array('success' => false, 'url' => '', 'message' => '');
     logger('mod_magic: invoked', LOGGER_DEBUG);
     logger('mod_magic: args: ' . print_r($_REQUEST, true), LOGGER_DATA);
     $addr = x($_REQUEST, 'addr') ? $_REQUEST['addr'] : '';
     $dest = x($_REQUEST, 'dest') ? $_REQUEST['dest'] : '';
     $test = x($_REQUEST, 'test') ? intval($_REQUEST['test']) : 0;
     $rev = x($_REQUEST, 'rev') ? intval($_REQUEST['rev']) : 0;
     $delegate = x($_REQUEST, 'delegate') ? $_REQUEST['delegate'] : '';
     $parsed = parse_url($dest);
     if (!$parsed) {
         if ($test) {
             $ret['message'] .= 'could not parse ' . $dest . EOL;
             return $ret;
         }
         goaway($dest);
     }
     $basepath = $parsed['scheme'] . '://' . $parsed['host'] . ($parsed['port'] ? ':' . $parsed['port'] : '');
     $x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1", dbesc($basepath));
     if (!$x) {
         /*
          * We have no records for, or prior communications with this hub. 
          * If an address was supplied, let's finger them to create a hub record. 
          * Otherwise we'll use the special address '[system]' which will return
          * either a system channel or the first available normal channel. We don't
          * really care about what channel is returned - we need the hub information 
          * from that response so that we can create signed auth packets destined 
          * for that hub.
          *
          */
         $j = \Zotlabs\Zot\Finger::run($addr ? $addr : '[system]@' . $parsed['host'], null);
         if ($j['success']) {
             import_xchan($j);
             // Now try again
             $x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1", dbesc($basepath));
         }
     }
     if (!$x) {
         if ($rev) {
             goaway($dest);
         } else {
             logger('mod_magic: no channels found for requested hub.' . print_r($_REQUEST, true));
             if ($test) {
                 $ret['message'] .= 'This site has no previous connections with ' . $basepath . EOL;
                 return $ret;
             }
             notice(t('Hub not found.') . EOL);
             return;
         }
     }
     // This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
     // By default, we'll proceed without asking.
     $arr = array('channel_id' => local_channel(), 'xchan' => $x[0], 'destination' => $dest, 'proceed' => true);
     call_hooks('magic_auth', $arr);
     $dest = $arr['destination'];
     if (!$arr['proceed']) {
         if ($test) {
             $ret['message'] .= 'cancelled by plugin.' . EOL;
             return $ret;
         }
         goaway($dest);
     }
     if (get_observer_hash() && $x[0]['hubloc_url'] === z_root()) {
         // We are already authenticated on this site and a registered observer.
         // Just redirect.
         if ($test) {
             $ret['success'] = true;
             $ret['message'] .= 'Local site - you are already authenticated.' . EOL;
             return $ret;
         }
         $delegation_success = false;
         if ($delegate) {
             $r = q("select * from channel left join hubloc on channel_hash = hubloc_hash where hubloc_addr = '%s' limit 1", dbesc($delegate));
             if ($r && intval($r[0]['channel_id'])) {
                 $allowed = perm_is_allowed($r[0]['channel_id'], get_observer_hash(), 'delegate');
                 if ($allowed) {
                     $_SESSION['delegate_channel'] = $r[0]['channel_id'];
                     $_SESSION['delegate'] = get_observer_hash();
                     $_SESSION['account_id'] = intval($r[0]['channel_account_id']);
                     change_channel($r[0]['channel_id']);
                     $delegation_success = true;
                 }
             }
         }
         // FIXME: check and honour local delegation
         goaway($dest);
     }
     if (local_channel()) {
         $channel = \App::get_channel();
         $token = random_string();
         $token_sig = base64url_encode(rsa_sign($token, $channel['channel_prvkey']));
         $channel['token'] = $token;
         $channel['token_sig'] = $token_sig;
         \Zotlabs\Zot\Verify::create('auth', $channel['channel_id'], $token, $x[0]['hubloc_url']);
         $target_url = $x[0]['hubloc_callback'] . '/?f=&auth=' . urlencode(channel_reddress($channel)) . '&sec=' . $token . '&dest=' . urlencode($dest) . '&version=' . ZOT_REVISION;
         if ($delegate) {
             $target_url .= '&delegate=' . urlencode($delegate);
         }
         logger('mod_magic: redirecting to: ' . $target_url, LOGGER_DEBUG);
         if ($test) {
             $ret['success'] = true;
             $ret['url'] = $target_url;
             $ret['message'] = 'token ' . $token . ' created for channel ' . $channel['channel_id'] . ' for url ' . $x[0]['hubloc_url'] . EOL;
             return $ret;
         }
         goaway($target_url);
     }
     if ($test) {
         $ret['message'] = 'Not authenticated or invalid arguments to mod_magic' . EOL;
         return $ret;
     }
     goaway($dest);
 }
示例#13
0
/**
 * @brief Push local channel updates to a local directory server.
 *
 * This is called from include/directory.php if a profile is to be pushed to the
 * directory and the local hub in this case is any kind of directory server.
 *
 * @param int $uid
 * @param boolean $force
 */
function local_dir_update($uid, $force)
{
    logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
    $p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1", intval($uid));
    $profile = array();
    $profile['encoding'] = 'zot';
    if ($p) {
        $hash = $p[0]['channel_hash'];
        $profile['description'] = $p[0]['pdesc'];
        $profile['birthday'] = $p[0]['dob'];
        if ($age = age($p[0]['dob'], $p[0]['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)) {
                        $tags[] = trim($kk);
                    }
                }
            }
            if ($tags) {
                $profile['keywords'] = $tags;
            }
        }
        $hidden = 1 - intval($p[0]['publish']);
        logger('hidden: ' . $hidden);
        $r = q("select xchan_hidden from xchan where xchan_hash = '%s' limit 1", dbesc($p[0]['channel_hash']));
        if (intval($r[0]['xchan_hidden']) != $hidden) {
            $r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'", intval($hidden), dbesc($p[0]['channel_hash']));
        }
        $arr = array('channel_id' => $uid, 'hash' => $hash, 'profile' => $profile);
        call_hooks('local_dir_update', $arr);
        $address = channel_reddress($p[0]);
        if (perm_is_allowed($uid, '', 'view_profile')) {
            import_directory_profile($hash, $arr['profile'], $address, 0);
        } else {
            // they may have made it private
            $r = q("delete from xprof where xprof_hash = '%s'", dbesc($hash));
            $r = q("delete from xtag where xtag_hash = '%s'", dbesc($hash));
        }
    }
    $ud_hash = random_string() . '@' . App::get_hostname();
    update_modtime($hash, $ud_hash, channel_reddress($p[0]), $force ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED);
}
示例#14
0
文件: zot.php 项目: phellmes/hubzilla
function check_zotinfo($channel, $locations, &$ret)
{
    //	logger('locations: ' . print_r($locations,true),LOGGER_DATA, LOG_DEBUG);
    // 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_reddress($channel)), intval(1), 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')), dbesc('zot'));
            if ($r) {
                $x = zot_encode_locations($channel);
                if ($x) {
                    $ret['locations'] = $x;
                }
            } else {
                logger('Unable to store sys hub location');
            }
        }
    }
}
示例#15
0
function get_site_info()
{
    $register_policy = array('REGISTER_CLOSED', 'REGISTER_APPROVE', 'REGISTER_OPEN');
    $directory_mode = array('DIRECTORY_MODE_NORMAL', 'DIRECTORY_MODE_PRIMARY', 'DIRECTORY_MODE_SECONDARY', 256 => 'DIRECTORY_MODE_STANDALONE');
    $sql_extra = '';
    $r = q("select * from channel left join account on account_id = channel_account_id where ( account_roles & 4096 )>0 and account_default_channel = channel_id");
    if ($r) {
        $admin = array();
        foreach ($r as $rr) {
            if ($rr['channel_pageflags'] & PAGE_HUBADMIN) {
                $admin[] = array('name' => $rr['channel_name'], 'address' => channel_reddress($rr), 'channel' => z_root() . '/channel/' . $rr['channel_address']);
            }
        }
        if (!$admin) {
            foreach ($r as $rr) {
                $admin[] = array('name' => $rr['channel_name'], 'address' => channel_reddress($rr), 'channel' => z_root() . '/channel/' . $rr['channel_address']);
            }
        }
    } else {
        $admin = false;
    }
    $def_service_class = get_config('system', 'default_service_class');
    if ($def_service_class) {
        $service_class = get_config('service_class', $def_service_class);
    } else {
        $service_class = false;
    }
    $visible_plugins = visible_plugin_list();
    if (@is_dir('.git') && function_exists('shell_exec')) {
        $commit = trim(@shell_exec('git log -1 --format="%h"'));
    }
    if (!isset($commit) || strlen($commit) > 16) {
        $commit = '';
    }
    $site_info = get_config('system', 'info');
    $site_name = get_config('system', 'sitename');
    if (!get_config('system', 'hidden_version_siteinfo')) {
        $version = Zotlabs\Lib\System::get_project_version();
        $tag = Zotlabs\Lib\System::get_std_version();
        if (@is_dir('.git') && function_exists('shell_exec')) {
            $commit = trim(@shell_exec('git log -1 --format="%h"'));
        }
        if (!isset($commit) || strlen($commit) > 16) {
            $commit = '';
        }
    } else {
        $version = $commit = '';
    }
    //Statistics
    $channels_total_stat = intval(get_config('system', 'channels_total_stat'));
    $channels_active_halfyear_stat = intval(get_config('system', 'channels_active_halfyear_stat'));
    $channels_active_monthly_stat = intval(get_config('system', 'channels_active_monthly_stat'));
    $local_posts_stat = intval(get_config('system', 'local_posts_stat'));
    $hide_in_statistics = intval(get_config('system', 'hide_in_statistics'));
    $site_expire = intval(get_config('system', 'default_expire_days'));
    load_config('feature_lock');
    $locked_features = array();
    if (is_array(App::$config['feature_lock']) && count(App::$config['feature_lock'])) {
        foreach (App::$config['feature_lock'] as $k => $v) {
            if ($k === 'config_loaded') {
                continue;
            }
            $locked_features[$k] = intval($v);
        }
    }
    $data = array('version' => $version, 'version_tag' => $tag, 'server_role' => Zotlabs\Lib\System::get_server_role(), 'commit' => $commit, 'url' => z_root(), 'plugins' => $visible_plugins, 'register_policy' => $register_policy[get_config('system', 'register_policy')], 'invitation_only' => intval(get_config('system', 'invitation_only')), 'directory_mode' => $directory_mode[get_config('system', 'directory_mode')], 'language' => get_config('system', 'language'), 'rss_connections' => intval(get_config('system', 'feed_contacts')), 'expiration' => $site_expire, 'default_service_restrictions' => $service_class, 'locked_features' => $locked_features, 'admin' => $admin, 'site_name' => $site_name ? $site_name : '', 'platform' => Zotlabs\Lib\System::get_platform_name(), 'dbdriver' => DBA::$dba->getdriver(), 'lastpoll' => get_config('system', 'lastpoll'), 'info' => $site_info ? $site_info : '', 'channels_total' => $channels_total_stat, 'channels_active_halfyear' => $channels_active_halfyear_stat, 'channels_active_monthly' => $channels_active_monthly_stat, 'local_posts' => $local_posts_stat, 'hide_in_statistics' => $hide_in_statistics);
    return $data;
}
示例#16
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');
 }
示例#17
0
 /**
  * @brief
  *
  * @param array $params an assoziative array with:
  *  * \e string \b from_xchan sender xchan hash
  *  * \e string \b to_xchan recipient xchan hash
  *  * \e array \b item an assoziative array
  *  * \e int \b type one of the NOTIFY_* constants from boot.php
  *  * \e string \b link
  *  * \e string \b parent_mid
  *  * \e string \b otype
  *  * \e string \b verb
  *  * \e string \b activity
  */
 public static function submit($params)
 {
     logger('notification: entry', LOGGER_DEBUG);
     // throw a small amount of entropy into the system to breakup duplicates arriving at the same precise instant.
     usleep(mt_rand(0, 10000));
     if ($params['from_xchan']) {
         $x = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($params['from_xchan']));
     }
     if ($params['to_xchan']) {
         $y = q("select channel.*, account.* from channel left join account on channel_account_id = account_id\n\t\t\t\twhere channel_hash = '%s' and channel_removed = 0 limit 1", dbesc($params['to_xchan']));
     }
     if ($x & $y) {
         $sender = $x[0];
         $recip = $y[0];
     } else {
         logger('notification: no sender or recipient.');
         logger('sender: ' . $params['from_xchan']);
         logger('recip: ' . $params['to_xchan']);
         return;
     }
     // from here on everything is in the recipients language
     push_lang($recip['account_language']);
     // should probably have a channel language
     $banner = t('$Projectname Notification');
     $product = t('$projectname');
     // PLATFORM_NAME;
     $siteurl = z_root();
     $thanks = t('Thank You,');
     $sitename = get_config('system', 'sitename');
     $site_admin = sprintf(t('%s Administrator'), $sitename);
     $sender_name = $product;
     $hostname = \App::get_hostname();
     if (strpos($hostname, ':')) {
         $hostname = substr($hostname, 0, strpos($hostname, ':'));
     }
     // Do not translate 'noreply' as it must be a legal 7-bit email address
     $reply_email = get_config('system', 'reply_address');
     if (!$reply_email) {
         $reply_email = 'noreply' . '@' . $hostname;
     }
     $sender_email = get_config('system', 'from_email');
     if (!$sender_email) {
         $sender_email = 'Administrator' . '@' . \App::get_hostname();
     }
     $sender_name = get_config('system', 'from_email_name');
     if (!$sender_name) {
         $sender_name = \Zotlabs\Lib\System::get_site_name();
     }
     $additional_mail_header = "";
     if (array_key_exists('item', $params)) {
         require_once 'include/conversation.php';
         // if it's a normal item...
         if (array_key_exists('verb', $params['item'])) {
             // localize_item() alters the original item so make a copy first
             $i = $params['item'];
             logger('calling localize');
             localize_item($i);
             $title = $i['title'];
             $body = $i['body'];
             $private = $i['item_private'] || intval($i['item_obscured']);
         } else {
             $title = $params['item']['title'];
             $body = $params['item']['body'];
         }
     } else {
         $title = $body = '';
     }
     // e.g. "your post", "David's photo", etc.
     $possess_desc = t('%s <!item_type!>');
     if ($params['type'] == NOTIFY_MAIL) {
         logger('notification: mail');
         $subject = sprintf(t('[$Projectname:Notify] New mail received at %s'), $sitename);
         $preamble = sprintf(t('%1$s, %2$s sent you a new private message at %3$s.'), $recip['channel_name'], $sender['xchan_name'], $sitename);
         $epreamble = sprintf(t('%1$s sent you %2$s.'), '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]');
         $sitelink = t('Please visit %s to view and/or reply to your private messages.');
         $tsitelink = sprintf($sitelink, $siteurl . '/mail/' . $params['item']['id']);
         $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '/mail/' . $params['item']['id'] . '">' . $sitename . '</a>');
         $itemlink = $siteurl . '/mail/' . $params['item']['id'];
     }
     if ($params['type'] == NOTIFY_COMMENT) {
         //		logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
         $itemlink = $params['link'];
         // ignore like/unlike activity on posts - they probably require a separate notification preference
         if (array_key_exists('item', $params) && !visible_activity($params['item'])) {
             logger('notification: not a visible activity. Ignoring.');
             pop_lang();
             return;
         }
         $parent_mid = $params['parent_mid'];
         // Check to see if there was already a notify for this post.
         // If so don't create a second notification
         $p = null;
         $p = q("select id from notify where link = '%s' and uid = %d limit 1", dbesc($params['link']), intval($recip['channel_id']));
         if ($p) {
             logger('notification: comment already notified');
             pop_lang();
             return;
         }
         // if it's a post figure out who's post it is.
         $p = null;
         if ($params['otype'] === 'item' && $parent_mid) {
             $p = q("select * from item where mid = '%s' and uid = %d limit 1", dbesc($parent_mid), intval($recip['channel_id']));
         }
         xchan_query($p);
         $item_post_type = item_post_type($p[0]);
         //		$private = $p[0]['item_private'];
         $parent_id = $p[0]['id'];
         $parent_item = $p[0];
         //$possess_desc = str_replace('<!item_type!>',$possess_desc);
         // "a post"
         $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]a %4$s[/zrl]'), $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $itemlink, $item_post_type);
         // "George Bull's post"
         if ($p) {
             $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]%4$s\'s %5$s[/zrl]'), $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $itemlink, $p[0]['author']['xchan_name'], $item_post_type);
         }
         // "your post"
         if ($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall'])) {
             $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]your %4$s[/zrl]'), $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $itemlink, $item_post_type);
         }
         // Some mail softwares relies on subject field for threading.
         // So, we cannot have different subjects for notifications of the same thread.
         // Before this we have the name of the replier on the subject rendering
         // differents subjects for messages on the same thread.
         $subject = sprintf(t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
         $preamble = sprintf(t('%1$s, %2$s commented on an item/conversation you have been following.'), $recip['channel_name'], $sender['xchan_name']);
         $epreamble = $dest_str;
         $sitelink = t('Please visit %s to view and/or reply to the conversation.');
         $tsitelink = sprintf($sitelink, $siteurl);
         $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
     }
     if ($params['type'] == NOTIFY_WALL) {
         $subject = sprintf(t('[$Projectname:Notify] %s posted to your profile wall'), $sender['xchan_name']);
         $preamble = sprintf(t('%1$s, %2$s posted to your profile wall at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
         $epreamble = sprintf(t('%1$s, %2$s posted to [zrl=%3$s]your wall[/zrl]'), $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $params['link']);
         $sitelink = t('Please visit %s to view and/or reply to the conversation.');
         $tsitelink = sprintf($sitelink, $siteurl);
         $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
         $itemlink = $params['link'];
     }
     if ($params['type'] == NOTIFY_TAGSELF) {
         $p = null;
         $p = q("select id from notify where link = '%s' and uid = %d limit 1", dbesc($params['link']), intval($recip['channel_id']));
         if ($p) {
             logger('enotify: tag: already notified about this post');
             pop_lang();
             return;
         }
         $subject = sprintf(t('[$Projectname:Notify] %s tagged you'), $sender['xchan_name']);
         $preamble = sprintf(t('%1$s, %2$s tagged you at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
         $epreamble = sprintf(t('%1$s, %2$s [zrl=%3$s]tagged you[/zrl].'), $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $params['link']);
         $sitelink = t('Please visit %s to view and/or reply to the conversation.');
         $tsitelink = sprintf($sitelink, $siteurl);
         $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
         $itemlink = $params['link'];
     }
     if ($params['type'] == NOTIFY_POKE) {
         $subject = sprintf(t('[$Projectname:Notify] %1$s poked you'), $sender['xchan_name']);
         $preamble = sprintf(t('%1$s, %2$s poked you at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
         $epreamble = sprintf(t('%1$s, %2$s [zrl=%2$s]poked you[/zrl].'), $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $params['link']);
         $subject = str_replace('poked', t($params['activity']), $subject);
         $preamble = str_replace('poked', t($params['activity']), $preamble);
         $epreamble = str_replace('poked', t($params['activity']), $epreamble);
         $sitelink = t('Please visit %s to view and/or reply to the conversation.');
         $tsitelink = sprintf($sitelink, $siteurl);
         $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
         $itemlink = $params['link'];
     }
     if ($params['type'] == NOTIFY_TAGSHARE) {
         $subject = sprintf(t('[$Projectname:Notify] %s tagged your post'), $sender['xchan_name']);
         $preamble = sprintf(t('%1$s, %2$s tagged your post at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
         $epreamble = sprintf(t('%1$s, %2$s tagged [zrl=%3$s]your post[/zrl]'), $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $itemlink);
         $sitelink = t('Please visit %s to view and/or reply to the conversation.');
         $tsitelink = sprintf($sitelink, $siteurl);
         $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
         $itemlink = $params['link'];
     }
     if ($params['type'] == NOTIFY_INTRO) {
         $subject = sprintf(t('[$Projectname:Notify] Introduction received'));
         $preamble = sprintf(t('%1$s, you\'ve received an new connection request from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
         $epreamble = sprintf(t('%1$s, you\'ve received [zrl=%2$s]a new connection request[/zrl] from %3$s.'), $recip['channel_name'], $siteurl . '/connections/ifpending', '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
         $body = sprintf(t('You may visit their profile at %s'), $sender['xchan_url']);
         $sitelink = t('Please visit %s to approve or reject the connection request.');
         $tsitelink = sprintf($sitelink, $siteurl . '/connections/ifpending');
         $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '/connections/ifpending">' . $sitename . '</a>');
         $itemlink = $params['link'];
     }
     if ($params['type'] == NOTIFY_SUGGEST) {
         $subject = sprintf(t('[$Projectname:Notify] Friend suggestion received'));
         $preamble = sprintf(t('%1$s, you\'ve received a friend suggestion from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
         $epreamble = sprintf(t('%1$s, you\'ve received [zrl=%2$s]a friend suggestion[/zrl] for %3$s from %4$s.'), $recip['channel_name'], $itemlink, '[zrl=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/zrl]', '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
         $body = t('Name:') . ' ' . $params['item']['name'] . "\n";
         $body .= t('Photo:') . ' ' . $params['item']['photo'] . "\n";
         $body .= sprintf(t('You may visit their profile at %s'), $params['item']['url']);
         $sitelink = t('Please visit %s to approve or reject the suggestion.');
         $tsitelink = sprintf($sitelink, $siteurl);
         $hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
         $itemlink = $params['link'];
     }
     if ($params['type'] == NOTIFY_CONFIRM) {
         // ?
     }
     if ($params['type'] == NOTIFY_SYSTEM) {
         // ?
     }
     $h = array('params' => $params, 'subject' => $subject, 'preamble' => $preamble, 'epreamble' => $epreamble, 'body' => $body, 'sitelink' => $sitelink, 'sitename' => $sitename, 'tsitelink' => $tsitelink, 'hsitelink' => $hsitelink, 'itemlink' => $itemlink, 'sender' => $sender, 'recipient' => $recip);
     call_hooks('enotify', $h);
     $subject = $h['subject'];
     $preamble = $h['preamble'];
     $epreamble = $h['epreamble'];
     $body = $h['body'];
     $sitelink = $h['sitelink'];
     $tsitelink = $h['tsitelink'];
     $hsitelink = $h['hsitelink'];
     $itemlink = $h['itemlink'];
     require_once 'include/html2bbcode.php';
     do {
         $dups = false;
         $hash = random_string();
         $r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1", dbesc($hash));
         if ($r) {
             $dups = true;
         }
     } while ($dups === true);
     $datarray = array();
     $datarray['hash'] = $hash;
     $datarray['sender_hash'] = $sender['xchan_hash'];
     $datarray['xname'] = $sender['xchan_name'];
     $datarray['url'] = $sender['xchan_url'];
     $datarray['photo'] = $sender['xchan_photo_s'];
     $datarray['created'] = datetime_convert();
     $datarray['aid'] = $recip['channel_account_id'];
     $datarray['uid'] = $recip['channel_id'];
     $datarray['link'] = $itemlink;
     $datarray['parent'] = $parent_mid;
     $datarray['parent_item'] = $parent_item;
     $datarray['ntype'] = $params['type'];
     $datarray['verb'] = $params['verb'];
     $datarray['otype'] = $params['otype'];
     $datarray['abort'] = false;
     $datarray['item'] = $params['item'];
     call_hooks('enotify_store', $datarray);
     if ($datarray['abort']) {
         pop_lang();
         return;
     }
     // create notification entry in DB
     $seen = 0;
     // Mark some notifications as seen right away
     // Note! The notification have to be created, because they are used to send emails
     // So easiest solution to hide them from Notices is to mark them as seen right away.
     // Another option would be to not add them to the DB, and change how emails are handled
     // (probably would be better that way)
     $always_show_in_notices = get_pconfig($recip['channel_id'], 'system', 'always_show_in_notices');
     if (!$always_show_in_notices) {
         if ($params['type'] == NOTIFY_WALL || $params['type'] == NOTIFY_MAIL || $params['type'] == NOTIFY_INTRO) {
             $seen = 1;
         }
     }
     $r = q("insert into notify (hash,xname,url,photo,created,aid,uid,link,parent,seen,ntype,verb,otype)\n\t\tvalues('%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')", dbesc($datarray['hash']), dbesc($datarray['xname']), dbesc($datarray['url']), dbesc($datarray['photo']), dbesc($datarray['created']), intval($datarray['aid']), intval($datarray['uid']), dbesc($datarray['link']), dbesc($datarray['parent']), intval($seen), intval($datarray['ntype']), dbesc($datarray['verb']), dbesc($datarray['otype']));
     $r = q("select id from notify where hash = '%s' and uid = %d limit 1", dbesc($hash), intval($recip['channel_id']));
     if ($r) {
         $notify_id = $r[0]['id'];
     } else {
         logger('notification not found.');
         pop_lang();
         return;
     }
     $itemlink = z_root() . '/notify/view/' . $notify_id;
     $msg = str_replace('$itemlink', $itemlink, $epreamble);
     // wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation
     if ((\App::$language === 'en' || !\App::$language) && strpos($msg, ', ')) {
         $msg = substr($msg, strpos($msg, ', ') + 1);
     }
     $r = q("update notify set msg = '%s' where id = %d and uid = %d", dbesc($msg), intval($notify_id), intval($datarray['uid']));
     // send email notification if notification preferences permit
     require_once 'bbcode.php';
     if (intval($recip['channel_notifyflags']) & intval($params['type']) || $params['type'] == NOTIFY_SYSTEM) {
         logger('notification: sending notification email');
         $hn = get_pconfig($recip['channel_id'], 'system', 'email_notify_host');
         if ($hn && !stristr(\App::get_hostname(), $hn)) {
             // this isn't the email notification host
             pop_lang();
             return;
         }
         $textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r", "\\n"), array("", "\n"), $body))), ENT_QUOTES, 'UTF-8'));
         $htmlversion = bbcode(stripslashes(str_replace(array("\\r", "\\n"), array("", "<br />\n"), $body)));
         // use $_SESSION['zid_override'] to force zid() to use
         // the recipient address instead of the current observer
         $_SESSION['zid_override'] = channel_reddress($recip);
         $_SESSION['zrl_override'] = z_root() . '/channel/' . $recip['channel_address'];
         $textversion = zidify_links($textversion);
         $htmlversion = zidify_links($htmlversion);
         // unset when done to revert to normal behaviour
         unset($_SESSION['zid_override']);
         unset($_SESSION['zrl_override']);
         $datarray = array();
         $datarray['banner'] = $banner;
         $datarray['product'] = $product;
         $datarray['preamble'] = $preamble;
         $datarray['sitename'] = $sitename;
         $datarray['siteurl'] = $siteurl;
         $datarray['type'] = $params['type'];
         $datarray['parent'] = $params['parent_mid'];
         $datarray['source_name'] = $sender['xchan_name'];
         $datarray['source_link'] = $sender['xchan_url'];
         $datarray['source_photo'] = $sender['xchan_photo_s'];
         $datarray['uid'] = $recip['channel_id'];
         $datarray['username'] = $recip['channel_name'];
         $datarray['hsitelink'] = $hsitelink;
         $datarray['tsitelink'] = $tsitelink;
         $datarray['hitemlink'] = '<a href="' . $itemlink . '">' . $itemlink . '</a>';
         $datarray['titemlink'] = $itemlink;
         $datarray['thanks'] = $thanks;
         $datarray['site_admin'] = $site_admin;
         $datarray['title'] = stripslashes($title);
         $datarray['htmlversion'] = $htmlversion;
         $datarray['textversion'] = $textversion;
         $datarray['subject'] = $subject;
         $datarray['headers'] = $additional_mail_header;
         $datarray['email_secure'] = false;
         call_hooks('enotify_mail', $datarray);
         // Default to private - don't disclose message contents over insecure channels (such as email)
         // Might be interesting to use GPG,PGP,S/MIME encryption instead
         // but we'll save that for a clever plugin developer to implement
         $private_activity = false;
         if (!$datarray['email_secure']) {
             switch ($params['type']) {
                 case NOTIFY_WALL:
                 case NOTIFY_TAGSELF:
                 case NOTIFY_POKE:
                 case NOTIFY_COMMENT:
                     if (!$private) {
                         break;
                     }
                     $private_activity = true;
                 case NOTIFY_MAIL:
                     $datarray['textversion'] = $datarray['htmlversion'] = $datarray['title'] = '';
                     $datarray['subject'] = preg_replace('/' . preg_quote(t('[$Projectname:Notify]')) . '/', '$0*', $datarray['subject']);
                     break;
                 default:
                     break;
             }
         }
         if ($private_activity && intval(get_pconfig($datarray['uid'], 'system', 'ignore_private_notifications'))) {
             pop_lang();
             return;
         }
         // load the template for private message notifications
         $tpl = get_markup_template('email_notify_html.tpl');
         $email_html_body = replace_macros($tpl, array('$banner' => $datarray['banner'], '$notify_icon' => \Zotlabs\Lib\System::get_notify_icon(), '$product' => $datarray['product'], '$preamble' => $datarray['preamble'], '$sitename' => $datarray['sitename'], '$siteurl' => $datarray['siteurl'], '$source_name' => $datarray['source_name'], '$source_link' => $datarray['source_link'], '$source_photo' => $datarray['source_photo'], '$username' => $datarray['to_name'], '$hsitelink' => $datarray['hsitelink'], '$hitemlink' => $datarray['hitemlink'], '$thanks' => $datarray['thanks'], '$site_admin' => $datarray['site_admin'], '$title' => $datarray['title'], '$htmlversion' => $datarray['htmlversion']));
         // load the template for private message notifications
         $tpl = get_markup_template('email_notify_text.tpl');
         $email_text_body = replace_macros($tpl, array('$banner' => $datarray['banner'], '$product' => $datarray['product'], '$preamble' => $datarray['preamble'], '$sitename' => $datarray['sitename'], '$siteurl' => $datarray['siteurl'], '$source_name' => $datarray['source_name'], '$source_link' => $datarray['source_link'], '$source_photo' => $datarray['source_photo'], '$username' => $datarray['to_name'], '$tsitelink' => $datarray['tsitelink'], '$titemlink' => $datarray['titemlink'], '$thanks' => $datarray['thanks'], '$site_admin' => $datarray['site_admin'], '$title' => $datarray['title'], '$textversion' => $datarray['textversion']));
         //		logger('text: ' . $email_text_body);
         // use the EmailNotification library to send the message
         self::send(array('fromName' => $sender_name, 'fromEmail' => $sender_email, 'replyTo' => $reply_email, 'toEmail' => $recip['account_email'], 'messageSubject' => $datarray['subject'], 'htmlVersion' => $email_html_body, 'textVersion' => $email_text_body, 'additionalMailHeader' => $datarray['headers']));
     }
     pop_lang();
 }
示例#18
0
function send_message($uid = 0, $recipient = '', $body = '', $subject = '', $replyto = '', $expires = '')
{
    $ret = array('success' => false);
    $is_reply = false;
    $a = get_app();
    $observer_hash = get_observer_hash();
    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 = 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)) {
        $is_reply = true;
        $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_reddress($channel);
        $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 . '@' . 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\\=([0-9]*)x([0-9]*)\\](.*?)\\[\\/zmg\\]/", strpos($body, '[/crypt]') ? $_POST['media_str'] : $body, $match)) {
        $images = $match[3];
    }
    $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, get_observer_hash(), $rev);
            if ($r['success']) {
                $attachments[] = array('href' => z_root() . '/attach/' . $r['data']['hash'], 'length' => $r['data']['filesize'], 'type' => $r['data']['filetype'], 'title' => urlencode($r['data']['filename']), 'revision' => $r['data']['revision']);
            }
            $body = trim(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, mail_isreply )\n\t\tVALUES ( %d, '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d )", 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), intval($is_reply));
    // 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, z_root() . '/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 . '>'));
        }
    }
    Zotlabs\Daemon\Master::Summon(array('Notifier', 'mail', $post_id));
    $ret['success'] = true;
    $ret['message_item'] = intval($post_id);
    $ret['conv'] = $retconv;
    $ret['mail'] = $retmail;
    return $ret;
}