Example #1
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)
{
    $a = get_app();
    $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']);
    }
    $primary = true;
    if (array_key_exists('primary', $arr)) {
        $primary = intval($arr['primary']);
    }
    $role_permissions = null;
    $global_perms = get_perms();
    if (array_key_exists('permissions_role', $arr) && $arr['permissions_role']) {
        $role_permissions = get_role_perms($arr['permissions_role']);
        if ($role_permissions) {
            foreach ($role_permissions as $p => $v) {
                if (strpos($p, 'channel_') !== false) {
                    $perms_keys .= ', ' . $p;
                    $perms_vals .= ', ' . intval($v);
                }
                if ($p === 'directory_publish') {
                    $publish = intval($v);
                }
            }
        }
    } else {
        $defperms = site_default_perms();
        foreach ($defperms as $p => $v) {
            $perms_keys .= ', ' . $global_perms[$p][0];
            $perms_vals .= ', ' . intval($v);
        }
    }
    $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 {$perms_keys} )\n\t\tvalues ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s' {$perms_vals} ) ", 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($a->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;
    }
    $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($ret['channel']['channel_address'] . '@' . get_app()->get_hostname()), intval($primary), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(), $ret['channel']['channel_prvkey']))), dbesc(get_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($a->get_baseurl() . "/photo/profile/l/{$newuid}"), dbesc($a->get_baseurl() . "/photo/profile/m/{$newuid}"), dbesc($a->get_baseurl() . "/photo/profile/s/{$newuid}"), dbesc($ret['channel']['channel_address'] . '@' . get_app()->get_hostname()), 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, name, 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($a->get_baseurl() . "/photo/profile/l/{$newuid}"), dbesc($a->get_baseurl() . "/photo/profile/m/{$newuid}"));
    if ($role_permissions) {
        $myperms = array_key_exists('perms_auto', $role_permissions) && $role_permissions['perms_auto'] ? intval($role_permissions['perms_accept']) : 0;
    } else {
        $myperms = PERMS_R_STREAM | PERMS_R_PROFILE | PERMS_R_PHOTOS | PERMS_R_ABOOK | PERMS_W_STREAM | PERMS_W_WALL | PERMS_W_COMMENT | PERMS_W_MAIL | PERMS_W_CHAT | PERMS_R_STORAGE | PERMS_R_PAGES | PERMS_W_LIKE;
    }
    $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_self, abook_my_perms )\n\t\tvalues ( %d, %d, '%s', %d, '%s', '%s', %d, %d ) ", intval($ret['channel']['channel_account_id']), intval($newuid), dbesc($hash), intval(0), dbesc(datetime_convert()), dbesc(datetime_convert()), intval(1), intval($myperms));
    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)) {
                set_pconfig($newuid, 'system', 'autoperms', $role_permissions['perms_auto'] ? $role_permissions['perms_accept'] : 0);
            }
        }
        // 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 name = '%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);
        proc_run('php', 'include/directory.php', $ret['channel']['channel_id']);
    }
    $ret['success'] = true;
    return $ret;
}
Example #2
0
/**
 * @function create_identity($arr)
 *     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
 *       'name'       => full name of channel
 *       'nickname'   => "email/url-compliant" nickname
 *       'account_id' => 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)
{
    $a = get_app();
    $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;
    }
    $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;
    $xchanflags = x($arr, 'xchanflags') ? intval($arr['xchanflags']) : XCHAN_FLAGS_NORMAL;
    $name_error = validate_channelname($arr['name']);
    if ($name_error) {
        $ret['message'] = $name_error;
        return $ret;
    }
    if ($nick === 'sys' && !($pageflags & PAGE_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']);
    }
    $primary = true;
    if (array_key_exists('primary', $arr)) {
        $primary = intval($arr['primary']);
    }
    $perms_sql = '';
    $defperms = site_default_perms();
    $global_perms = get_perms();
    foreach ($defperms as $p => $v) {
        $perms_keys .= ', ' . $global_perms[$p][0];
        $perms_vals .= ', ' . intval($v);
    }
    $expire = get_config('system', 'default_expire_days');
    $expire = $expire === false ? '0' : $expire;
    $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_expire_days {$perms_keys} )\n\t\tvalues ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d {$perms_vals} ) ", 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($expire));
    $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;
    }
    $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_flags, \n\t\thubloc_url, hubloc_url_sig, hubloc_host, hubloc_callback, hubloc_sitekey )\n\t\tvalues ( '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s' )", dbesc($guid), dbesc($sig), dbesc($hash), dbesc($ret['channel']['channel_address'] . '@' . get_app()->get_hostname()), intval($primary ? HUBLOC_FLAGS_PRIMARY : 0), dbesc(z_root()), dbesc(base64url_encode(rsa_sign(z_root(), $ret['channel']['channel_prvkey']))), dbesc(get_app()->get_hostname()), dbesc(z_root() . '/post'), dbesc(get_config('system', 'pubkey')));
    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_flags ) 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($a->get_baseurl() . "/photo/profile/l/{$newuid}"), dbesc($a->get_baseurl() . "/photo/profile/m/{$newuid}"), dbesc($a->get_baseurl() . "/photo/profile/s/{$newuid}"), dbesc($ret['channel']['channel_address'] . '@' . get_app()->get_hostname()), 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($xchanflags));
    // 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, name, 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($a->get_baseurl() . "/photo/profile/l/{$newuid}"), dbesc($a->get_baseurl() . "/photo/profile/m/{$newuid}"));
    $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_flags )\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(ABOOK_FLAG_SELF));
    if (intval($ret['channel']['channel_account_id'])) {
        // Create a group with no members. This allows somebody to use it
        // right away as a default group for new contacts.
        require_once 'include/group.php';
        group_add($newuid, t('Friends'));
        call_hooks('register_account', $newuid);
        proc_run('php', 'include/directory.php', $ret['channel']['channel_id']);
    }
    $ret['success'] = true;
    return $ret;
}