예제 #1
0
function pubsub_init(&$a)
{
    $nick = argc() > 1 ? escape_tags(trim(argv(1))) : '';
    $contact_id = argc() > 2 ? intval(argv(2)) : 0;
    if ($_SERVER['REQUEST_METHOD'] === 'GET') {
        $hub_mode = x($_GET, 'hub_mode') ? notags(trim($_GET['hub_mode'])) : '';
        $hub_topic = x($_GET, 'hub_topic') ? notags(trim($_GET['hub_topic'])) : '';
        $hub_challenge = x($_GET, 'hub_challenge') ? notags(trim($_GET['hub_challenge'])) : '';
        $hub_lease = x($_GET, 'hub_lease_seconds') ? notags(trim($_GET['hub_lease_seconds'])) : '';
        $hub_verify = x($_GET, 'hub_verify_token') ? notags(trim($_GET['hub_verify_token'])) : '';
        logger('pubsub: Subscription from ' . $_SERVER['REMOTE_ADDR']);
        logger('pubsub: data: ' . print_r($_GET, true), LOGGER_DATA);
        $subscribe = $hub_mode === 'subscribe' ? 1 : 0;
        $channel = channelx_by_nick($nick);
        if (!$channel) {
            http_status_exit(404, 'not found.');
        }
        $connections = abook_connections($channel['channel_id'], ' and abook_id = ' . $contact_id);
        if ($connections) {
            $xchan = $connections[0];
        } else {
            logger('connection ' . $contact_id . ' not found.');
            http_status_exit(404, 'not found.');
        }
        if ($hub_verify) {
            $verify = get_abconfig($channel['channel_id'], $xchan['xchan_hash'], 'pubsubhubbub', 'verify_token');
            if ($verify != $hub_verify) {
                logger('hub verification failed.');
                http_status_exit(404, 'not found.');
            }
        }
        $feed_url = z_root() . '/feed/' . $channel['channel_address'];
        if ($hub_topic) {
            if (!link_compare($hub_topic, $feed_url)) {
                logger('hub topic ' . $hub_topic . ' != ' . $feed_url);
                // should abort but let's humour them.
            }
        }
        $contact = $r[0];
        // We must initiate an unsubscribe request with a verify_token.
        // Don't allow outsiders to unsubscribe us.
        if ($hub_mode === 'unsubscribe') {
            if (!strlen($hub_verify)) {
                logger('pubsub: bogus unsubscribe');
                http_status_exit(403, 'permission denied.');
            }
            logger('pubsub: unsubscribe success');
        }
        if ($hub_mode) {
            set_abconfig($channel['channel_id'], $xchan['xchan_hash'], 'pubsubhubbub', 'subscribed', intval($subscribe));
        }
        header($_SERVER["SERVER_PROTOCOL"] . ' 200 ' . 'OK');
        echo $hub_challenge;
        killme();
    }
}
예제 #2
0
 function post()
 {
     $channel = \App::get_channel();
     check_form_security_token_redirectOnErr('/settings/tokens', 'settings_tokens');
     $token_errs = 0;
     if (array_key_exists('token', $_POST)) {
         $atoken_id = $_POST['atoken_id'] ? intval($_POST['atoken_id']) : 0;
         $name = trim(escape_tags($_POST['name']));
         $token = trim($_POST['token']);
         if (!$name || !$token) {
             $token_errs++;
         }
         if (trim($_POST['expires'])) {
             $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_POST['expires']);
         } else {
             $expires = NULL_DATE;
         }
         $max_atokens = service_class_fetch(local_channel(), 'access_tokens');
         if ($max_atokens) {
             $r = q("select count(atoken_id) as total where atoken_uid = %d", intval(local_channel()));
             if ($r && intval($r[0]['total']) >= $max_tokens) {
                 notice(sprintf(t('This channel is limited to %d tokens'), $max_tokens) . EOL);
                 return;
             }
         }
     }
     if ($token_errs) {
         notice(t('Name and Password are required.') . EOL);
         return;
     }
     if ($atoken_id) {
         $r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s' \n\t\t\t\twhere atoken_id = %d and atoken_uid = %d", dbesc($name), dbesc($token), dbesc($expires), intval($atoken_id), intval($channel['channel_id']));
     } else {
         $r = q("insert into atoken ( atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires )\n\t\t\t\tvalues ( %d, %d, '%s', '%s', '%s' ) ", intval($channel['channel_account_id']), intval($channel['channel_id']), dbesc($name), dbesc($token), dbesc($expires));
     }
     $atoken_xchan = substr($channel['channel_hash'], 0, 16) . '.' . $name;
     $all_perms = \Zotlabs\Access\Permissions::Perms();
     if ($all_perms) {
         foreach ($all_perms as $perm => $desc) {
             if (array_key_exists('perms_' . $perm, $_POST)) {
                 set_abconfig($channel['channel_id'], $atoken_xchan, 'my_perms', $perm, intval($_POST['perms_' . $perm]));
             } else {
                 set_abconfig($channel['channel_id'], $atoken_xchan, 'my_perms', $perm, 0);
             }
         }
     }
     info(t('Token saved.') . EOL);
     return;
 }
예제 #3
0
function perm_abook_upgrade($abook)
{
    $x = perms_int_to_array($abook['abook_their_perms']);
    if ($x) {
        foreach ($x as $k => $v) {
            set_abconfig($abook['abook_channel'], $abook['abook_xchan'], 'their_perms', $k, $v);
        }
    }
    $x = perms_int_to_array($abook['abook_my_perms']);
    if ($x) {
        foreach ($x as $k => $v) {
            set_abconfig($abook['abook_channel'], $abook['abook_xchan'], 'my_perms', $k, $v);
        }
    }
}
예제 #4
0
function gnusoc_follow_from_feed(&$a, &$b)
{
    $item = $b['item'];
    $importer = $b['channel'];
    $xchan = $b['xchan'];
    $author = $b['author'];
    $b['caught'] = true;
    logger('follow activity received');
    if ($author && !$xchan) {
        $r = q("select * from xchan where xchan_guid = '%s' limit 1", dbesc($author['author_link']));
        if (!$r) {
            if (discover_by_webbie($author['author_link'])) {
                $r = q("select * from xchan where xchan_guid = '%s' limit 1", dbesc($author['author_link']));
                if (!$r) {
                    logger('discovery failed');
                    return;
                }
            }
            $xchan = $r[0];
        }
        $x = \Zotlabs\Access\PermissionRoles::role_perms('social');
        $their_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']);
        $r = q("select * from abook where abook_channel = %d and abook_xchan = '%s' limit 1", intval($importer['channel_id']), dbesc($xchan['xchan_hash']));
        if ($r) {
            $contact = $r[0];
            $abook_instance = $contact['abook_instance'];
            if ($abook_instance) {
                $abook_instance .= ',';
            }
            $abook_instance .= z_root();
            $r = q("update abook set abook_instance = '%s' where abook_id = %d and abook_channel = %d", dbesc($abook_instance), intval($contact['abook_id']), intval($importer['channel_id']));
            foreach ($their_perms as $k => $v) {
                set_abconfig($importer['channel_id'], $contact['abook_xchan'], 'their_perms', $k, $v);
            }
        } else {
            $role = get_pconfig($importer['channel_id'], 'system', 'permissions_role');
            if ($role) {
                $x = \Zotlabs\Access\PermissionRoles::role_perms($role);
                if ($x['perms_auto']) {
                    $my_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']);
                }
            }
            if (!$my_perms) {
                $my_perms = \Zotlabs\Access\Permissions::FilledAutoperms($importer['channel_id']);
            }
            $closeness = get_pconfig($importer['channel_id'], 'system', 'new_abook_closeness');
            if ($closeness === false) {
                $closeness = 80;
            }
            $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_connected, abook_dob, abook_pending, abook_instance ) values ( %d, %d, '%s', %d, '%s', '%s', '%s', '%s', %d, '%s' )", intval($importer['channel_account_id']), intval($importer['channel_id']), dbesc($xchan['xchan_hash']), intval($closeness), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(NULL_DATE), intval($my_perms ? 0 : 1), dbesc(z_root()));
            if ($r) {
                if ($my_perms) {
                    foreach ($my_perms as $k => $v) {
                        set_abconfig($importer['channel_id'], $xchan['xchan_hash'], 'my_perms', $k, $v);
                    }
                }
                if ($their_perms) {
                    foreach ($their_perms as $k => $v) {
                        set_abconfig($importer['channel_id'], $xchan['xchan_hash'], 'their_perms', $k, $v);
                    }
                }
                logger("New GNU-Social follower received for {$importer['channel_name']}");
                $new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash left join hubloc on hubloc_hash = xchan_hash where abook_channel = %d and abook_xchan = '%s' order by abook_created desc limit 1", intval($importer['channel_id']), dbesc($xchan['xchan_hash']));
                if ($new_connection) {
                    \Zotlabs\Lib\Enotify::submit(array('type' => NOTIFY_INTRO, 'from_xchan' => $xchan['xchan_hash'], 'to_xchan' => $importer['channel_hash'], 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']));
                    if ($default_perms) {
                        // Send back a sharing notification to them
                        $deliver = gnusoc_remote_follow($importer, $new_connection[0]);
                        if ($deliver) {
                            Zotlabs\Daemon\Master::Summon(array('Deliver', $deliver));
                        }
                    }
                    $clone = array();
                    foreach ($new_connection[0] as $k => $v) {
                        if (strpos($k, 'abook_') === 0) {
                            $clone[$k] = $v;
                        }
                    }
                    unset($clone['abook_id']);
                    unset($clone['abook_account']);
                    unset($clone['abook_channel']);
                    $abconfig = load_abconfig($importer['channel_id'], $clone['abook_xchan']);
                    if ($abconfig) {
                        $clone['abconfig'] = $abconfig;
                    }
                    build_sync_packet($importer['channel_id'], array('abook' => array($clone)));
                }
            }
        }
        return;
    }
}
예제 #5
0
function new_contact($uid, $url, $channel, $interactive = false, $confirm = false)
{
    $result = array('success' => false, 'message' => '');
    $is_red = false;
    $is_http = strpos($url, '://') !== false ? true : false;
    if ($is_http && substr($url, -1, 1) === '/') {
        $url = substr($url, 0, -1);
    }
    if (!allowed_url($url)) {
        $result['message'] = t('Channel is blocked on this site.');
        return $result;
    }
    if (!$url) {
        $result['message'] = t('Channel location missing.');
        return $result;
    }
    // check service class limits
    $r = q("select count(*) as total from abook where abook_channel = %d and abook_self = 0 ", intval($uid));
    if ($r) {
        $total_channels = $r[0]['total'];
    }
    if (!service_class_allows($uid, 'total_channels', $total_channels)) {
        $result['message'] = upgrade_message();
        return $result;
    }
    $arr = array('url' => $url, 'channel' => array());
    call_hooks('follow', $arr);
    if ($arr['channel']['success']) {
        $ret = $arr['channel'];
    } elseif (!$is_http) {
        $ret = Zotlabs\Zot\Finger::run($url, $channel);
    }
    if ($ret && is_array($ret) && $ret['success']) {
        $is_red = true;
        $j = $ret;
    }
    $my_perms = get_channel_default_perms($uid);
    $role = get_pconfig($uid, 'system', 'permissions_role');
    if ($role) {
        $x = \Zotlabs\Access\PermissionRoles::role_perms($role);
        if ($x['perms_connect']) {
            $my_perms = $x['perms_connect'];
        }
    }
    if ($is_red && $j) {
        logger('follow: ' . $url . ' ' . print_r($j, true), LOGGER_DEBUG);
        if (!($j['success'] && $j['guid'])) {
            $result['message'] = t('Response from remote channel was incomplete.');
            logger('mod_follow: ' . $result['message']);
            return $result;
        }
        // Premium channel, set confirm before callback to avoid recursion
        if (array_key_exists('connect_url', $j) && $interactive && !$confirm) {
            goaway(zid($j['connect_url']));
        }
        // do we have an xchan and hubloc?
        // If not, create them.
        $x = import_xchan($j);
        if (array_key_exists('deleted', $j) && intval($j['deleted'])) {
            $result['message'] = t('Channel was deleted and no longer exists.');
            return $result;
        }
        if (!$x['success']) {
            return $x;
        }
        $xchan_hash = $x['hash'];
        if (array_key_exists('permissions', $j) && array_key_exists('data', $j['permissions'])) {
            $permissions = crypto_unencapsulate(array('data' => $j['permissions']['data'], 'key' => $j['permissions']['key'], 'iv' => $j['permissions']['iv']), $channel['channel_prvkey']);
            if ($permissions) {
                $permissions = json_decode($permissions, true);
            }
            logger('decrypted permissions: ' . print_r($permissions, true), LOGGER_DATA);
        } else {
            $permissions = $j['permissions'];
        }
        if (is_array($permissions) && $permissions) {
            foreach ($permissions as $k => $v) {
                set_abconfig($channel['channel_uid'], $xchan_hash, 'their_perms', $k, intval($v));
            }
        }
    } else {
        $xchan_hash = '';
        $r = q("select * from xchan where xchan_hash = '%s' or xchan_url = '%s' limit 1", dbesc($url), dbesc($url));
        if (!$r) {
            // attempt network auto-discovery
            $d = discover_by_webbie($url);
            if (!$d && $is_http) {
                // try RSS discovery
                if (get_config('system', 'feed_contacts')) {
                    $d = discover_by_url($url);
                } else {
                    $result['message'] = t('Protocol disabled.');
                    return $result;
                }
            }
            if ($d) {
                $r = q("select * from xchan where xchan_hash = '%s' or xchan_url = '%s' limit 1", dbesc($url), dbesc($url));
            }
        }
        // if discovery was a success we should have an xchan record in $r
        if ($r) {
            $xchan = $r[0];
            $xchan_hash = $r[0]['xchan_hash'];
            $their_perms = 0;
        }
    }
    if (!$xchan_hash) {
        $result['message'] = t('Channel discovery failed.');
        logger('follow: ' . $result['message']);
        return $result;
    }
    $allowed = $is_red || $r[0]['xchan_network'] === 'rss' ? 1 : 0;
    $x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => $allowed, 'singleton' => 0);
    call_hooks('follow_allow', $x);
    if (!$x['allowed']) {
        $result['message'] = t('Protocol disabled.');
        return $result;
    }
    $singleton = intval($x['singleton']);
    $aid = $channel['channel_account_id'];
    $hash = get_observer_hash();
    $default_group = $channel['channel_default_group'];
    if ($xchan['xchan_network'] === 'rss') {
        // check service class feed limits
        $r = q("select count(*) as total from abook where abook_account = %d and abook_feed = 1 ", intval($aid));
        if ($r) {
            $total_feeds = $r[0]['total'];
        }
        if (!service_class_allows($uid, 'total_feeds', $total_feeds)) {
            $result['message'] = upgrade_message();
            return $result;
        }
    }
    if ($hash == $xchan_hash) {
        $result['message'] = t('Cannot connect to yourself.');
        return $result;
    }
    $r = q("select abook_xchan, abook_instance from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc($xchan_hash), intval($uid));
    if ($is_http) {
        // Always set these "remote" permissions for feeds since we cannot interact with them
        // to negotiate a suitable permission response
        set_abconfig($uid, $xchan_hash, 'their_perms', 'view_stream', 1);
        set_abconfig($uid, $xchan_hash, 'their_perms', 'republish', 1);
    }
    if ($r) {
        $abook_instance = $r[0]['abook_instance'];
        if ($singleton && strpos($abook_instance, z_root()) === false) {
            if ($abook_instance) {
                $abook_instance .= ',';
            }
            $abook_instance .= z_root();
        }
        $x = q("update abook set abook_instance = '%s' where abook_id = %d", dbesc($abook_instance), intval($r[0]['abook_id']));
    } else {
        $closeness = get_pconfig($uid, 'system', 'new_abook_closeness');
        if ($closeness === false) {
            $closeness = 80;
        }
        $r = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_feed, abook_created, abook_updated, abook_instance )\n\t\t\tvalues( %d, %d, %d, '%s', %d, '%s', '%s', '%s' ) ", intval($aid), intval($uid), intval($closeness), dbesc($xchan_hash), intval($is_http ? 1 : 0), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($singleton ? z_root() : ''));
    }
    if (!$r) {
        logger('mod_follow: abook creation failed');
    }
    $all_perms = \Zotlabs\Access\Permissions::Perms();
    if ($all_perms) {
        foreach ($all_perms as $k => $v) {
            if (in_array($k, $my_perms)) {
                set_abconfig($uid, $xchan_hash, 'my_perms', $k, 1);
            } else {
                set_abconfig($uid, $xchan_hash, 'my_perms', $k, 0);
            }
        }
    }
    $r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash \n\t\twhere abook_xchan = '%s' and abook_channel = %d limit 1", dbesc($xchan_hash), intval($uid));
    if ($r) {
        $result['abook'] = $r[0];
        Zotlabs\Daemon\Master::Summon(array('Notifier', 'permission_create', $result['abook']['abook_id']));
    }
    $arr = array('channel_id' => $uid, 'channel' => $channel, 'abook' => $result['abook']);
    call_hooks('follow', $arr);
    /** If there is a default group for this channel, add this connection to it */
    if ($default_group) {
        require_once 'include/group.php';
        $g = group_rec_byhash($uid, $default_group);
        if ($g) {
            group_add_member($uid, '', $xchan_hash, $g['id']);
        }
    }
    $result['success'] = true;
    return $result;
}
예제 #6
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');
 }
