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 }
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; } }
/** * @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; }
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; }
/** * @brief Refreshes after permission changed or friending, etc. * * zot_refresh is typically invoked when somebody has changed permissions of a channel and they are notified * to fetch new permissions via a finger/discovery operation. This may result in a new connection * (abook entry) being added to a local channel and it may result in auto-permissions being granted. * * Friending in zot is accomplished by sending a refresh packet to a specific channel which indicates a * permission change has been made by the sender which affects the target channel. The hub controlling * the target channel does targetted discovery (a zot-finger request requesting permissions for the local * channel). These are decoded here, and if necessary and abook structure (addressbook) is created to store * the permissions assigned to this channel. * * Initially these abook structures are created with a 'pending' flag, so that no reverse permissions are * implied until this is approved by the owner channel. A channel can also auto-populate permissions in * return and send back a refresh packet of its own. This is used by forum and group communication channels * so that friending and membership in the channel's "club" is automatic. * * @param array $them => xchan structure of sender * @param array $channel => local channel structure of target recipient, required for "friending" operations * @param array $force default false * * @returns boolean true if successful, else false */ function zot_refresh($them, $channel = null, $force = false) { if (array_key_exists('xchan_network', $them) && $them['xchan_network'] !== 'zot') { logger('zot_refresh: not got zot. ' . $them['xchan_name']); return true; } logger('zot_refresh: them: ' . print_r($them, true), LOGGER_DATA, LOG_DEBUG); if ($channel) { logger('zot_refresh: channel: ' . print_r($channel, true), LOGGER_DATA, LOG_DEBUG); } $url = null; if ($them['hubloc_url']) { $url = $them['hubloc_url']; } else { $r = null; // if they re-installed the server we could end up with the wrong record - pointing to the old install. // We'll order by reverse id to try and pick off the newest one first and hopefully end up with the // correct hubloc. If this doesn't work we may have to re-write this section to try them all. if (array_key_exists('xchan_addr', $them) && $them['xchan_addr']) { $r = q("select hubloc_url, hubloc_primary from hubloc where hubloc_addr = '%s' order by hubloc_id desc", dbesc($them['xchan_addr'])); } if (!$r) { $r = q("select hubloc_url, hubloc_primary from hubloc where hubloc_hash = '%s' order by hubloc_id desc", dbesc($them['xchan_hash'])); } if ($r) { foreach ($r as $rr) { if (intval($rr['hubloc_primary'])) { $url = $rr['hubloc_url']; break; } } if (!$url) { $url = $r[0]['hubloc_url']; } } } if (!$url) { logger('zot_refresh: no url'); return false; } $token = random_string(); $postvars = array(); $postvars['token'] = $token; if ($channel) { $postvars['target'] = $channel['channel_guid']; $postvars['target_sig'] = $channel['channel_guid_sig']; $postvars['key'] = $channel['channel_pubkey']; } if (array_key_exists('xchan_addr', $them) && $them['xchan_addr']) { $postvars['address'] = $them['xchan_addr']; } if (array_key_exists('xchan_hash', $them) && $them['xchan_hash']) { $postvars['guid_hash'] = $them['xchan_hash']; } if (array_key_exists('xchan_guid', $them) && $them['xchan_guid'] && array_key_exists('xchan_guid_sig', $them) && $them['xchan_guid_sig']) { $postvars['guid'] = $them['xchan_guid']; $postvars['guid_sig'] = $them['xchan_guid_sig']; } $rhs = '/.well-known/zot-info'; $result = z_post_url($url . $rhs, $postvars); logger('zot_refresh: zot-info: ' . print_r($result, true), LOGGER_DATA, LOG_DEBUG); if ($result['success']) { $j = json_decode($result['body'], true); if (!($j && $j['success'])) { logger('zot_refresh: result not decodable'); return false; } $signed_token = is_array($j) && array_key_exists('signed_token', $j) ? $j['signed_token'] : null; if ($signed_token) { $valid = rsa_verify('token.' . $token, base64url_decode($signed_token), $j['key']); if (!$valid) { logger('invalid signed token: ' . $url . $rhs, LOGGER_NORMAL, LOG_ERR); return false; } } else { logger('No signed token from ' . $url . $rhs, LOGGER_NORMAL, LOG_WARNING); // after 2017-01-01 this will be a hard error unless you over-ride it. if (time() > 1483228800 && !get_config('system', 'allow_unsigned_zotfinger')) { return false; } } $x = import_xchan($j, $force ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED); if (!$x['success']) { return false; } if ($channel) { if ($j['permissions']['data']) { $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, LOG_DEBUG); } else { $permissions = $j['permissions']; } $connected_set = false; if ($permissions && is_array($permissions)) { $old_read_stream_perm = get_abconfig($channel['channel_id'], $x['hash'], 'their_perms', 'view_stream'); foreach ($permissions as $k => $v) { set_abconfig($channel['channel_id'], $x['hash'], 'their_perms', $k, $v); } } if (array_key_exists('profile', $j) && array_key_exists('next_birthday', $j['profile'])) { $next_birthday = datetime_convert('UTC', 'UTC', $j['profile']['next_birthday']); } else { $next_birthday = NULL_DATE; } $r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", dbesc($x['hash']), intval($channel['channel_id'])); if ($r) { // connection exists // if the dob is the same as what we have stored (disregarding the year), keep the one // we have as we may have updated the year after sending a notification; and resetting // to the one we just received would cause us to create duplicated events. if (substr($r[0]['abook_dob'], 5) == substr($next_birthday, 5)) { $next_birthday = $r[0]['abook_dob']; } $y = q("update abook set abook_dob = '%s'\n\t\t\t\t\twhere abook_xchan = '%s' and abook_channel = %d\n\t\t\t\t\tand abook_self = 0 ", dbescdate($next_birthday), dbesc($x['hash']), intval($channel['channel_id'])); if (!$y) { logger('abook update failed'); } else { // if we were just granted read stream permission and didn't have it before, try to pull in some posts if (!$old_read_stream_perm && intval($permissions['view_stream'])) { Zotlabs\Daemon\Master::Summon(array('Onepoll', $r[0]['abook_id'])); } } } else { // new connection $my_perms = null; $automatic = false; $role = get_pconfig($channel['channel_id'], 'system', 'permissions_role'); if ($role) { $xx = \Zotlabs\Access\PermissionRoles::role_perms($role); if ($xx['perms_auto']) { $automatic = true; $default_perms = $xx['perms_connect']; $my_perms = \Zotlabs\Access\Permissions::FilledPerms($default_perms); } } if (!$my_perms) { $m = \Zotlabs\Access\Permissions::FilledAutoperms($channel['channel_id']); if ($m) { $automatic = true; $my_perms = $m; } } if ($my_perms) { foreach ($my_perms as $k => $v) { set_abconfig($channel['channel_id'], $x['hash'], 'my_perms', $k, $v); } } // Keep original perms to check if we need to notify them $previous_perms = get_all_perms($channel['channel_id'], $x['hash']); $closeness = get_pconfig($channel['channel_id'], 'system', 'new_abook_closeness'); if ($closeness === false) { $closeness = 80; } $y = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_created, abook_updated, abook_dob, abook_pending ) values ( %d, %d, %d, '%s', '%s', '%s', '%s', %d )", intval($channel['channel_account_id']), intval($channel['channel_id']), intval($closeness), dbesc($x['hash']), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($next_birthday), intval($automatic ? 0 : 1)); if ($y) { logger("New introduction received for {$channel['channel_name']}"); $new_perms = get_all_perms($channel['channel_id'], $x['hash']); // Send a clone sync packet and a permissions update if permissions have changed $new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 order by abook_created desc limit 1", dbesc($x['hash']), intval($channel['channel_id'])); if ($new_connection) { if (!\Zotlabs\Access\Permissions::PermsCompare($new_perms, $previous_perms)) { Zotlabs\Daemon\Master::Summon(array('Notifier', 'permission_create', $new_connection[0]['abook_id'])); } Zotlabs\Lib\Enotify::submit(array('type' => NOTIFY_INTRO, 'from_xchan' => $x['hash'], 'to_xchan' => $channel['channel_hash'], 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'])); if (intval($permissions['view_stream'])) { if (intval(get_pconfig($channel['channel_id'], 'perm_limits', 'send_stream') & PERMS_PENDING) || !intval($new_connection[0]['abook_pending'])) { Zotlabs\Daemon\Master::Summon(array('Onepoll', $new_connection[0]['abook_id'])); } } /** If there is a default group for this channel, add this connection to it */ $default_group = $channel['channel_default_group']; if ($default_group) { require_once 'include/group.php'; $g = group_rec_byhash($channel['channel_id'], $default_group); if ($g) { group_add_member($channel['channel_id'], '', $x['hash'], $g['id']); } } unset($new_connection[0]['abook_id']); unset($new_connection[0]['abook_account']); unset($new_connection[0]['abook_channel']); $abconfig = load_abconfig($channel['channel_id'], $new_connection['abook_xchan']); if ($abconfig) { $new_connection['abconfig'] = $abconfig; } build_sync_packet($channel['channel_id'], array('abook' => $new_connection)); } } } } return true; } return false; }
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; }
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 }