예제 #7
0
 function post()
 {
     $channel = \App::get_channel();
     check_form_security_token_redirectOnErr('/settings', 'settings');
     call_hooks('settings_post', $_POST);
     $set_perms = '';
     $role = x($_POST, 'permissions_role') ? notags(trim($_POST['permissions_role'])) : '';
     $oldrole = get_pconfig(local_channel(), 'system', 'permissions_role');
     if ($role != $oldrole || $role === 'custom') {
         if ($role === 'custom') {
             $hide_presence = x($_POST, 'hide_presence') && intval($_POST['hide_presence']) == 1 ? 1 : 0;
             $publish = x($_POST, 'profile_in_directory') && intval($_POST['profile_in_directory']) == 1 ? 1 : 0;
             $def_group = x($_POST, 'group-selection') ? notags(trim($_POST['group-selection'])) : '';
             $r = q("update channel set channel_default_group = '%s' where channel_id = %d", dbesc($def_group), intval(local_channel()));
             $global_perms = \Zotlabs\Access\Permissions::Perms();
             foreach ($global_perms as $k => $v) {
                 \Zotlabs\Access\PermissionLimits::Set(local_channel(), $k, intval($_POST[$k]));
             }
             $acl = new \Zotlabs\Access\AccessList($channel);
             $acl->set_from_array($_POST);
             $x = $acl->get();
             $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s', \n\t\t\t\t\tchannel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d", dbesc($x['allow_cid']), dbesc($x['allow_gid']), dbesc($x['deny_cid']), dbesc($x['deny_gid']), intval(local_channel()));
         } else {
             $role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($_POST['permissions_role']);
             if (!$role_permissions) {
                 notice('Permissions category could not be found.');
                 return;
             }
             $hide_presence = 1 - intval($role_permissions['online']);
             if ($role_permissions['default_collection']) {
                 $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc(t('Friends')));
                 if (!$r) {
                     require_once 'include/group.php';
                     group_add(local_channel(), t('Friends'));
                     group_add_member(local_channel(), t('Friends'), $channel['channel_hash']);
                     $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc(t('Friends')));
                 }
                 if ($r) {
                     q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d", dbesc($r[0]['hash']), dbesc('<' . $r[0]['hash'] . '>'), intval(local_channel()));
                 } else {
                     notice(sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL);
                     return;
                 }
             } else {
                 q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '', \n\t\t\t\t\t\tchannel_deny_cid = '' where channel_id = %d", intval(local_channel()));
             }
             $x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']);
             foreach ($x as $k => $v) {
                 set_abconfig(local_channel(), $channel['channel_hash'], 'my_perms', $k, $v);
                 if ($role_permissions['perms_auto']) {
                     set_pconfig(local_channel(), 'autoperms', $k, $v);
                 } else {
                     del_pconfig(local_channel(), 'autoperms', $k);
                 }
             }
             if ($role_permissions['limits']) {
                 foreach ($role_permissions['limits'] as $k => $v) {
                     \Zotlabs\Access\PermissionLimits::Set(local_channel(), $k, $v);
                 }
             }
             if (array_key_exists('directory_publish', $role_permissions)) {
                 $publish = intval($role_permissions['directory_publish']);
             }
         }
         set_pconfig(local_channel(), 'system', 'hide_online_status', $hide_presence);
         set_pconfig(local_channel(), 'system', 'permissions_role', $role);
     }
     $username = x($_POST, 'username') ? notags(trim($_POST['username'])) : '';
     $timezone = x($_POST, 'timezone_select') ? notags(trim($_POST['timezone_select'])) : '';
     $defloc = x($_POST, 'defloc') ? notags(trim($_POST['defloc'])) : '';
     $openid = x($_POST, 'openid_url') ? notags(trim($_POST['openid_url'])) : '';
     $maxreq = x($_POST, 'maxreq') ? intval($_POST['maxreq']) : 0;
     $expire = x($_POST, 'expire') ? intval($_POST['expire']) : 0;
     $evdays = x($_POST, 'evdays') ? intval($_POST['evdays']) : 3;
     $photo_path = x($_POST, 'photo_path') ? escape_tags(trim($_POST['photo_path'])) : '';
     $attach_path = x($_POST, 'attach_path') ? escape_tags(trim($_POST['attach_path'])) : '';
     $channel_menu = x($_POST['channel_menu']) ? htmlspecialchars_decode(trim($_POST['channel_menu']), ENT_QUOTES) : '';
     $expire_items = x($_POST, 'expire_items') ? intval($_POST['expire_items']) : 0;
     $expire_starred = x($_POST, 'expire_starred') ? intval($_POST['expire_starred']) : 0;
     $expire_photos = x($_POST, 'expire_photos') ? intval($_POST['expire_photos']) : 0;
     $expire_network_only = x($_POST, 'expire_network_only') ? intval($_POST['expire_network_only']) : 0;
     $allow_location = x($_POST, 'allow_location') && intval($_POST['allow_location']) == 1 ? 1 : 0;
     $blocktags = x($_POST, 'blocktags') && intval($_POST['blocktags']) == 1 ? 0 : 1;
     // this setting is inverted!
     $unkmail = x($_POST, 'unkmail') && intval($_POST['unkmail']) == 1 ? 1 : 0;
     $cntunkmail = x($_POST, 'cntunkmail') ? intval($_POST['cntunkmail']) : 0;
     $suggestme = x($_POST, 'suggestme') ? intval($_POST['suggestme']) : 0;
     $post_newfriend = $_POST['post_newfriend'] == 1 ? 1 : 0;
     $post_joingroup = $_POST['post_joingroup'] == 1 ? 1 : 0;
     $post_profilechange = $_POST['post_profilechange'] == 1 ? 1 : 0;
     $adult = $_POST['adult'] == 1 ? 1 : 0;
     $cal_first_day = x($_POST, 'first_day') && intval($_POST['first_day']) == 1 ? 1 : 0;
     $pageflags = $channel['channel_pageflags'];
     $existing_adult = $pageflags & PAGE_ADULT ? 1 : 0;
     if ($adult != $existing_adult) {
         $pageflags = $pageflags ^ PAGE_ADULT;
     }
     $notify = 0;
     if (x($_POST, 'notify1')) {
         $notify += intval($_POST['notify1']);
     }
     if (x($_POST, 'notify2')) {
         $notify += intval($_POST['notify2']);
     }
     if (x($_POST, 'notify3')) {
         $notify += intval($_POST['notify3']);
     }
     if (x($_POST, 'notify4')) {
         $notify += intval($_POST['notify4']);
     }
     if (x($_POST, 'notify5')) {
         $notify += intval($_POST['notify5']);
     }
     if (x($_POST, 'notify6')) {
         $notify += intval($_POST['notify6']);
     }
     if (x($_POST, 'notify7')) {
         $notify += intval($_POST['notify7']);
     }
     if (x($_POST, 'notify8')) {
         $notify += intval($_POST['notify8']);
     }
     $vnotify = 0;
     if (x($_POST, 'vnotify1')) {
         $vnotify += intval($_POST['vnotify1']);
     }
     if (x($_POST, 'vnotify2')) {
         $vnotify += intval($_POST['vnotify2']);
     }
     if (x($_POST, 'vnotify3')) {
         $vnotify += intval($_POST['vnotify3']);
     }
     if (x($_POST, 'vnotify4')) {
         $vnotify += intval($_POST['vnotify4']);
     }
     if (x($_POST, 'vnotify5')) {
         $vnotify += intval($_POST['vnotify5']);
     }
     if (x($_POST, 'vnotify6')) {
         $vnotify += intval($_POST['vnotify6']);
     }
     if (x($_POST, 'vnotify7')) {
         $vnotify += intval($_POST['vnotify7']);
     }
     if (x($_POST, 'vnotify8')) {
         $vnotify += intval($_POST['vnotify8']);
     }
     if (x($_POST, 'vnotify9')) {
         $vnotify += intval($_POST['vnotify9']);
     }
     if (x($_POST, 'vnotify10')) {
         $vnotify += intval($_POST['vnotify10']);
     }
     if (x($_POST, 'vnotify11')) {
         $vnotify += intval($_POST['vnotify11']);
     }
     $always_show_in_notices = x($_POST, 'always_show_in_notices') ? 1 : 0;
     $err = '';
     $name_change = false;
     if ($username != $channel['channel_name']) {
         $name_change = true;
         require_once 'include/channel.php';
         $err = validate_channelname($username);
         if ($err) {
             notice($err);
             return;
         }
     }
     if ($timezone != $channel['channel_timezone']) {
         if (strlen($timezone)) {
             date_default_timezone_set($timezone);
         }
     }
     set_pconfig(local_channel(), 'system', 'use_browser_location', $allow_location);
     set_pconfig(local_channel(), 'system', 'suggestme', $suggestme);
     set_pconfig(local_channel(), 'system', 'post_newfriend', $post_newfriend);
     set_pconfig(local_channel(), 'system', 'post_joingroup', $post_joingroup);
     set_pconfig(local_channel(), 'system', 'post_profilechange', $post_profilechange);
     set_pconfig(local_channel(), 'system', 'blocktags', $blocktags);
     set_pconfig(local_channel(), 'system', 'channel_menu', $channel_menu);
     set_pconfig(local_channel(), 'system', 'vnotify', $vnotify);
     set_pconfig(local_channel(), 'system', 'always_show_in_notices', $always_show_in_notices);
     set_pconfig(local_channel(), 'system', 'evdays', $evdays);
     set_pconfig(local_channel(), 'system', 'photo_path', $photo_path);
     set_pconfig(local_channel(), 'system', 'attach_path', $attach_path);
     set_pconfig(local_channel(), 'system', 'cal_first_day', $cal_first_day);
     $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d {$set_perms} where channel_id = %d", dbesc($username), intval($pageflags), dbesc($timezone), dbesc($defloc), intval($notify), intval($unkmail), intval($maxreq), intval($expire), intval(local_channel()));
     if ($r) {
         info(t('Settings updated.') . EOL);
     }
     if (!is_null($publish)) {
         $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d", intval($publish), intval(local_channel()));
     }
     if ($name_change) {
         $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'", dbesc($username), dbesc(datetime_convert()), dbesc($channel['channel_hash']));
         $r = q("update profile set fullname = '%s' where uid = %d and is_default = 1", dbesc($username), intval($channel['channel_id']));
     }
     \Zotlabs\Daemon\Master::Summon(array('Directory', local_channel()));
     build_sync_packet();
     if ($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) {
         // FIXME - set to un-verified, blocked and redirect to logout
         // Why? Are we verifying people or email addresses?
     }
     goaway(z_root() . '/settings');
     return;
     // NOTREACHED
 }
예제 #8
0
/**
 * @brief Create a new channel.
 *
 * Also creates the related xchan, hubloc, profile, and "self" abook records,
 * and an empty "Friends" group/collection for the new channel.
 *
 * @param array $arr assoziative array with:
 *  * \e string \b name full name of channel
 *  * \e string \b nickname "email/url-compliant" nickname
 *  * \e int \b account_id to attach with this channel
 *  * [other identity fields as desired]
 *
 * @returns array
 *     'success' => boolean true or false
 *     'message' => optional error text if success is false
 *     'channel' => if successful the created channel array
 */
function create_identity($arr)
{
    $ret = array('success' => false);
    if (!$arr['account_id']) {
        $ret['message'] = t('No account identifier');
        return $ret;
    }
    $ret = identity_check_service_class($arr['account_id']);
    if (!$ret['success']) {
        return $ret;
    }
    // save this for auto_friending
    $total_identities = $ret['total_identities'];
    $nick = mb_strtolower(trim($arr['nickname']));
    if (!$nick) {
        $ret['message'] = t('Nickname is required.');
        return $ret;
    }
    $name = escape_tags($arr['name']);
    $pageflags = x($arr, 'pageflags') ? intval($arr['pageflags']) : PAGE_NORMAL;
    $system = x($arr, 'system') ? intval($arr['system']) : 0;
    $name_error = validate_channelname($arr['name']);
    if ($name_error) {
        $ret['message'] = $name_error;
        return $ret;
    }
    if ($nick === 'sys' && !$system) {
        $ret['message'] = t('Reserved nickname. Please choose another.');
        return $ret;
    }
    if (check_webbie(array($nick)) !== $nick) {
        $ret['message'] = t('Nickname has unsupported characters or is already being used on this site.');
        return $ret;
    }
    $guid = zot_new_uid($nick);
    $key = new_keypair(4096);
    $sig = base64url_encode(rsa_sign($guid, $key['prvkey']));
    $hash = make_xchan_hash($guid, $sig);
    // Force a few things on the short term until we can provide a theme or app with choice
    $publish = 1;
    if (array_key_exists('publish', $arr)) {
        $publish = intval($arr['publish']);
    }
    $role_permissions = null;
    if (array_key_exists('permissions_role', $arr) && $arr['permissions_role']) {
        $role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($arr['permissions_role']);
    }
    if ($role_permissions && array_key_exists('directory_publish', $role_permissions)) {
        $publish = intval($role_permissions['directory_publish']);
    }
    $primary = true;
    if (array_key_exists('primary', $arr)) {
        $primary = intval($arr['primary']);
    }
    $expire = 0;
    $r = q("insert into channel ( channel_account_id, channel_primary, \n\t\tchannel_name, channel_address, channel_guid, channel_guid_sig,\n\t\tchannel_hash, channel_prvkey, channel_pubkey, channel_pageflags, channel_system, channel_expire_days, channel_timezone )\n\t\tvalues ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s' ) ", intval($arr['account_id']), intval($primary), dbesc($name), dbesc($nick), dbesc($guid), dbesc($sig), dbesc($hash), dbesc($key['prvkey']), dbesc($key['pubkey']), intval($pageflags), intval($system), intval($expire), dbesc(App::$timezone));
    $r = q("select * from channel where channel_account_id = %d \n\t\tand channel_guid = '%s' limit 1", intval($arr['account_id']), dbesc($guid));
    if (!$r) {
        $ret['message'] = t('Unable to retrieve created identity');
        return $ret;
    }
    if ($role_permissions && array_key_exists('limits', $role_permissions)) {
        $perm_limits = $role_permissions['limits'];
    } else {
        $perm_limits = site_default_perms();
    }
    foreach ($perm_limits as $p => $v) {
        \Zotlabs\Access\PermissionLimits::Set($r[0]['channel_id'], $p, $v);
    }
    if ($role_permissions && array_key_exists('perms_auto', $role_permissions)) {
        set_pconfig($r[0]['channel_id'], 'system', 'autoperms', intval($role_permissions['perms_auto']));
    }
    $ret['channel'] = $r[0];
    if (intval($arr['account_id'])) {
        set_default_login_identity($arr['account_id'], $ret['channel']['channel_id'], false);
    }
    // Create a verified hub location pointing to this site.
    $r = q("insert into hubloc ( hubloc_guid, hubloc_guid_sig, hubloc_hash, hubloc_addr, hubloc_primary, \n\t\thubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey, hubloc_network )\n\t\tvalues ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )", dbesc($guid), dbesc($sig), dbesc($hash), dbesc(channel_reddress($ret['channel'])), intval($primary), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(), $ret['channel']['channel_prvkey']))), dbesc(App::get_hostname()), dbesc(z_root() . '/post'), dbesc(get_config('system', 'pubkey')), dbesc('zot'));
    if (!$r) {
        logger('create_identity: Unable to store hub location');
    }
    $newuid = $ret['channel']['channel_id'];
    $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_system ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)", dbesc($hash), dbesc($guid), dbesc($sig), dbesc($key['pubkey']), dbesc(z_root() . "/photo/profile/l/{$newuid}"), dbesc(z_root() . "/photo/profile/m/{$newuid}"), dbesc(z_root() . "/photo/profile/s/{$newuid}"), dbesc(channel_reddress($ret['channel'])), dbesc(z_root() . '/channel/' . $ret['channel']['channel_address']), dbesc(z_root() . '/follow?f=&url=%s'), dbesc(z_root() . '/poco/' . $ret['channel']['channel_address']), dbesc($ret['channel']['channel_name']), dbesc('zot'), dbesc(datetime_convert()), dbesc(datetime_convert()), intval($system));
    // Not checking return value.
    // It's ok for this to fail if it's an imported channel, and therefore the hash is a duplicate
    $r = q("INSERT INTO profile ( aid, uid, profile_guid, profile_name, is_default, publish, fullname, photo, thumb)\n\t\tVALUES ( %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s') ", intval($ret['channel']['channel_account_id']), intval($newuid), dbesc(random_string()), t('Default Profile'), 1, $publish, dbesc($ret['channel']['channel_name']), dbesc(z_root() . "/photo/profile/l/{$newuid}"), dbesc(z_root() . "/photo/profile/m/{$newuid}"));
    if ($role_permissions) {
        $myperms = array_key_exists('perms_connect', $role_permissions) ? $role_permissions['perms_connect'] : array();
    } else {
        $x = \Zotlabs\Access\PermissionRoles::role_perms('social');
        $myperms = $x['perms_connect'];
    }
    $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_self )\n\t\tvalues ( %d, %d, '%s', %d, '%s', '%s', %d ) ", intval($ret['channel']['channel_account_id']), intval($newuid), dbesc($hash), intval(0), dbesc(datetime_convert()), dbesc(datetime_convert()), intval(1));
    $x = \Zotlabs\Access\Permissions::FilledPerms($myperms);
    foreach ($x as $k => $v) {
        set_abconfig($newuid, $hash, 'my_perms', $k, $v);
    }
    if (intval($ret['channel']['channel_account_id'])) {
        // Save our permissions role so we can perhaps call it up and modify it later.
        if ($role_permissions) {
            set_pconfig($newuid, 'system', 'permissions_role', $arr['permissions_role']);
            if (array_key_exists('online', $role_permissions)) {
                set_pconfig($newuid, 'system', 'hide_presence', 1 - intval($role_permissions['online']));
            }
            if (array_key_exists('perms_auto', $role_permissions)) {
                $autoperms = intval($role_permissions['perms_auto']);
                set_pconfig($newuid, 'system', 'autoperms', $autoperms);
                if ($autoperms) {
                    $x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']);
                    foreach ($x as $k => $v) {
                        set_pconfig($newuid, 'autoperms', $k, $v);
                    }
                } else {
                    $r = q("delete from pconfig where uid = %d and cat = 'autoperms'", intval($newuid));
                }
            }
        }
        // Create a group with yourself as a member. This allows somebody to use it
        // right away as a default group for new contacts.
        require_once 'include/group.php';
        group_add($newuid, t('Friends'));
        group_add_member($newuid, t('Friends'), $ret['channel']['channel_hash']);
        // if our role_permissions indicate that we're using a default collection ACL, add it.
        if (is_array($role_permissions) && $role_permissions['default_collection']) {
            $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval($newuid), dbesc(t('Friends')));
            if ($r) {
                q("update channel set channel_default_group = '%s', channel_allow_gid = '%s' where channel_id = %d", dbesc($r[0]['hash']), dbesc('<' . $r[0]['hash'] . '>'), intval($newuid));
            }
        }
        if (!$system) {
            set_pconfig($ret['channel']['channel_id'], 'system', 'photo_path', '%Y-%m');
            set_pconfig($ret['channel']['channel_id'], 'system', 'attach_path', '%Y-%m');
        }
        // auto-follow any of the hub's pre-configured channel choices.
        // Only do this if it's the first channel for this account;
        // otherwise it could get annoying. Don't make this list too big
        // or it will impact registration time.
        $accts = get_config('system', 'auto_follow');
        if ($accts && !$total_identities) {
            require_once 'include/follow.php';
            if (!is_array($accts)) {
                $accts = array($accts);
            }
            foreach ($accts as $acct) {
                if (trim($acct)) {
                    new_contact($newuid, trim($acct), $ret['channel'], false);
                }
            }
        }
        call_hooks('create_identity', $newuid);
        Zotlabs\Daemon\Master::Summon(array('Directory', $ret['channel']['channel_id']));
    }
    $ret['success'] = true;
    return $ret;
}
예제 #9
0
/**
 * @brief
 *
 * @param array $sender
 * @param array $arr
 * @param array $deliveries
 * @return array
 */
function process_channel_sync_delivery($sender, $arr, $deliveries)
{
    if (UNO) {
        return;
    }
    require_once 'include/import.php';
    /** @FIXME this will sync red structures (channel, pconfig and abook). Eventually we need to make this application agnostic. */
    $result = array();
    foreach ($deliveries as $d) {
        $r = q("select * from channel where channel_hash = '%s' limit 1", dbesc($d['hash']));
        if (!$r) {
            $result[] = array($d['hash'], 'not found');
            continue;
        }
        $channel = $r[0];
        $max_friends = service_class_fetch($channel['channel_id'], 'total_channels');
        $max_feeds = account_service_class_fetch($channel['channel_account_id'], 'total_feeds');
        if ($channel['channel_hash'] != $sender['hash']) {
            logger('process_channel_sync_delivery: possible forgery. Sender ' . $sender['hash'] . ' is not ' . $channel['channel_hash']);
            $result[] = array($d['hash'], 'channel mismatch', $channel['channel_name'], '');
            continue;
        }
        if (array_key_exists('config', $arr) && is_array($arr['config']) && count($arr['config'])) {
            foreach ($arr['config'] as $cat => $k) {
                foreach ($arr['config'][$cat] as $k => $v) {
                    set_pconfig($channel['channel_id'], $cat, $k, $v);
                }
            }
        }
        if (array_key_exists('obj', $arr) && $arr['obj']) {
            sync_objs($channel, $arr['obj']);
        }
        if (array_key_exists('likes', $arr) && $arr['likes']) {
            import_likes($channel, $arr['likes']);
        }
        if (array_key_exists('app', $arr) && $arr['app']) {
            sync_apps($channel, $arr['app']);
        }
        if (array_key_exists('chatroom', $arr) && $arr['chatroom']) {
            sync_chatrooms($channel, $arr['chatroom']);
        }
        if (array_key_exists('conv', $arr) && $arr['conv']) {
            import_conv($channel, $arr['conv']);
        }
        if (array_key_exists('mail', $arr) && $arr['mail']) {
            sync_mail($channel, $arr['mail']);
        }
        if (array_key_exists('event', $arr) && $arr['event']) {
            sync_events($channel, $arr['event']);
        }
        if (array_key_exists('event_item', $arr) && $arr['event_item']) {
            sync_items($channel, $arr['event_item'], array_key_exists('relocate', $arr) ? $arr['relocate'] : null);
        }
        if (array_key_exists('item', $arr) && $arr['item']) {
            sync_items($channel, $arr['item'], array_key_exists('relocate', $arr) ? $arr['relocate'] : null);
        }
        // deprecated, maintaining for a few months for upward compatibility
        // this should sync webpages, but the logic is a bit subtle
        if (array_key_exists('item_id', $arr) && $arr['item_id']) {
            sync_items($channel, $arr['item_id']);
        }
        if (array_key_exists('menu', $arr) && $arr['menu']) {
            sync_menus($channel, $arr['menu']);
        }
        if (array_key_exists('file', $arr) && $arr['file']) {
            sync_files($channel, $arr['file']);
        }
        if (array_key_exists('channel', $arr) && is_array($arr['channel']) && count($arr['channel'])) {
            if (array_key_exists('channel_pageflags', $arr['channel']) && intval($arr['channel']['channel_pageflags'])) {
                // These flags cannot be sync'd.
                // remove the bits from the incoming flags.
                // These correspond to PAGE_REMOVED and PAGE_SYSTEM on redmatrix
                if ($arr['channel']['channel_pageflags'] & 0x8000) {
                    $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] - 0x8000;
                }
                if ($arr['channel']['channel_pageflags'] & 0x1000) {
                    $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] - 0x1000;
                }
            }
            $disallowed = array('channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey', 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted', 'channel_system');
            $clean = array();
            foreach ($arr['channel'] as $k => $v) {
                if (in_array($k, $disallowed)) {
                    continue;
                }
                $clean[$k] = $v;
            }
            if (count($clean)) {
                foreach ($clean as $k => $v) {
                    $r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) . "' where channel_id = " . intval($channel['channel_id']));
                }
            }
        }
        if (array_key_exists('abook', $arr) && is_array($arr['abook']) && count($arr['abook'])) {
            $total_friends = 0;
            $total_feeds = 0;
            $r = q("select abook_id, abook_feed from abook where abook_channel = %d", intval($channel['channel_id']));
            if ($r) {
                // don't count yourself
                $total_friends = count($r) > 0 ? count($r) - 1 : 0;
                foreach ($r as $rr) {
                    if (intval($rr['abook_feed'])) {
                        $total_feeds++;
                    }
                }
            }
            $disallowed = array('abook_id', 'abook_account', 'abook_channel', 'abook_rating', 'abook_rating_text');
            foreach ($arr['abook'] as $abook) {
                $abconfig = null;
                if (array_key_exists('abconfig', $abook) && is_array($abook['abconfig']) && count($abook['abconfig'])) {
                    $abconfig = $abook['abconfig'];
                }
                if (!array_key_exists('abook_blocked', $abook)) {
                    // convert from redmatrix
                    $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;
                }
                $clean = array();
                if ($abook['abook_xchan'] && $abook['entry_deleted']) {
                    logger('process_channel_sync_delivery: removing abook entry for ' . $abook['abook_xchan']);
                    $r = q("select abook_id, abook_feed from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", dbesc($abook['abook_xchan']), intval($channel['channel_id']));
                    if ($r) {
                        contact_remove($channel['channel_id'], $r[0]['abook_id']);
                        if ($total_friends) {
                            $total_friends--;
                        }
                        if (intval($r[0]['abook_feed'])) {
                            $total_feeds--;
                        }
                    }
                    continue;
                }
                // Perform discovery if the referenced xchan hasn't ever been seen on this hub.
                // This relies on the undocumented behaviour that red sites send xchan info with the abook
                // and import_author_xchan will look them up on all federated networks
                if ($abook['abook_xchan'] && $abook['xchan_addr']) {
                    $h = zot_get_hublocs($abook['abook_xchan']);
                    if (!$h) {
                        $xhash = import_author_xchan(encode_item_xchan($abook));
                        if (!$xhash) {
                            logger('process_channel_sync_delivery: import of ' . $abook['xchan_addr'] . ' failed.');
                            continue;
                        }
                    }
                }
                foreach ($abook as $k => $v) {
                    if (in_array($k, $disallowed) || strpos($k, 'abook') !== 0) {
                        continue;
                    }
                    $clean[$k] = $v;
                }
                if (!array_key_exists('abook_xchan', $clean)) {
                    continue;
                }
                $r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc($clean['abook_xchan']), intval($channel['channel_id']));
                // make sure we have an abook entry for this xchan on this system
                if (!$r) {
                    if ($max_friends !== false && $total_friends > $max_friends) {
                        logger('process_channel_sync_delivery: total_channels service class limit exceeded');
                        continue;
                    }
                    if ($max_feeds !== false && intval($clean['abook_feed']) && $total_feeds > $max_feeds) {
                        logger('process_channel_sync_delivery: total_feeds service class limit exceeded');
                        continue;
                    }
                    q("insert into abook ( abook_xchan, abook_account, abook_channel ) values ('%s', %d, %d ) ", dbesc($clean['abook_xchan']), intval($channel['channel_account_id']), intval($channel['channel_id']));
                    $total_friends++;
                    if (intval($clean['abook_feed'])) {
                        $total_feeds++;
                    }
                }
                if (count($clean)) {
                    foreach ($clean as $k => $v) {
                        if ($k == 'abook_dob') {
                            $v = dbescdate($v);
                        }
                        $r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v) . "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id']));
                    }
                }
                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']);
                    }
                }
            }
        }
        // sync collections (privacy groups) oh joy...
        if (array_key_exists('collections', $arr) && is_array($arr['collections']) && count($arr['collections'])) {
            $x = q("select * from groups where uid = %d", intval($channel['channel_id']));
            foreach ($arr['collections'] as $cl) {
                $found = false;
                if ($x) {
                    foreach ($x as $y) {
                        if ($cl['collection'] == $y['hash']) {
                            $found = true;
                            break;
                        }
                    }
                    if ($found) {
                        if ($y['gname'] != $cl['name'] || $y['visible'] != $cl['visible'] || $y['deleted'] != $cl['deleted']) {
                            q("update groups set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d", dbesc($cl['name']), intval($cl['visible']), intval($cl['deleted']), dbesc($cl['hash']), intval($channel['channel_id']));
                        }
                        if (intval($cl['deleted']) && !intval($y['deleted'])) {
                            q("delete from group_member where gid = %d", intval($y['id']));
                        }
                    }
                }
                if (!$found) {
                    $r = q("INSERT INTO `groups` ( hash, uid, visible, deleted, gname )\n\t\t\t\t\t\tVALUES( '%s', %d, %d, %d, '%s' ) ", dbesc($cl['collection']), intval($channel['channel_id']), intval($cl['visible']), intval($cl['deleted']), dbesc($cl['name']));
                }
                // now look for any collections locally which weren't in the list we just received.
                // They need to be removed by marking deleted and removing the members.
                // This shouldn't happen except for clones created before this function was written.
                if ($x) {
                    $found_local = false;
                    foreach ($x as $y) {
                        foreach ($arr['collections'] as $cl) {
                            if ($cl['collection'] == $y['hash']) {
                                $found_local = true;
                                break;
                            }
                        }
                        if (!$found_local) {
                            q("delete from group_member where gid = %d", intval($y['id']));
                            q("update groups set deleted = 1 where id = %d and uid = %d", intval($y['id']), intval($channel['channel_id']));
                        }
                    }
                }
            }
            // reload the group list with any updates
            $x = q("select * from groups where uid = %d", intval($channel['channel_id']));
            // now sync the members
            if (array_key_exists('collection_members', $arr) && is_array($arr['collection_members']) && count($arr['collection_members'])) {
                // first sort into groups keyed by the group hash
                $members = array();
                foreach ($arr['collection_members'] as $cm) {
                    if (!array_key_exists($cm['collection'], $members)) {
                        $members[$cm['collection']] = array();
                    }
                    $members[$cm['collection']][] = $cm['member'];
                }
                // our group list is already synchronised
                if ($x) {
                    foreach ($x as $y) {
                        // for each group, loop on members list we just received
                        foreach ($members[$y['hash']] as $member) {
                            $found = false;
                            $z = q("select xchan from group_member where gid = %d and uid = %d and xchan = '%s' limit 1", intval($y['id']), intval($channel['channel_id']), dbesc($member));
                            if ($z) {
                                $found = true;
                            }
                            // if somebody is in the group that wasn't before - add them
                            if (!$found) {
                                q("INSERT INTO `group_member` (`uid`, `gid`, `xchan`)\n\t\t\t\t\t\t\t\t\tVALUES( %d, %d, '%s' ) ", intval($channel['channel_id']), intval($y['id']), dbesc($member));
                            }
                        }
                        // now retrieve a list of members we have on this site
                        $m = q("select xchan from group_member where gid = %d and uid = %d", intval($y['id']), intval($channel['channel_id']));
                        if ($m) {
                            foreach ($m as $mm) {
                                // if the local existing member isn't in the list we just received - remove them
                                if (!in_array($mm['xchan'], $members[$y['hash']])) {
                                    q("delete from group_member where xchan = '%s' and gid = %d and uid = %d", dbesc($mm['xchan']), intval($y['id']), intval($channel['channel_id']));
                                }
                            }
                        }
                    }
                }
            }
        }
        if (array_key_exists('profile', $arr) && is_array($arr['profile']) && count($arr['profile'])) {
            $disallowed = array('id', 'aid', 'uid', 'guid');
            foreach ($arr['profile'] as $profile) {
                $x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1", dbesc($profile['profile_guid']), intval($channel['channel_id']));
                if (!$x) {
                    q("insert into profile ( profile_guid, aid, uid ) values ('%s', %d, %d)", dbesc($profile['profile_guid']), intval($channel['channel_account_id']), intval($channel['channel_id']));
                    $x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1", dbesc($profile['profile_guid']), intval($channel['channel_id']));
                    if (!$x) {
                        continue;
                    }
                }
                $clean = array();
                foreach ($profile as $k => $v) {
                    if (in_array($k, $disallowed)) {
                        continue;
                    }
                    if ($k === 'name') {
                        $clean['fullname'] = $v;
                    } elseif ($k === 'with') {
                        $clean['partner'] = $v;
                    } elseif ($k === 'work') {
                        $clean['employment'] = $v;
                    } elseif (array_key_exists($k, $x[0])) {
                        $clean[$k] = $v;
                    }
                    /**
                     * @TODO 
                     * We also need to import local photos if a custom photo is selected
                     */
                }
                if (count($clean)) {
                    foreach ($clean as $k => $v) {
                        $r = dbq("UPDATE profile set `" . dbesc($k) . "` = '" . dbesc($v) . "' where profile_guid = '" . dbesc($profile['profile_guid']) . "' and uid = " . intval($channel['channel_id']));
                    }
                }
            }
        }
        $addon = array('channel' => $channel, 'data' => $arr);
        call_hooks('process_channel_sync_delivery', $addon);
        // we should probably do this for all items, but usually we only send one.
        if (array_key_exists('item', $arr) && is_array($arr['item'][0])) {
            $DR = new Zotlabs\Zot\DReport(z_root(), $d['hash'], $d['hash'], $arr['item'][0]['message_id'], 'channel sync processed');
            $DR->addto_recipient($channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . App::get_hostname() . '>');
        } else {
            $DR = new Zotlabs\Zot\DReport(z_root(), $d['hash'], $d['hash'], 'sync packet', 'channel sync delivered');
        }
        $result[] = $DR->get();
    }
    return $result;
}
예제 #10
0
function pubsubhubbub_subscribe($url, $channel, $xchan, $feed, $hubmode = 'subscribe')
{
    $push_url = z_root() . '/pubsub/' . $channel['channel_address'] . '/' . $xchan['abook_id'];
    $verify = get_abconfig($channel['channel_id'], $xchan['xchan_hash'], 'pubsubhubbub', 'verify_token');
    if (!$verify) {
        $verify = set_abconfig($channel['channel_id'], $xchan['xchan_hash'], 'pubsubhubbub', 'verify_token', random_string(16));
    }
    if ($feed) {
        set_xconfig($xchan['xchan_hash'], 'system', 'feed_url', $feed);
    } else {
        $feed = get_xconfig($xchan['xchan_hash'], 'system', 'feed_url');
    }
    $params = 'hub.mode=' . $hubmode . '&hub.callback=' . urlencode($push_url) . '&hub.topic=' . urlencode($feed) . '&hub.verify=async&hub.verify_token=' . $verify;
    logger('subscribe_to_hub: ' . $hubmode . ' ' . $xchan['xchan_name'] . ' to hub ' . $url . ' endpoint: ' . $push_url . ' with verifier ' . $verify);
    $x = z_post_url($url, $params);
    logger('subscribe_to_hub: returns: ' . $x['return_code'], LOGGER_DEBUG);
    return;
}
예제 #11
0
파일: boot.php 프로젝트: phellmes/hubzilla
function check_for_new_perms()
{
    $pregistered = get_config('system', 'perms');
    $pcurrent = array_keys(\Zotlabs\Access\Permissions::Perms());
    if (!$pregistered) {
        set_config('system', 'perms', $pcurrent);
        return;
    }
    $found_new_perm = false;
    foreach ($pcurrent as $p) {
        if (!in_array($p, $pregistered)) {
            $found_new_perm = true;
            // for all channels
            $c = q("select channel_id from channel where true");
            if ($c) {
                foreach ($c as $cc) {
                    // get the permission role
                    $r = q("select v from pconfig where uid = %d and cat = 'system' and k = 'permissions_role'", intval($cc['uid']));
                    if ($r) {
                        // get a list of connections
                        $x = q("select abook_xchan from abook where abook_channel = %d and abook_self = 0", intval($cc['uid']));
                        // get the permissions role details
                        $rp = \Zotlabs\Access\PermissionRoles::role_perms($r[0]['v']);
                        if ($rp) {
                            // set the channel limits if appropriate or 0
                            if (array_key_exists('limits', $rp) && array_key_exists($p, $rp['limits'])) {
                                \Zotlabs\Access\PermissionLimits::Set($cc['uid'], $p, $rp['limits'][$p]);
                            } else {
                                \Zotlabs\Access\PermissionLimits::Set($cc['uid'], $p, 0);
                            }
                            $set = array_key_exists('perms_connect', $rp) && array_key_exists($p, $rp['perms_connect']) ? true : false;
                            // foreach connection set to the perms_connect value
                            if ($x) {
                                foreach ($x as $xx) {
                                    set_abconfig($cc['uid'], $xx['abook_xchan'], 'my_perms', $p, intval($set));
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    // We should probably call perms_refresh here, but this should get pushed in 24 hours and there is no urgency
    if ($found_new_perm) {
        set_config('system', 'perms', $pcurrent);
    }
}
예제 #12
0
function diaspora_request($importer, $xml)
{
    $a = get_app();
    $sender_handle = unxmlify(diaspora_get_author($xml));
    $recipient_handle = unxmlify(diaspora_get_recipient($xml));
    // @TODO - map these perms to $newperms below
    if (array_key_exists('following', $xml) && array_key_exists('sharing', $xml)) {
        $following = unxmlify($xml['following']) === 'true' ? true : false;
        $sharing = unxmlify($xml['sharing']) === 'true' ? true : false;
    } else {
        $following = true;
        $sharing = true;
    }
    if (!$sender_handle || !$recipient_handle) {
        return;
    }
    // Do we already have an abook record?
    $contact = diaspora_get_contact_by_handle($importer['channel_id'], $sender_handle);
    // Please note some permissions such as PERMS_R_PAGES are impossible for Disapora.
    // They cannot currently authenticate to our system.
    $x = \Zotlabs\Access\PermissionRoles::role_perms('social');
    $their_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']);
    if ($contact && $contact['abook_id']) {
        // perhaps we were already sharing with this person. Now they're sharing with us.
        // That makes us friends. Maybe.
        foreach ($their_perms as $k => $v) {
            set_abconfig($importer['channel_id'], $contact['abook_xchan'], 'their_perms', $k, $v);
        }
        $abook_instance = $contact['abook_instance'];
        if ($abook_instance) {
            $abook_instance .= ',';
        }
        $abook_instance .= z_root();
        $r = q("update abook set abook_instance = '%s' where abook_id = %d and abook_channel = %d", dbesc($abook_instance), intval($contact['abook_id']), intval($importer['channel_id']));
        return;
    }
    $ret = find_diaspora_person_by_handle($sender_handle);
    if (!$ret || !strstr($ret['xchan_network'], 'diaspora')) {
        logger('diaspora_request: Cannot resolve diaspora handle ' . $sender_handle . ' for ' . $recipient_handle);
        return;
    }
    $my_perms = false;
    $role = get_pconfig($importer['channel_id'], 'system', 'permissions_role');
    if ($role) {
        $x = \Zotlabs\Access\PermissionRoles::role_perms($role);
        if ($x['perms_auto']) {
            $my_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']);
        }
    }
    if (!$my_perms) {
        $my_perms = \Zotlabs\Access\Permissions::FilledAutoperms($importer['channel_id']);
    }
    $closeness = get_pconfig($importer['channel_id'], 'system', 'new_abook_closeness');
    if ($closeness === false) {
        $closeness = 80;
    }
    $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_my_perms, abook_their_perms, abook_closeness, abook_created, abook_updated, abook_connected, abook_dob, abook_pending, abook_instance ) values ( %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', %d, '%s' )", intval($importer['channel_account_id']), intval($importer['channel_id']), dbesc($ret['xchan_hash']), intval($default_perms), intval($their_perms), intval($closeness), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(NULL_DATE), intval($my_perms ? 0 : 1), dbesc(z_root()));
    if ($my_perms) {
        foreach ($my_perms as $k => $v) {
            set_abconfig($importer['channel_id'], $ret['xchan_hash'], 'my_perms', $k, $v);
        }
    }
    if ($their_perms) {
        foreach ($their_perms as $k => $v) {
            set_abconfig($importer['channel_id'], $ret['xchan_hash'], 'their_perms', $k, $v);
        }
    }
    if ($r) {
        logger("New Diaspora introduction received for {$importer['channel_name']}");
        $new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash left join hubloc on hubloc_hash = xchan_hash where abook_channel = %d and abook_xchan = '%s' order by abook_created desc limit 1", intval($importer['channel_id']), dbesc($ret['xchan_hash']));
        if ($new_connection) {
            \Zotlabs\Lib\Enotify::submit(['type' => NOTIFY_INTRO, 'from_xchan' => $ret['xchan_hash'], 'to_xchan' => $importer['channel_hash'], 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']]);
            if ($my_perms) {
                // Send back a sharing notification to them
                $x = diaspora_share($importer, $new_connection[0]);
                if ($x) {
                    Zotlabs\Daemon\Master::Summon(array('Deliver', $x));
                }
            }
            $clone = array();
            foreach ($new_connection[0] as $k => $v) {
                if (strpos($k, 'abook_') === 0) {
                    $clone[$k] = $v;
                }
            }
            unset($clone['abook_id']);
            unset($clone['abook_account']);
            unset($clone['abook_channel']);
            $abconfig = load_abconfig($importer['channel_id'], $clone['abook_xchan']);
            if ($abconfig) {
                $clone['abconfig'] = $abconfig;
            }
            build_sync_packet($importer['channel_id'], ['abook' => array($clone)]);
        }
    }
    // find the abook record we just created
    $contact_record = diaspora_get_contact_by_handle($importer['channel_id'], $sender_handle);
    if (!$contact_record) {
        logger('diaspora_request: unable to locate newly created contact record.');
        return;
    }
    /** If there is a default group for this channel, add this member to it */
    if ($importer['channel_default_group']) {
        require_once 'include/group.php';
        $g = group_rec_byhash($importer['channel_id'], $importer['channel_default_group']);
        if ($g) {
            group_add_member($importer['channel_id'], '', $contact_record['xchan_hash'], $g['id']);
        }
    }
    return;
}
예제 #13
0
 function post()
 {
     if (!local_channel()) {
         return;
     }
     $contact_id = intval(argv(1));
     if (!$contact_id) {
         return;
     }
     $channel = \App::get_channel();
     // TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the
     // connection enable is toggled to a special autopost url and set permissions immediately, leaving
     // the other form elements alone pending a manual submit of the form. The downside is that there
     // will be a window of opportunity when the permissions have been set but before you've had a chance
     // to review and possibly restrict them. The upside is we won't have to warn you that your connection
     // can't do anything until you save the bloody form.
     $autopost = argc() > 2 && argv(2) === 'auto' ? true : false;
     $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1", intval($contact_id), intval(local_channel()));
     if (!$orig_record) {
         notice(t('Could not access contact record.') . EOL);
         goaway(z_root() . '/connections');
         return;
         // NOTREACHED
     }
     call_hooks('contact_edit_post', $_POST);
     if (intval($orig_record[0]['abook_self'])) {
         $autoperms = intval($_POST['autoperms']);
         $is_self = true;
     } else {
         $autoperms = null;
         $is_self = false;
     }
     $profile_id = $_POST['profile_assign'];
     if ($profile_id) {
         $r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND `uid` = %d LIMIT 1", dbesc($profile_id), intval(local_channel()));
         if (!count($r)) {
             notice(t('Could not locate selected profile.') . EOL);
             return;
         }
     }
     $abook_incl = escape_tags($_POST['abook_incl']);
     $abook_excl = escape_tags($_POST['abook_excl']);
     $hidden = intval($_POST['hidden']);
     $priority = intval($_POST['poll']);
     if ($priority > 5 || $priority < 0) {
         $priority = 0;
     }
     $closeness = intval($_POST['closeness']);
     if ($closeness < 0) {
         $closeness = 99;
     }
     $rating = intval($_POST['rating']);
     if ($rating < -10) {
         $rating = -10;
     }
     if ($rating > 10) {
         $rating = 10;
     }
     $rating_text = trim(escape_tags($_REQUEST['rating_text']));
     $all_perms = \Zotlabs\Access\Permissions::Perms();
     if ($all_perms) {
         foreach ($all_perms as $perm => $desc) {
             if (array_key_exists('perms_' . $perm, $_POST)) {
                 set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $perm, intval($_POST['perms_' . $perm]));
                 if ($autoperms) {
                     set_pconfig($channel['channel_id'], 'autoperms', $perm, intval($_POST['perms_' . $perm]));
                 }
             } else {
                 set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $perm, 0);
                 if ($autoperms) {
                     set_pconfig($channel['channel_id'], 'autoperms', $perm, 0);
                 }
             }
         }
     }
     if (!is_null($autoperms)) {
         set_pconfig($channel['channel_id'], 'system', 'autoperms', $autoperms);
     }
     $new_friend = false;
     // only store a record and notify the directory if the rating changed
     if (!$is_self) {
         $signed = $orig_record[0]['abook_xchan'] . '.' . $rating . '.' . $rating_text;
         $sig = base64url_encode(rsa_sign($signed, $channel['channel_prvkey']));
         $rated = intval($rating) || strlen($rating_text) ? true : false;
         $record = 0;
         $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) {
             if ($z[0]['xlink_rating'] != $rating || $z[0]['xlink_rating_text'] != $rating_text) {
                 $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\t\t\twhere xlink_id = %d", intval($rating), dbesc($rating_text), dbesc($sig), dbesc(datetime_convert()), intval($record));
             }
         } elseif ($rated) {
             // only create a record if there's something to save
             $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($orig_record[0]['abook_xchan']), 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) {
             \Zotlabs\Daemon\Master::Summon(array('Ratenotif', 'rating', $record));
         }
     }
     if ($_REQUEST['pending'] && intval($orig_record[0]['abook_pending'])) {
         $new_friend = true;
         // @fixme it won't be common, but when you accept a new connection request
         // the permissions will now be that of your permissions role and ignore
         // any you may have set manually on the form. We'll probably see a bug if somebody
         // tries to set the permissions *and* approve the connection in the same
         // request. The workaround is to approve the connection, then go back and
         // adjust permissions as desired.
         $abook_my_perms = get_channel_default_perms(local_channel());
         $role = get_pconfig(local_channel(), 'system', 'permissions_role');
         if ($role) {
             $x = \Zotlabs\Access\PermissionRoles::role_perms($role);
             if ($x['perms_connect']) {
                 $abook_my_perms = $x['perms_connect'];
             }
         }
         $filled_perms = \Zotlabs\Access\Permissions::FilledPerms($abook_my_perms);
         foreach ($filled_perms as $k => $v) {
             set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $k, $v);
         }
     }
     $abook_pending = $new_friend ? 0 : $orig_record[0]['abook_pending'];
     $r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,\n\t\t\tabook_incl = '%s', abook_excl = '%s'\n\t\t\twhere abook_id = %d AND abook_channel = %d", dbesc($profile_id), intval($closeness), intval($abook_pending), dbesc($abook_incl), dbesc($abook_excl), intval($contact_id), intval(local_channel()));
     if ($orig_record[0]['abook_profile'] != $profile_id) {
         //Update profile photo permissions
         logger('A new profile was assigned - updating profile photos');
         profile_photo_set_profile_perms(local_channel(), $profile_id);
     }
     if ($r) {
         info(t('Connection updated.') . EOL);
     } else {
         notice(t('Failed to update connection record.') . EOL);
     }
     if (!intval(\App::$poi['abook_self'])) {
         \Zotlabs\Daemon\Master::Summon(['Notifier', $new_friend ? 'permission_create' : 'permission_update', $contact_id]);
     }
     if ($new_friend) {
         $default_group = $channel['channel_default_group'];
         if ($default_group) {
             require_once 'include/group.php';
             $g = group_rec_byhash(local_channel(), $default_group);
             if ($g) {
                 group_add_member(local_channel(), '', \App::$poi['abook_xchan'], $g['id']);
             }
         }
         // Check if settings permit ("post new friend activity" is allowed, and
         // friends in general or this friend in particular aren't hidden)
         // and send out a new friend activity
         $pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0", intval($channel['channel_id']));
         if ($pr && !intval($orig_record[0]['abook_hidden']) && intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend'))) {
             $xarr = array();
             $xarr['verb'] = ACTIVITY_FRIEND;
             $xarr['item_wall'] = 1;
             $xarr['item_origin'] = 1;
             $xarr['item_thread_top'] = 1;
             $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
             $xarr['allow_cid'] = $channel['channel_allow_cid'];
             $xarr['allow_gid'] = $channel['channel_allow_gid'];
             $xarr['deny_cid'] = $channel['channel_deny_cid'];
             $xarr['deny_gid'] = $channel['channel_deny_gid'];
             $xarr['item_private'] = $xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid'] ? 1 : 0;
             $obj = array('type' => ACTIVITY_OBJ_PERSON, 'title' => \App::$poi['xchan_name'], 'id' => \App::$poi['xchan_hash'], 'link' => array(array('rel' => 'alternate', 'type' => 'text/html', 'href' => \App::$poi['xchan_url']), array('rel' => 'photo', 'type' => \App::$poi['xchan_photo_mimetype'], 'href' => \App::$poi['xchan_photo_l'])));
             $xarr['obj'] = json_encode($obj);
             $xarr['obj_type'] = ACTIVITY_OBJ_PERSON;
             $xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . \App::$poi['xchan_url'] . ']' . \App::$poi['xchan_name'] . '[/zrl]';
             $xarr['body'] .= "\n\n\n" . '[zrl=' . \App::$poi['xchan_url'] . '][zmg=80x80]' . \App::$poi['xchan_photo_m'] . '[/zmg][/zrl]';
             post_activity_item($xarr);
         }
         // pull in a bit of content if there is any to pull in
         \Zotlabs\Daemon\Master::Summon(array('Onepoll', $contact_id));
     }
     // Refresh the structure in memory with the new data
     $r = q("SELECT abook.*, xchan.*\n\t\t\tFROM abook left join xchan on abook_xchan = xchan_hash\n\t\t\tWHERE abook_channel = %d and abook_id = %d LIMIT 1", intval(local_channel()), intval($contact_id));
     if ($r) {
         \App::$poi = $r[0];
     }
     if ($new_friend) {
         $arr = array('channel_id' => local_channel(), 'abook' => \App::$poi);
         call_hooks('accept_follow', $arr);
     }
     $this->connedit_clone($a);
     if ($_REQUEST['pending'] && !$_REQUEST['done']) {
         goaway(z_root() . '/connections/ifpending');
     }
     return;
 }
예제 #14
0
 function post()
 {
     if (!local_channel()) {
         return;
     }
     if ($_SESSION['delegate']) {
         return;
     }
     $channel = \App::get_channel();
     // logger('mod_settings: ' . print_r($_REQUEST,true));
     if (argc() > 1 && argv(1) === 'oauth' && x($_POST, 'remove')) {
         check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
         $key = $_POST['remove'];
         q("DELETE FROM tokens WHERE id='%s' AND uid=%d", dbesc($key), local_channel());
         goaway(z_root() . "/settings/oauth/");
         return;
     }
     if (argc() > 2 && argv(1) === 'oauth' && (argv(2) === 'edit' || argv(2) === 'add') && x($_POST, 'submit')) {
         check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
         $name = x($_POST, 'name') ? $_POST['name'] : '';
         $key = x($_POST, 'key') ? $_POST['key'] : '';
         $secret = x($_POST, 'secret') ? $_POST['secret'] : '';
         $redirect = x($_POST, 'redirect') ? $_POST['redirect'] : '';
         $icon = x($_POST, 'icon') ? $_POST['icon'] : '';
         $ok = true;
         if ($name == '') {
             $ok = false;
             notice(t('Name is required') . EOL);
         }
         if ($key == '' || $secret == '') {
             $ok = false;
             notice(t('Key and Secret are required') . EOL);
         }
         if ($ok) {
             if ($_POST['submit'] == t("Update")) {
                 $r = q("UPDATE clients SET\n\t\t\t\t\t\t\t\tclient_id='%s',\n\t\t\t\t\t\t\t\tpw='%s',\n\t\t\t\t\t\t\t\tclname='%s',\n\t\t\t\t\t\t\t\tredirect_uri='%s',\n\t\t\t\t\t\t\t\ticon='%s',\n\t\t\t\t\t\t\t\tuid=%d\n\t\t\t\t\t\t\tWHERE client_id='%s'", dbesc($key), dbesc($secret), dbesc($name), dbesc($redirect), dbesc($icon), intval(local_channel()), dbesc($key));
             } else {
                 $r = q("INSERT INTO clients (client_id, pw, clname, redirect_uri, icon, uid)\n\t\t\t\t\t\tVALUES ('%s','%s','%s','%s','%s',%d)", dbesc($key), dbesc($secret), dbesc($name), dbesc($redirect), dbesc($icon), intval(local_channel()));
                 $r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ", dbesc($key), intval(local_channel()), dbesc('all'));
             }
         }
         goaway(z_root() . "/settings/oauth/");
         return;
     }
     if (argc() > 1 && argv(1) == 'featured') {
         check_form_security_token_redirectOnErr('/settings/featured', 'settings_featured');
         call_hooks('feature_settings_post', $_POST);
         build_sync_packet();
         return;
     }
     if (argc() > 1 && argv(1) == 'tokens') {
         check_form_security_token_redirectOnErr('/settings/tokens', 'settings_tokens');
         $token_errs = 0;
         if (array_key_exists('token', $_POST)) {
             $atoken_id = $_POST['atoken_id'] ? intval($_POST['atoken_id']) : 0;
             $name = trim(escape_tags($_POST['name']));
             $token = trim($_POST['token']);
             if (!$name || !$token) {
                 $token_errs++;
             }
             if (trim($_POST['expires'])) {
                 $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_POST['expires']);
             } else {
                 $expires = NULL_DATE;
             }
             $max_atokens = service_class_fetch(local_channel(), 'access_tokens');
             if ($max_atokens) {
                 $r = q("select count(atoken_id) as total where atoken_uid = %d", intval(local_channel()));
                 if ($r && intval($r[0]['total']) >= $max_tokens) {
                     notice(sprintf(t('This channel is limited to %d tokens'), $max_tokens) . EOL);
                     return;
                 }
             }
         }
         if ($token_errs) {
             notice(t('Name and Password are required.') . EOL);
             return;
         }
         if ($atoken_id) {
             $r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s' \n\t\t\t\t\twhere atoken_id = %d and atoken_uid = %d", dbesc($name), dbesc($token), dbesc($expires), intval($atoken_id), intval($channel['channel_id']));
         } else {
             $r = q("insert into atoken ( atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires )\n\t\t\t\t\tvalues ( %d, %d, '%s', '%s', '%s' ) ", intval($channel['channel_account_id']), intval($channel['channel_id']), dbesc($name), dbesc($token), dbesc($expires));
         }
         $atoken_xchan = substr($channel['channel_hash'], 0, 16) . '.' . $name;
         $all_perms = \Zotlabs\Access\Permissions::Perms();
         if ($all_perms) {
             foreach ($all_perms as $perm => $desc) {
                 if (array_key_exists('perms_' . $perm, $_POST)) {
                     set_abconfig($channel['channel_id'], $atoken_xchan, 'my_perms', $perm, intval($_POST['perms_' . $perm]));
                 } else {
                     set_abconfig($channel['channel_id'], $atoken_xchan, 'my_perms', $perm, 0);
                 }
             }
         }
         info(t('Token saved.') . EOL);
         return;
     }
     if (argc() > 1 && argv(1) === 'features') {
         check_form_security_token_redirectOnErr('/settings/features', 'settings_features');
         // Build list of features and check which are set
         $features = get_features();
         $all_features = array();
         foreach ($features as $k => $v) {
             foreach ($v as $f) {
                 $all_features[] = $f[0];
             }
         }
         foreach ($all_features as $k) {
             if (x($_POST, "feature_{$k}")) {
                 set_pconfig(local_channel(), 'feature', $k, 1);
             } else {
                 set_pconfig(local_channel(), 'feature', $k, 0);
             }
         }
         build_sync_packet();
         return;
     }
     if (argc() > 1 && argv(1) == 'display') {
         check_form_security_token_redirectOnErr('/settings/display', 'settings_display');
         $theme = x($_POST, 'theme') ? notags(trim($_POST['theme'])) : \App::$channel['channel_theme'];
         $mobile_theme = x($_POST, 'mobile_theme') ? notags(trim($_POST['mobile_theme'])) : '';
         $preload_images = x($_POST, 'preload_images') ? intval($_POST['preload_images']) : 0;
         $user_scalable = x($_POST, 'user_scalable') ? intval($_POST['user_scalable']) : 0;
         $nosmile = x($_POST, 'nosmile') ? intval($_POST['nosmile']) : 0;
         $title_tosource = x($_POST, 'title_tosource') ? intval($_POST['title_tosource']) : 0;
         $channel_list_mode = x($_POST, 'channel_list_mode') ? intval($_POST['channel_list_mode']) : 0;
         $network_list_mode = x($_POST, 'network_list_mode') ? intval($_POST['network_list_mode']) : 0;
         $channel_divmore_height = x($_POST, 'channel_divmore_height') ? intval($_POST['channel_divmore_height']) : 400;
         if ($channel_divmore_height < 50) {
             $channel_divmore_height = 50;
         }
         $network_divmore_height = x($_POST, 'network_divmore_height') ? intval($_POST['network_divmore_height']) : 400;
         if ($network_divmore_height < 50) {
             $network_divmore_height = 50;
         }
         $browser_update = x($_POST, 'browser_update') ? intval($_POST['browser_update']) : 0;
         $browser_update = $browser_update * 1000;
         if ($browser_update < 10000) {
             $browser_update = 10000;
         }
         $itemspage = x($_POST, 'itemspage') ? intval($_POST['itemspage']) : 20;
         if ($itemspage > 100) {
             $itemspage = 100;
         }
         if ($mobile_theme == "---") {
             del_pconfig(local_channel(), 'system', 'mobile_theme');
         } else {
             set_pconfig(local_channel(), 'system', 'mobile_theme', $mobile_theme);
         }
         set_pconfig(local_channel(), 'system', 'preload_images', $preload_images);
         set_pconfig(local_channel(), 'system', 'user_scalable', $user_scalable);
         set_pconfig(local_channel(), 'system', 'update_interval', $browser_update);
         set_pconfig(local_channel(), 'system', 'itemspage', $itemspage);
         set_pconfig(local_channel(), 'system', 'no_smilies', 1 - intval($nosmile));
         set_pconfig(local_channel(), 'system', 'title_tosource', $title_tosource);
         set_pconfig(local_channel(), 'system', 'channel_list_mode', $channel_list_mode);
         set_pconfig(local_channel(), 'system', 'network_list_mode', $network_list_mode);
         set_pconfig(local_channel(), 'system', 'channel_divmore_height', $channel_divmore_height);
         set_pconfig(local_channel(), 'system', 'network_divmore_height', $network_divmore_height);
         if ($theme == \App::$channel['channel_theme']) {
             // call theme_post only if theme has not been changed
             if (($themeconfigfile = $this->get_theme_config_file($theme)) != null) {
                 require_once $themeconfigfile;
                 theme_post($a);
             }
         }
         $r = q("UPDATE channel SET channel_theme = '%s' WHERE channel_id = %d", dbesc($theme), intval(local_channel()));
         call_hooks('display_settings_post', $_POST);
         build_sync_packet();
         goaway(z_root() . '/settings/display');
         return;
         // NOTREACHED
     }
     if (argc() > 1 && argv(1) === 'account') {
         check_form_security_token_redirectOnErr('/settings/account', 'settings_account');
         call_hooks('account_settings_post', $_POST);
         //		call_hooks('settings_account', $_POST);
         $errs = array();
         $email = x($_POST, 'email') ? trim(notags($_POST['email'])) : '';
         $account = \App::get_account();
         if ($email != $account['account_email']) {
             if (!valid_email($email)) {
                 $errs[] = t('Not valid email.');
             }
             $adm = trim(get_config('system', 'admin_email'));
             if ($adm && strcasecmp($email, $adm) == 0) {
                 $errs[] = t('Protected email address. Cannot change to that email.');
                 $email = \App::$user['email'];
             }
             if (!$errs) {
                 $r = q("update account set account_email = '%s' where account_id = %d", dbesc($email), intval($account['account_id']));
                 if (!$r) {
                     $errs[] = t('System failure storing new email. Please try again.');
                 }
             }
         }
         if ($errs) {
             foreach ($errs as $err) {
                 notice($err . EOL);
             }
             $errs = array();
         }
         if (x($_POST, 'npassword') || x($_POST, 'confirm')) {
             $origpass = trim($_POST['origpass']);
             require_once 'include/auth.php';
             if (!account_verify_password($email, $origpass)) {
                 $errs[] = t('Password verification failed.');
             }
             $newpass = trim($_POST['npassword']);
             $confirm = trim($_POST['confirm']);
             if ($newpass != $confirm) {
                 $errs[] = t('Passwords do not match. Password unchanged.');
             }
             if (!x($newpass) || !x($confirm)) {
                 $errs[] = t('Empty passwords are not allowed. Password unchanged.');
             }
             if (!$errs) {
                 $salt = random_string(32);
                 $password_encoded = hash('whirlpool', $salt . $newpass);
                 $r = q("update account set account_salt = '%s', account_password = '******', account_password_changed = '%s' \n\t\t\t\t\t\twhere account_id = %d", dbesc($salt), dbesc($password_encoded), dbesc(datetime_convert()), intval(get_account_id()));
                 if ($r) {
                     info(t('Password changed.') . EOL);
                 } else {
                     $errs[] = t('Password update failed. Please try again.');
                 }
             }
         }
         if ($errs) {
             foreach ($errs as $err) {
                 notice($err . EOL);
             }
         }
         goaway(z_root() . '/settings/account');
     }
     check_form_security_token_redirectOnErr('/settings', 'settings');
     call_hooks('settings_post', $_POST);
     $set_perms = '';
     $role = x($_POST, 'permissions_role') ? notags(trim($_POST['permissions_role'])) : '';
     $oldrole = get_pconfig(local_channel(), 'system', 'permissions_role');
     if ($role != $oldrole || $role === 'custom') {
         if ($role === 'custom') {
             $hide_presence = x($_POST, 'hide_presence') && intval($_POST['hide_presence']) == 1 ? 1 : 0;
             $publish = x($_POST, 'profile_in_directory') && intval($_POST['profile_in_directory']) == 1 ? 1 : 0;
             $def_group = x($_POST, 'group-selection') ? notags(trim($_POST['group-selection'])) : '';
             $r = q("update channel set channel_default_group = '%s' where channel_id = %d", dbesc($def_group), intval(local_channel()));
             $global_perms = \Zotlabs\Access\Permissions::Perms();
             foreach ($global_perms as $k => $v) {
                 \Zotlabs\Access\PermissionLimits::Set(local_channel(), $k, intval($_POST[$k]));
             }
             $acl = new \Zotlabs\Access\AccessList($channel);
             $acl->set_from_array($_POST);
             $x = $acl->get();
             $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s', \n\t\t\t\t\tchannel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d", dbesc($x['allow_cid']), dbesc($x['allow_gid']), dbesc($x['deny_cid']), dbesc($x['deny_gid']), intval(local_channel()));
         } else {
             $role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($_POST['permissions_role']);
             if (!$role_permissions) {
                 notice('Permissions category could not be found.');
                 return;
             }
             $hide_presence = 1 - intval($role_permissions['online']);
             if ($role_permissions['default_collection']) {
                 $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc(t('Friends')));
                 if (!$r) {
                     require_once 'include/group.php';
                     group_add(local_channel(), t('Friends'));
                     group_add_member(local_channel(), t('Friends'), $channel['channel_hash']);
                     $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc(t('Friends')));
                 }
                 if ($r) {
                     q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d", dbesc($r[0]['hash']), dbesc('<' . $r[0]['hash'] . '>'), intval(local_channel()));
                 } else {
                     notice(sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL);
                     return;
                 }
             } else {
                 q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '', \n\t\t\t\t\t\tchannel_deny_cid = '' where channel_id = %d", intval(local_channel()));
             }
             $x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']);
             foreach ($x as $k => $v) {
                 set_abconfig(local_channel(), $channel['channel_hash'], 'my_perms', $k, $v);
                 if ($role_permissions['perms_auto']) {
                     set_pconfig(local_channel(), 'autoperms', $k, $v);
                 } else {
                     del_pconfig(local_channel(), 'autoperms', $k);
                 }
             }
             if ($role_permissions['limits']) {
                 foreach ($role_permissions['limits'] as $k => $v) {
                     \Zotlabs\Access\PermissionLimits::Set(local_channel(), $k, $v);
                 }
             }
             if (array_key_exists('directory_publish', $role_permissions)) {
                 $publish = intval($role_permissions['directory_publish']);
             }
         }
         set_pconfig(local_channel(), 'system', 'hide_online_status', $hide_presence);
         set_pconfig(local_channel(), 'system', 'permissions_role', $role);
     }
     $username = x($_POST, 'username') ? notags(trim($_POST['username'])) : '';
     $timezone = x($_POST, 'timezone_select') ? notags(trim($_POST['timezone_select'])) : '';
     $defloc = x($_POST, 'defloc') ? notags(trim($_POST['defloc'])) : '';
     $openid = x($_POST, 'openid_url') ? notags(trim($_POST['openid_url'])) : '';
     $maxreq = x($_POST, 'maxreq') ? intval($_POST['maxreq']) : 0;
     $expire = x($_POST, 'expire') ? intval($_POST['expire']) : 0;
     $evdays = x($_POST, 'evdays') ? intval($_POST['evdays']) : 3;
     $photo_path = x($_POST, 'photo_path') ? escape_tags(trim($_POST['photo_path'])) : '';
     $attach_path = x($_POST, 'attach_path') ? escape_tags(trim($_POST['attach_path'])) : '';
     $channel_menu = x($_POST['channel_menu']) ? htmlspecialchars_decode(trim($_POST['channel_menu']), ENT_QUOTES) : '';
     $expire_items = x($_POST, 'expire_items') ? intval($_POST['expire_items']) : 0;
     $expire_starred = x($_POST, 'expire_starred') ? intval($_POST['expire_starred']) : 0;
     $expire_photos = x($_POST, 'expire_photos') ? intval($_POST['expire_photos']) : 0;
     $expire_network_only = x($_POST, 'expire_network_only') ? intval($_POST['expire_network_only']) : 0;
     $allow_location = x($_POST, 'allow_location') && intval($_POST['allow_location']) == 1 ? 1 : 0;
     $blocktags = x($_POST, 'blocktags') && intval($_POST['blocktags']) == 1 ? 0 : 1;
     // this setting is inverted!
     $unkmail = x($_POST, 'unkmail') && intval($_POST['unkmail']) == 1 ? 1 : 0;
     $cntunkmail = x($_POST, 'cntunkmail') ? intval($_POST['cntunkmail']) : 0;
     $suggestme = x($_POST, 'suggestme') ? intval($_POST['suggestme']) : 0;
     $post_newfriend = $_POST['post_newfriend'] == 1 ? 1 : 0;
     $post_joingroup = $_POST['post_joingroup'] == 1 ? 1 : 0;
     $post_profilechange = $_POST['post_profilechange'] == 1 ? 1 : 0;
     $adult = $_POST['adult'] == 1 ? 1 : 0;
     $cal_first_day = x($_POST, 'first_day') && intval($_POST['first_day']) == 1 ? 1 : 0;
     $channel = \App::get_channel();
     $pageflags = $channel['channel_pageflags'];
     $existing_adult = $pageflags & PAGE_ADULT ? 1 : 0;
     if ($adult != $existing_adult) {
         $pageflags = $pageflags ^ PAGE_ADULT;
     }
     $notify = 0;
     if (x($_POST, 'notify1')) {
         $notify += intval($_POST['notify1']);
     }
     if (x($_POST, 'notify2')) {
         $notify += intval($_POST['notify2']);
     }
     if (x($_POST, 'notify3')) {
         $notify += intval($_POST['notify3']);
     }
     if (x($_POST, 'notify4')) {
         $notify += intval($_POST['notify4']);
     }
     if (x($_POST, 'notify5')) {
         $notify += intval($_POST['notify5']);
     }
     if (x($_POST, 'notify6')) {
         $notify += intval($_POST['notify6']);
     }
     if (x($_POST, 'notify7')) {
         $notify += intval($_POST['notify7']);
     }
     if (x($_POST, 'notify8')) {
         $notify += intval($_POST['notify8']);
     }
     $vnotify = 0;
     if (x($_POST, 'vnotify1')) {
         $vnotify += intval($_POST['vnotify1']);
     }
     if (x($_POST, 'vnotify2')) {
         $vnotify += intval($_POST['vnotify2']);
     }
     if (x($_POST, 'vnotify3')) {
         $vnotify += intval($_POST['vnotify3']);
     }
     if (x($_POST, 'vnotify4')) {
         $vnotify += intval($_POST['vnotify4']);
     }
     if (x($_POST, 'vnotify5')) {
         $vnotify += intval($_POST['vnotify5']);
     }
     if (x($_POST, 'vnotify6')) {
         $vnotify += intval($_POST['vnotify6']);
     }
     if (x($_POST, 'vnotify7')) {
         $vnotify += intval($_POST['vnotify7']);
     }
     if (x($_POST, 'vnotify8')) {
         $vnotify += intval($_POST['vnotify8']);
     }
     if (x($_POST, 'vnotify9')) {
         $vnotify += intval($_POST['vnotify9']);
     }
     if (x($_POST, 'vnotify10')) {
         $vnotify += intval($_POST['vnotify10']);
     }
     if (x($_POST, 'vnotify11')) {
         $vnotify += intval($_POST['vnotify11']);
     }
     $always_show_in_notices = x($_POST, 'always_show_in_notices') ? 1 : 0;
     $channel = \App::get_channel();
     $err = '';
     $name_change = false;
     if ($username != $channel['channel_name']) {
         $name_change = true;
         require_once 'include/channel.php';
         $err = validate_channelname($username);
         if ($err) {
             notice($err);
             return;
         }
     }
     if ($timezone != $channel['channel_timezone']) {
         if (strlen($timezone)) {
             date_default_timezone_set($timezone);
         }
     }
     set_pconfig(local_channel(), 'system', 'use_browser_location', $allow_location);
     set_pconfig(local_channel(), 'system', 'suggestme', $suggestme);
     set_pconfig(local_channel(), 'system', 'post_newfriend', $post_newfriend);
     set_pconfig(local_channel(), 'system', 'post_joingroup', $post_joingroup);
     set_pconfig(local_channel(), 'system', 'post_profilechange', $post_profilechange);
     set_pconfig(local_channel(), 'system', 'blocktags', $blocktags);
     set_pconfig(local_channel(), 'system', 'channel_menu', $channel_menu);
     set_pconfig(local_channel(), 'system', 'vnotify', $vnotify);
     set_pconfig(local_channel(), 'system', 'always_show_in_notices', $always_show_in_notices);
     set_pconfig(local_channel(), 'system', 'evdays', $evdays);
     set_pconfig(local_channel(), 'system', 'photo_path', $photo_path);
     set_pconfig(local_channel(), 'system', 'attach_path', $attach_path);
     set_pconfig(local_channel(), 'system', 'cal_first_day', $cal_first_day);
     $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d {$set_perms} where channel_id = %d", dbesc($username), intval($pageflags), dbesc($timezone), dbesc($defloc), intval($notify), intval($unkmail), intval($maxreq), intval($expire), intval(local_channel()));
     if ($r) {
         info(t('Settings updated.') . EOL);
     }
     if (!is_null($publish)) {
         $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d", intval($publish), intval(local_channel()));
     }
     if ($name_change) {
         $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'", dbesc($username), dbesc(datetime_convert()), dbesc($channel['channel_hash']));
         $r = q("update profile set fullname = '%s' where uid = %d and is_default = 1", dbesc($username), intval($channel['channel_id']));
     }
     \Zotlabs\Daemon\Master::Summon(array('Directory', local_channel()));
     build_sync_packet();
     //$_SESSION['theme'] = $theme;
     if ($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) {
         // FIXME - set to un-verified, blocked and redirect to logout
         // Why? Are we verifying people or email addresses?
     }
     goaway(z_root() . '/settings');
     return;
     // NOTREACHED
 }