/** * This is the preferred way to create a PermissionDescription, as it provides the most details. * Use this method if you know an empty ACL will result in one of the global default permissions * being used, such as channel_r_stream (for which you would pass 'view_stream'). * * @param string $permname - a key for the global perms array from get_perms() in permissions.php, * e.g. 'view_stream', 'view_profile', etc. * @return a new instance of PermissionDescription */ public static function fromGlobalPermission($permname) { $result = null; $global_perms = \Zotlabs\Access\Permissions::Perms(); if (array_key_exists($permname, $global_perms)) { $channelPerm = \Zotlabs\Access\PermissionLimits::Get(\App::$channel['channel_id'], $permname); $result = new PermissionDescription('', $channelPerm); } else { // The acl dialog can handle null arguments, but it shouldn't happen logger('null PermissionDescription from unknown global permission: ' . $permname, LOGGER_DEBUG, LOG_ERROR); } return $result; }
public static function Std_Limits() { $perms = Permissions::Perms(); $limits = array(); foreach ($perms as $k => $v) { if (strstr($k, 'view')) { $limits[$k] = PERMS_PUBLIC; } else { $limits[$k] = PERMS_SPECIFIC; } } return $limits; }
function get() { $channel = \App::get_channel(); $atoken = null; $atoken_xchan = ''; if (argc() > 2) { $id = argv(2); $atoken = q("select * from atoken where atoken_id = %d and atoken_uid = %d", intval($id), intval(local_channel())); if ($atoken) { $atoken = $atoken[0]; $atoken_xchan = substr($channel['channel_hash'], 0, 16) . '.' . $atoken['atoken_name']; } if ($atoken && argc() > 3 && argv(3) === 'drop') { atoken_delete($id); $atoken = null; $atoken_xchan = ''; } } $t = q("select * from atoken where atoken_uid = %d", intval(local_channel())); $desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content.'); $desc2 = t('You may also provide <em>dropbox</em> style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:'); $global_perms = \Zotlabs\Access\Permissions::Perms(); $existing = get_all_perms(local_channel(), $atoken_xchan ? $atoken_xchan : ''); if ($atoken_xchan) { $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", intval(local_channel()), dbesc($atoken_xchan)); $their_perms = array(); if ($theirs) { foreach ($theirs as $t) { $their_perms[$t['k']] = $t['v']; } } } foreach ($global_perms as $k => $v) { $thisperm = get_abconfig(local_channel(), $contact['abook_xchan'], 'my_perms', $k); //fixme $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(), $k); if ($existing[$k]) { $thisperm = "1"; } $perms[] = array('perms_' . $k, $v, array_key_exists($k, $their_perms) ? intval($their_perms[$k]) : '', $thisperm, 1, $checkinherited & PERMS_SPECIFIC ? '' : '1', '', $checkinherited); } $tpl = get_markup_template("settings_tokens.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_tokens"), '$title' => t('Guest Access Tokens'), '$desc' => $desc, '$desc2' => $desc2, '$tokens' => $t, '$atoken' => $atoken, '$url1' => z_root() . '/channel/' . $channel['channel_address'], '$url2' => z_root() . '/photos/' . $channel['channel_address'], '$name' => array('name', t('Login Name') . ' <span class="required">*</span>', $atoken ? $atoken['atoken_name'] : '', ''), '$token' => array('token', t('Login Password') . ' <span class="required">*</span>', $atoken ? $atoken['atoken_token'] : autoname(8), ''), '$expires' => array('expires', t('Expires (yyyy-mm-dd)'), $atoken['atoken_expires'] && $atoken['atoken_expires'] > NULL_DATE ? datetime_convert('UTC', date_default_timezone_get(), $atoken['atoken_expires']) : '', ''), '$them' => t('Their Settings'), '$me' => t('My Settings'), '$perms' => $perms, '$inherited' => t('inherited'), '$notself' => '1', '$permlbl' => t('Individual Permissions'), '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'), '$submit' => t('Submit'))); return $o; }
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; } }
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; }
function get() { require_once 'include/acl_selectors.php'; require_once 'include/permissions.php'; $yes_no = array(t('No'), t('Yes')); $p = q("SELECT * FROM `profile` WHERE `is_default` = 1 AND `uid` = %d LIMIT 1", intval(local_channel())); if (count($p)) { $profile = $p[0]; } load_pconfig(local_channel(), 'expire'); $channel = \App::get_channel(); $global_perms = \Zotlabs\Access\Permissions::Perms(); $permiss = array(); $perm_opts = array(array(t('Nobody except yourself'), 0), array(t('Only those you specifically allow'), PERMS_SPECIFIC), array(t('Approved connections'), PERMS_CONTACTS), array(t('Any connections'), PERMS_PENDING), array(t('Anybody on this website'), PERMS_SITE), array(t('Anybody in this network'), PERMS_NETWORK), array(t('Anybody authenticated'), PERMS_AUTHED), array(t('Anybody on the internet'), PERMS_PUBLIC)); $limits = \Zotlabs\Access\PermissionLimits::Get(local_channel()); foreach ($global_perms as $k => $perm) { $options = array(); foreach ($perm_opts as $opt) { if (!strstr($k, 'view') && $opt[1] == PERMS_PUBLIC) { continue; } $options[$opt[1]] = $opt[0]; } $permiss[] = array($k, $perm, $limits[$k], '', $options); } $username = $channel['channel_name']; $nickname = $channel['channel_address']; $timezone = $channel['channel_timezone']; $notify = $channel['channel_notifyflags']; $defloc = $channel['channel_location']; $maxreq = $channel['channel_max_friend_req']; $expire = $channel['channel_expire_days']; $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT); $sys_expire = get_config('system', 'default_expire_days'); // $unkmail = \App::$user['unkmail']; // $cntunkmail = \App::$user['cntunkmail']; $hide_presence = intval(get_pconfig(local_channel(), 'system', 'hide_online_status')); $expire_items = get_pconfig(local_channel(), 'expire', 'items'); $expire_items = $expire_items === false ? '1' : $expire_items; // default if not set: 1 $expire_notes = get_pconfig(local_channel(), 'expire', 'notes'); $expire_notes = $expire_notes === false ? '1' : $expire_notes; // default if not set: 1 $expire_starred = get_pconfig(local_channel(), 'expire', 'starred'); $expire_starred = $expire_starred === false ? '1' : $expire_starred; // default if not set: 1 $expire_photos = get_pconfig(local_channel(), 'expire', 'photos'); $expire_photos = $expire_photos === false ? '0' : $expire_photos; // default if not set: 0 $expire_network_only = get_pconfig(local_channel(), 'expire', 'network_only'); $expire_network_only = $expire_network_only === false ? '0' : $expire_network_only; // default if not set: 0 $suggestme = get_pconfig(local_channel(), 'system', 'suggestme'); $suggestme = $suggestme === false ? '0' : $suggestme; // default if not set: 0 $post_newfriend = get_pconfig(local_channel(), 'system', 'post_newfriend'); $post_newfriend = $post_newfriend === false ? '0' : $post_newfriend; // default if not set: 0 $post_joingroup = get_pconfig(local_channel(), 'system', 'post_joingroup'); $post_joingroup = $post_joingroup === false ? '0' : $post_joingroup; // default if not set: 0 $post_profilechange = get_pconfig(local_channel(), 'system', 'post_profilechange'); $post_profilechange = $post_profilechange === false ? '0' : $post_profilechange; // default if not set: 0 $blocktags = get_pconfig(local_channel(), 'system', 'blocktags'); $blocktags = $blocktags === false ? '0' : $blocktags; $timezone = date_default_timezone_get(); $opt_tpl = get_markup_template("field_checkbox.tpl"); if (get_config('system', 'publish_all')) { $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />'; } else { $profile_in_dir = replace_macros($opt_tpl, array('$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no))); } $suggestme = replace_macros($opt_tpl, array('$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no))); $subdir = strlen(\App::get_path()) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : ''; $tpl_addr = get_markup_template("settings_nick_set.tpl"); $prof_addr = replace_macros($tpl_addr, array('$desc' => t('Your channel address is'), '$nickname' => $nickname, '$subdir' => $subdir, '$basepath' => \App::get_hostname())); $stpl = get_markup_template('settings.tpl'); $acl = new \Zotlabs\Access\AccessList($channel); $perm_defaults = $acl->get(); require_once 'include/group.php'; $group_select = mini_group_select(local_channel(), $channel['channel_default_group']); require_once 'include/menu.php'; $m1 = menu_list(local_channel()); $menu = false; if ($m1) { $menu = array(); $current = get_pconfig(local_channel(), 'system', 'channel_menu'); $menu[] = array('name' => '', 'selected' => !$current ? true : false); foreach ($m1 as $m) { $menu[] = array('name' => htmlspecialchars($m['menu_name'], ENT_COMPAT, 'UTF-8'), 'selected' => $m['menu_name'] === $current ? ' selected="selected" ' : false); } } $evdays = get_pconfig(local_channel(), 'system', 'evdays'); if (!$evdays) { $evdays = 3; } $permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role'); if (!$permissions_role) { $permissions_role = 'custom'; } $permissions_set = $permissions_role != 'custom' ? true : false; $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); if (get_account_techlevel() < 4 && $permissions_role !== 'custom') { unset($perm_roles[t('Other')]); } $vnotify = get_pconfig(local_channel(), 'system', 'vnotify'); $always_show_in_notices = get_pconfig(local_channel(), 'system', 'always_show_in_notices'); if ($vnotify === false) { $vnotify = -1; } $o .= replace_macros($stpl, array('$ptitle' => t('Channel Settings'), '$submit' => t('Submit'), '$baseurl' => z_root(), '$uid' => local_channel(), '$form_security_token' => get_form_security_token("settings"), '$nickname_block' => $prof_addr, '$h_basic' => t('Basic Settings'), '$username' => array('username', t('Full Name:'), $username, ''), '$email' => array('email', t('Email Address:'), $email, ''), '$timezone' => array('timezone_select', t('Your Timezone:'), $timezone, '', get_timezones()), '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')), '$allowloc' => array('allow_location', t('Use Browser Location:'), get_pconfig(local_channel(), 'system', 'use_browser_location') ? 1 : '', '', $yes_no), '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no), '$h_prv' => t('Security and Privacy Settings'), '$permissions_set' => $permissions_set, '$server_role' => \Zotlabs\Lib\System::get_server_role(), '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'), '$hide_presence' => array('hide_presence', t('Hide my online presence'), $hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no), '$lbl_pmacro' => t('Simple Privacy Settings:'), '$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'), '$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'), '$pmacro1' => t('Private - <em>default private, never open or public</em>'), '$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'), '$permiss_arr' => $permiss, '$blocktags' => array('blocktags', t('Allow others to tag your posts'), 1 - $blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no), '$lbl_p2macro' => t('Channel Permission Limits'), '$expire' => array('expire', t('Expire other channel content after this many days'), $expire, t('0 or blank to use the website limit.') . ' ' . (intval($sys_expire) ? sprintf(t('This website expires after %d days.'), intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')), '$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']), t('May reduce spam activity')), '$permissions' => t('Default Access Control List (ACL)'), '$permdesc' => t("(click to open/close)"), '$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))), '$allow_cid' => acl2json($perm_defaults['allow_cid']), '$allow_gid' => acl2json($perm_defaults['allow_gid']), '$deny_cid' => acl2json($perm_defaults['deny_cid']), '$deny_gid' => acl2json($perm_defaults['deny_gid']), '$suggestme' => $suggestme, '$group_select' => $group_select, '$role' => array('permissions_role', t('Channel permissions category:'), $permissions_role, '', $perm_roles), '$profile_in_dir' => $profile_in_dir, '$hide_friends' => $hide_friends, '$hide_wall' => $hide_wall, '$unkmail' => $unkmail, '$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']), t("Useful to reduce spamming")), '$h_not' => t('Notification Settings'), '$activity_options' => t('By default post a status message when:'), '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no), '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no), '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no), '$lbl_not' => t('Send a notification email when:'), '$notify1' => array('notify1', t('You receive a connection request'), $notify & NOTIFY_INTRO, NOTIFY_INTRO, '', $yes_no), '$notify2' => array('notify2', t('Your connections are confirmed'), $notify & NOTIFY_CONFIRM, NOTIFY_CONFIRM, '', $yes_no), '$notify3' => array('notify3', t('Someone writes on your profile wall'), $notify & NOTIFY_WALL, NOTIFY_WALL, '', $yes_no), '$notify4' => array('notify4', t('Someone writes a followup comment'), $notify & NOTIFY_COMMENT, NOTIFY_COMMENT, '', $yes_no), '$notify5' => array('notify5', t('You receive a private message'), $notify & NOTIFY_MAIL, NOTIFY_MAIL, '', $yes_no), '$notify6' => array('notify6', t('You receive a friend suggestion'), $notify & NOTIFY_SUGGEST, NOTIFY_SUGGEST, '', $yes_no), '$notify7' => array('notify7', t('You are tagged in a post'), $notify & NOTIFY_TAGSELF, NOTIFY_TAGSELF, '', $yes_no), '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), $notify & NOTIFY_POKE, NOTIFY_POKE, '', $yes_no), '$lbl_vnot' => t('Show visual notifications including:'), '$vnotify1' => array('vnotify1', t('Unseen grid activity'), $vnotify & VNOTIFY_NETWORK, VNOTIFY_NETWORK, '', $yes_no), '$vnotify2' => array('vnotify2', t('Unseen channel activity'), $vnotify & VNOTIFY_CHANNEL, VNOTIFY_CHANNEL, '', $yes_no), '$vnotify3' => array('vnotify3', t('Unseen private messages'), $vnotify & VNOTIFY_MAIL, VNOTIFY_MAIL, t('Recommended'), $yes_no), '$vnotify4' => array('vnotify4', t('Upcoming events'), $vnotify & VNOTIFY_EVENT, VNOTIFY_EVENT, '', $yes_no), '$vnotify5' => array('vnotify5', t('Events today'), $vnotify & VNOTIFY_EVENTTODAY, VNOTIFY_EVENTTODAY, '', $yes_no), '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), $vnotify & VNOTIFY_BIRTHDAY, VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no), '$vnotify7' => array('vnotify7', t('System (personal) notifications'), $vnotify & VNOTIFY_SYSTEM, VNOTIFY_SYSTEM, '', $yes_no), '$vnotify8' => array('vnotify8', t('System info messages'), $vnotify & VNOTIFY_INFO, VNOTIFY_INFO, t('Recommended'), $yes_no), '$vnotify9' => array('vnotify9', t('System critical alerts'), $vnotify & VNOTIFY_ALERT, VNOTIFY_ALERT, t('Recommended'), $yes_no), '$vnotify10' => array('vnotify10', t('New connections'), $vnotify & VNOTIFY_INTRO, VNOTIFY_INTRO, t('Recommended'), $yes_no), '$vnotify11' => array('vnotify11', t('System Registrations'), $vnotify & VNOTIFY_REGISTER, VNOTIFY_REGISTER, '', $yes_no), '$always_show_in_notices' => array('always_show_in_notices', t('Also show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no), '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')), '$h_advn' => t('Advanced Account/Page Type Settings'), '$h_descadvn' => t('Change the behaviour of this account for special situations'), '$pagetype' => $pagetype, '$lbl_misc' => t('Miscellaneous Settings'), '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(), 'system', 'photo_path'), t('%Y - current year, %m - current month')), '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(), 'system', 'attach_path'), t('%Y - current year, %m - current month')), '$menus' => $menu, '$menu_desc' => t('Personal menu to display in your channel pages'), '$removeme' => t('Remove Channel'), '$removechannel' => t('Remove this channel.'), '$firefoxshare' => t('Firefox Share $Projectname provider'), '$cal_first_day' => array('first_day', t('Start calendar week on monday'), get_pconfig(local_channel(), 'system', 'cal_first_day') ? 1 : '', '', $yes_no))); call_hooks('settings_form', $o); //$o .= '</form>' . "\r\n"; return $o; }
/** * @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 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); } }
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 zotinfo($arr) { $ret = array('success' => false); $zhash = x($arr, 'guid_hash') ? $arr['guid_hash'] : ''; $zguid = x($arr, 'guid') ? $arr['guid'] : ''; $zguid_sig = x($arr, 'guid_sig') ? $arr['guid_sig'] : ''; $zaddr = x($arr, 'address') ? $arr['address'] : ''; $ztarget = x($arr, 'target') ? $arr['target'] : ''; $zsig = x($arr, 'target_sig') ? $arr['target_sig'] : ''; $zkey = x($arr, 'key') ? $arr['key'] : ''; $mindate = x($arr, 'mindate') ? $arr['mindate'] : ''; $token = x($arr, 'token') ? $arr['token'] : ''; $feed = x($arr, 'feed') ? intval($arr['feed']) : 0; if ($ztarget) { if (!$zkey || !$zsig || !rsa_verify($ztarget, base64url_decode($zsig), $zkey)) { logger('zfinger: invalid target signature'); $ret['message'] = t("invalid target signature"); return $ret; } } $ztarget_hash = $ztarget && $zsig ? make_xchan_hash($ztarget, $zsig) : ''; $r = null; if (strlen($zhash)) { $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash \n\t\t\twhere channel_hash = '%s' limit 1", dbesc($zhash)); } elseif (strlen($zguid) && strlen($zguid_sig)) { $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash \n\t\t\twhere channel_guid = '%s' and channel_guid_sig = '%s' limit 1", dbesc($zguid), dbesc($zguid_sig)); } elseif (strlen($zaddr)) { if (strpos($zaddr, '[system]') === false) { /* normal address lookup */ $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash\n\t\t\t\twhere ( channel_address = '%s' or xchan_addr = '%s' ) limit 1", dbesc($zaddr), dbesc($zaddr)); } else { /** * The special address '[system]' will return a system channel if one has been defined, * Or the first valid channel we find if there are no system channels. * * This is used by magic-auth if we have no prior communications with this site - and * returns an identity on this site which we can use to create a valid hub record so that * we can exchange signed messages. The precise identity is irrelevant. It's the hub * information that we really need at the other end - and this will return it. * */ $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash\n\t\t\t\twhere channel_system = 1 order by channel_id limit 1"); if (!$r) { $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash\n\t\t\t\t\twhere channel_removed = 0 order by channel_id limit 1"); } } } else { $ret['message'] = 'Invalid request'; return $ret; } if (!$r) { $ret['message'] = 'Item not found.'; return $ret; } $e = $r[0]; $id = $e['channel_id']; $sys_channel = intval($e['channel_system']) ? true : false; $special_channel = $e['channel_pageflags'] & PAGE_PREMIUM ? true : false; $adult_channel = $e['channel_pageflags'] & PAGE_ADULT ? true : false; $censored = $e['channel_pageflags'] & PAGE_CENSORED ? true : false; $searchable = $e['channel_pageflags'] & PAGE_HIDDEN ? false : true; $deleted = intval($e['xchan_deleted']) ? true : false; if ($deleted || $censored || $sys_channel) { $searchable = false; } $public_forum = false; $role = get_pconfig($e['channel_id'], 'system', 'permissions_role'); if ($role === 'forum' || $role === 'repository') { $public_forum = true; } elseif ($ztarget_hash) { // check if it has characteristics of a public forum based on custom permissions. $m = \Zotlabs\Access\Permissions::FilledAutoperms($e['channel_id']); if ($m) { foreach ($m as $k => $v) { if ($k == 'tag_deliver' && intval($v) == 1) { $ch++; } if ($k == 'send_stream' && intval($v) == 0) { $ch++; } } if ($ch == 2) { $public_forum = true; } } } // This is for birthdays and keywords, but must check access permissions $p = q("select * from profile where uid = %d and is_default = 1", intval($e['channel_id'])); $profile = array(); if ($p) { if (!intval($p[0]['publish'])) { $searchable = false; } $profile['description'] = $p[0]['pdesc']; $profile['birthday'] = $p[0]['dob']; if ($profile['birthday'] != '0000-00-00' && ($bd = z_birthday($p[0]['dob'], $e['channel_timezone'])) !== '') { $profile['next_birthday'] = $bd; } if ($age = age($p[0]['dob'], $e['channel_timezone'], '')) { $profile['age'] = $age; } $profile['gender'] = $p[0]['gender']; $profile['marital'] = $p[0]['marital']; $profile['sexual'] = $p[0]['sexual']; $profile['locale'] = $p[0]['locality']; $profile['region'] = $p[0]['region']; $profile['postcode'] = $p[0]['postal_code']; $profile['country'] = $p[0]['country_name']; $profile['about'] = $p[0]['about']; $profile['homepage'] = $p[0]['homepage']; $profile['hometown'] = $p[0]['hometown']; if ($p[0]['keywords']) { $tags = array(); $k = explode(' ', $p[0]['keywords']); if ($k) { foreach ($k as $kk) { if (trim($kk, " \t\n\r\v,")) { $tags[] = trim($kk, " \t\n\r\v,"); } } } if ($tags) { $profile['keywords'] = $tags; } } } $ret['success'] = true; // Communication details if ($token) { $ret['signed_token'] = base64url_encode(rsa_sign('token.' . $token, $e['channel_prvkey'])); } $ret['guid'] = $e['xchan_guid']; $ret['guid_sig'] = $e['xchan_guid_sig']; $ret['key'] = $e['xchan_pubkey']; $ret['name'] = $e['xchan_name']; $ret['name_updated'] = $e['xchan_name_date']; $ret['address'] = $e['xchan_addr']; $ret['photo_mimetype'] = $e['xchan_photo_mimetype']; $ret['photo'] = $e['xchan_photo_l']; $ret['photo_updated'] = $e['xchan_photo_date']; $ret['url'] = $e['xchan_url']; $ret['connections_url'] = $e['xchan_connurl'] ? $e['xchan_connurl'] : z_root() . '/poco/' . $e['channel_address']; $ret['target'] = $ztarget; $ret['target_sig'] = $zsig; $ret['searchable'] = $searchable; $ret['adult_content'] = $adult_channel; $ret['public_forum'] = $public_forum; if ($deleted) { $ret['deleted'] = $deleted; } if (intval($e['channel_removed'])) { $ret['deleted_locally'] = true; } // premium or other channel desiring some contact with potential followers before connecting. // This is a template - %s will be replaced with the follow_url we discover for the return channel. if ($special_channel) { $ret['connect_url'] = z_root() . '/connect/' . $e['channel_address']; } // This is a template for our follow url, %s will be replaced with a webbie $ret['follow_url'] = z_root() . '/follow?f=&url=%s'; $permissions = get_all_perms($e['channel_id'], $ztarget_hash, false); if ($ztarget_hash) { $permissions['connected'] = false; $b = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc($ztarget_hash), intval($e['channel_id'])); if ($b) { $permissions['connected'] = true; } } $ret['permissions'] = $ztarget && $zkey ? crypto_encapsulate(json_encode($permissions), $zkey) : $permissions; if ($permissions['view_profile']) { $ret['profile'] = $profile; } // array of (verified) hubs this channel uses $x = zot_encode_locations($e); if ($x) { $ret['locations'] = $x; } $ret['site'] = array(); $ret['site']['url'] = z_root(); $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(), $e['channel_prvkey'])); $ret['site']['zot_auth'] = z_root() . '/magic'; $dirmode = get_config('system', 'directory_mode'); if ($dirmode === false || $dirmode == DIRECTORY_MODE_NORMAL) { $ret['site']['directory_mode'] = 'normal'; } if ($dirmode == DIRECTORY_MODE_PRIMARY) { $ret['site']['directory_mode'] = 'primary'; } elseif ($dirmode == DIRECTORY_MODE_SECONDARY) { $ret['site']['directory_mode'] = 'secondary'; } elseif ($dirmode == DIRECTORY_MODE_STANDALONE) { $ret['site']['directory_mode'] = 'standalone'; } if ($dirmode != DIRECTORY_MODE_NORMAL) { $ret['site']['directory_url'] = z_root() . '/dirsearch'; } // hide detailed site information if you're off the grid if ($dirmode != DIRECTORY_MODE_STANDALONE) { $register_policy = intval(get_config('system', 'register_policy')); if ($register_policy == REGISTER_CLOSED) { $ret['site']['register_policy'] = 'closed'; } if ($register_policy == REGISTER_APPROVE) { $ret['site']['register_policy'] = 'approve'; } if ($register_policy == REGISTER_OPEN) { $ret['site']['register_policy'] = 'open'; } $access_policy = intval(get_config('system', 'access_policy')); if ($access_policy == ACCESS_PRIVATE) { $ret['site']['access_policy'] = 'private'; } if ($access_policy == ACCESS_PAID) { $ret['site']['access_policy'] = 'paid'; } if ($access_policy == ACCESS_FREE) { $ret['site']['access_policy'] = 'free'; } if ($access_policy == ACCESS_TIERED) { $ret['site']['access_policy'] = 'tiered'; } $ret['site']['accounts'] = account_total(); require_once 'include/channel.php'; $ret['site']['channels'] = channel_total(); $ret['site']['admin'] = get_config('system', 'admin_email'); $visible_plugins = array(); if (is_array(App::$plugins) && count(App::$plugins)) { $r = q("select * from addon where hidden = 0"); if ($r) { foreach ($r as $rr) { $visible_plugins[] = $rr['name']; } } } $ret['site']['plugins'] = $visible_plugins; $ret['site']['sitehash'] = get_config('system', 'location_hash'); $ret['site']['sitename'] = get_config('system', 'sitename'); $ret['site']['sellpage'] = get_config('system', 'sellpage'); $ret['site']['location'] = get_config('system', 'site_location'); $ret['site']['realm'] = get_directory_realm(); $ret['site']['project'] = Zotlabs\Lib\System::get_platform_name() . ' ' . Zotlabs\Lib\System::get_server_role(); $ret['site']['version'] = Zotlabs\Lib\System::get_project_version(); } check_zotinfo($e, $x, $ret); call_hooks('zot_finger', $ret); return $ret; }
/** * @brief Checks if given permission is allowed for given observer on a channel. * * Checks if the given observer with the hash $observer_xchan has permission * $permission on channel_id $uid. * $permission is one defined in get_perms(); * * @param int $uid The channel_id associated with the resource owner * @param string $observer_xchan The xchan_hash representing the observer * @param string $permission * @return bool true if permission is allowed for observer on channel */ function perm_is_allowed($uid, $observer_xchan, $permission) { $api = App::get_oauth_key(); if ($api) { return api_perm_is_allowed($uid, $api, $permission); } $arr = array('channel_id' => $uid, 'observer_hash' => $observer_xchan, 'permission' => $permission, 'result' => false); call_hooks('perm_is_allowed', $arr); if ($arr['result']) { return true; } $global_perms = \Zotlabs\Access\Permissions::Perms(); // First find out what the channel owner declared permissions to be. $channel_perm = \Zotlabs\Access\PermissionLimits::Get($uid, $permission); $r = q("select channel_pageflags, channel_moved, channel_hash from channel where channel_id = %d limit 1", intval($uid)); if (!$r) { return false; } $blocked_anon_perms = \Zotlabs\Access\Permissions::BlockedAnonPerms(); if ($observer_xchan) { if ($channel_perm & PERMS_AUTHED) { return true; } $x = q("select abook_my_perms, abook_blocked, abook_ignored, abook_pending, xchan_network from abook left join xchan on abook_xchan = xchan_hash \n\t\t\twhere abook_channel = %d and abook_xchan = '%s' and abook_self = 0 limit 1", intval($uid), dbesc($observer_xchan)); // If they're blocked - they can't read or write if ($x && intval($x[0]['abook_blocked'])) { return false; } if ($x && in_array($permission, $blocked_anon_perms) && intval($x[0]['abook_ignored'])) { return false; } if (!$x) { // see if they've got a guest access token $y = atoken_abook($uid, $observer_xchan); if ($y) { $x = array($y); } if (!$x) { // not in address book and no guest token, see if they've got an xchan $y = q("select xchan_network from xchan where xchan_hash = '%s' limit 1", dbesc($observer_xchan)); if ($y) { $x = array(pseudo_abook($y[0])); } } } $abperms = load_abconfig($uid, $observer_xchan, 'my_perms'); } // system is blocked to anybody who is not authenticated if (!$observer_xchan && intval(get_config('system', 'block_public'))) { return false; } // Check if this $uid is actually the $observer_xchan // you will have full access unless the channel was moved - // in which case you will have read_only access if ($r[0]['channel_hash'] === $observer_xchan) { if ($r[0]['channel_moved'] && in_array($permission, $blocked_anon_perms)) { return false; } else { return true; } } if ($channel_perm & PERMS_PUBLIC) { return true; } // If it's an unauthenticated observer, we only need to see if PERMS_PUBLIC is set if (!$observer_xchan) { return false; } // If we're still here, we have an observer, check the network. if ($channel_perm & PERMS_NETWORK) { if ($x && $x[0]['xchan_network'] === 'zot' || $y && $y[0]['xchan_network'] === 'zot') { return true; } } // If PERMS_SITE is specified, find out if they've got an account on this hub if ($channel_perm & PERMS_SITE) { $c = q("select channel_hash from channel where channel_hash = '%s' limit 1", dbesc($observer_xchan)); if ($c) { return true; } return false; } // From here on we require that the observer be a connection and // handle whether we're allowing any, approved or specific ones if (!$x) { return false; } // They are in your address book, but haven't been approved if ($channel_perm & PERMS_PENDING) { return true; } if (intval($x[0]['abook_pending'])) { return false; } // They're a contact, so they have permission if ($channel_perm & PERMS_CONTACTS) { // it was a fake abook entry, not really a connection if (array_key_exists('abook_pseudo', $x[0]) && intval($x[0]['abook_pseudo'])) { return false; } return true; } // Permission granted to certain channels. Let's see if the observer is one of them if ($r && $channel_perm & PERMS_SPECIFIC) { if ($abperms) { foreach ($abperms as $ab) { if ($ab['cat'] == 'my_perms' && $ab['k'] == $permission) { return intval($ab['v']) ? true : false; } } } } // No permissions allowed. return false; }
function get() { $sort_type = 0; $o = ''; if (!local_channel()) { notice(t('Permission denied.') . EOL); return login(); } $channel = \App::get_channel(); $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']) { $my_perms = $x['perms_connect']; } } $yes_no = array(t('No'), t('Yes')); if ($my_perms) { $o .= "<script>function connectDefaultShare() {\n\t\t\t\$('.abook-edit-me').each(function() {\n\t\t\t\tif(! \$(this).is(':disabled'))\n\t\t\t\t\t\$(this).prop('checked', false);\n\t\t\t});\n\n"; $perms = get_perms(); foreach ($perms as $p => $v) { if ($my_perms & $v[1]) { $o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n"; } } $o .= " }\n</script>\n"; } if (argc() == 3) { $contact_id = intval(argv(1)); if (!$contact_id) { return; } $cmd = argv(2); $orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash\n\t\t\t\tWHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1", intval($contact_id), intval(local_channel())); if (!count($orig_record)) { notice(t('Could not access address book record.') . EOL); goaway(z_root() . '/connections'); } if ($cmd === 'update') { // pull feed and consume it, which should subscribe to the hub. \Zotlabs\Daemon\Master::Summon(array('Poller', $contact_id)); goaway(z_root() . '/connedit/' . $contact_id); } if ($cmd === 'resetphoto') { q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s' limit 1", dbesc($orig_record[0]['xchan_hash'])); $cmd = 'refresh'; } if ($cmd === 'refresh') { if ($orig_record[0]['xchan_network'] === 'zot') { if (!zot_refresh($orig_record[0], \App::get_channel())) { notice(t('Refresh failed - channel is currently unavailable.')); } } else { // if you are on a different network we'll force a refresh of the connection basic info \Zotlabs\Daemon\Master::Summon(array('Notifier', 'permission_update', $contact_id)); } goaway(z_root() . '/connedit/' . $contact_id); } if ($cmd === 'block') { if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_BLOCKED)) { $this->connedit_clone($a); } else { notice(t('Unable to set address book parameters.') . EOL); } goaway(z_root() . '/connedit/' . $contact_id); } if ($cmd === 'ignore') { if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_IGNORED)) { $this->connedit_clone($a); } else { notice(t('Unable to set address book parameters.') . EOL); } goaway(z_root() . '/connedit/' . $contact_id); } if ($cmd === 'archive') { if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_ARCHIVED)) { $this->connedit_clone($a); } else { notice(t('Unable to set address book parameters.') . EOL); } goaway(z_root() . '/connedit/' . $contact_id); } if ($cmd === 'hide') { if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_HIDDEN)) { $this->connedit_clone($a); } else { notice(t('Unable to set address book parameters.') . EOL); } goaway(z_root() . '/connedit/' . $contact_id); } // We'll prevent somebody from unapproving an already approved contact. // Though maybe somebody will want this eventually (??) if ($cmd === 'approve') { if (intval($orig_record[0]['abook_pending'])) { if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_PENDING)) { $this->connedit_clone($a); } else { notice(t('Unable to set address book parameters.') . EOL); } } goaway(z_root() . '/connedit/' . $contact_id); } if ($cmd === 'drop') { // FIXME // We need to send either a purge or a refresh packet to the other side (the channel being unfriended). // The issue is that the abook DB record _may_ get destroyed when we call contact_remove. As the notifier runs // in the background there could be a race condition preventing this packet from being sent in all cases. // PLACEHOLDER contact_remove(local_channel(), $orig_record[0]['abook_id']); build_sync_packet(0, array('abook' => array(array('abook_xchan' => $orig_record[0]['abook_xchan'], 'entry_deleted' => true)))); info(t('Connection has been removed.') . EOL); if (x($_SESSION, 'return_url')) { goaway(z_root() . '/' . $_SESSION['return_url']); } goaway(z_root() . '/contacts'); } } if (\App::$poi) { $contact_id = \App::$poi['abook_id']; $contact = \App::$poi; $tools = array('view' => array('label' => t('View Profile'), 'url' => chanlink_cid($contact['abook_id']), 'sel' => '', 'title' => sprintf(t('View %s\'s profile'), $contact['xchan_name'])), 'refresh' => array('label' => t('Refresh Permissions'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/refresh', 'sel' => '', 'title' => t('Fetch updated permissions')), 'recent' => array('label' => t('Recent Activity'), 'url' => z_root() . '/network/?f=&cid=' . $contact['abook_id'], 'sel' => '', 'title' => t('View recent posts and comments')), 'block' => array('label' => intval($contact['abook_blocked']) ? t('Unblock') : t('Block'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block', 'sel' => intval($contact['abook_blocked']) ? 'active' : '', 'title' => t('Block (or Unblock) all communications with this connection'), 'info' => intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''), 'ignore' => array('label' => intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore', 'sel' => intval($contact['abook_ignored']) ? 'active' : '', 'title' => t('Ignore (or Unignore) all inbound communications from this connection'), 'info' => intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''), 'archive' => array('label' => intval($contact['abook_archived']) ? t('Unarchive') : t('Archive'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive', 'sel' => intval($contact['abook_archived']) ? 'active' : '', 'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'), 'info' => intval($contact['abook_archived']) ? t('This connection is archived!') : ''), 'hide' => array('label' => intval($contact['abook_hidden']) ? t('Unhide') : t('Hide'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide', 'sel' => intval($contact['abook_hidden']) ? 'active' : '', 'title' => t('Hide or Unhide this connection from your other connections'), 'info' => intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''), 'delete' => array('label' => t('Delete'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/drop', 'sel' => '', 'title' => t('Delete this connection'))); $self = false; if (intval($contact['abook_self'])) { $self = true; } $tpl = get_markup_template("abook_edit.tpl"); if (feature_enabled(local_channel(), 'affinity')) { $labels = array(t('Me'), t('Family'), t('Friends'), t('Acquaintances'), t('All')); call_hooks('affinity_labels', $labels); $label_str = ''; if ($labels) { foreach ($labels as $l) { if ($label_str) { $label_str .= ", '|'"; $label_str .= ", '" . $l . "'"; } else { $label_str .= "'" . $l . "'"; } } } $slider_tpl = get_markup_template('contact_slider.tpl'); $slide = replace_macros($slider_tpl, array('$min' => 1, '$val' => $contact['abook_closeness'] ? $contact['abook_closeness'] : 99, '$labels' => $label_str)); } $rating_val = 0; $rating_text = ''; $xl = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1", dbesc($channel['channel_hash']), dbesc($contact['xchan_hash'])); if ($xl) { $rating_val = intval($xl[0]['xlink_rating']); $rating_text = $xl[0]['xlink_rating_text']; } $poco_rating = get_config('system', 'poco_rating_enable'); // if unset default to enabled if ($poco_rating === false) { $poco_rating = true; } if ($poco_rating) { $rating = replace_macros(get_markup_template('rating_slider.tpl'), array('$min' => -10, '$val' => $rating_val)); } else { $rating = false; } $perms = array(); $channel = \App::get_channel(); $global_perms = \Zotlabs\Access\Permissions::Perms(); $existing = get_all_perms(local_channel(), $contact['abook_xchan']); $unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'), 'Yes')); $multiprofs = feature_enabled(local_channel(), 'multi_profiles') ? true : false; if ($slide && !$multiprofs) { $affinity = t('Set Affinity'); } if (!$slide && $multiprofs) { $affinity = t('Set Profile'); } if ($slide && $multiprofs) { $affinity = t('Set Affinity & Profile'); } $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", intval(local_channel()), dbesc($contact['abook_xchan'])); $their_perms = array(); if ($theirs) { foreach ($theirs as $t) { $their_perms[$t['k']] = $t['v']; } } foreach ($global_perms as $k => $v) { $thisperm = get_abconfig(local_channel(), $contact['abook_xchan'], 'my_perms', $k); //fixme $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(), $k); // For auto permissions (when $self is true) we don't want to look at existing // permissions because they are enabled for the channel owner if (!$self && $existing[$k]) { $thisperm = "1"; } $perms[] = array('perms_' . $k, $v, array_key_exists($k, $their_perms) ? intval($their_perms[$k]) : '', $thisperm, 1, $checkinherited & PERMS_SPECIFIC ? '' : '1', '', $checkinherited); } $locstr = ''; $locs = q("select hubloc_addr as location from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s'\n\t\t\t\tand hubloc_deleted = 0 and site_dead = 0", dbesc($contact['xchan_hash'])); if ($locs) { foreach ($locs as $l) { if (!$l['location']) { continue; } if (strpos($locstr, $l['location']) !== false) { continue; } if (strlen($locstr)) { $locstr .= ', '; } $locstr .= $l['location']; } } else { $locstr = t('none'); } $o .= replace_macros($tpl, array('$header' => $self ? t('Connection Default Permissions') : sprintf(t('Connection: %s'), $contact['xchan_name']), '$autoperms' => array('autoperms', t('Apply these permissions automatically'), get_pconfig(local_channel(), 'system', 'autoperms') ? 1 : 0, t('Connection requests will be approved without your interaction'), $yes_no), '$addr' => $contact['xchan_addr'], '$addr_text' => t('This connection\'s primary address is'), '$loc_text' => t('Available locations:'), '$locstr' => $locstr, '$notself' => $self ? '' : '1', '$self' => $self ? '1' : '', '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'), '$tools_label' => t('Connection Tools'), '$tools' => $self ? '' : $tools, '$lbl_slider' => t('Slide to adjust your degree of friendship'), '$lbl_rating' => t('Rating'), '$lbl_rating_label' => t('Slide to adjust your rating'), '$lbl_rating_txt' => t('Optionally explain your rating'), '$connfilter' => feature_enabled(local_channel(), 'connfilter'), '$connfilter_label' => t('Custom Filter'), '$incl' => array('abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')), '$excl' => array('abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')), '$rating_text' => array('rating_text', t('Optionally explain your rating'), $rating_text, ''), '$rating_info' => t('This information is public!'), '$rating' => $rating, '$rating_val' => $rating_val, '$slide' => $slide, '$affinity' => $affinity, '$pending_label' => t('Connection Pending Approval'), '$is_pending' => intval($contact['abook_pending']) ? 1 : '', '$unapproved' => $unapproved, '$inherited' => t('inherited'), '$submit' => t('Submit'), '$lbl_vis2' => sprintf(t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']), '$close' => $contact['abook_closeness'], '$them' => t('Their Settings'), '$me' => t('My Settings'), '$perms' => $perms, '$permlbl' => t('Individual Permissions'), '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'), '$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'), '$lastupdtext' => t('Last update:'), '$last_update' => relative_date($contact['abook_connected']), '$profile_select' => contact_profile_assign($contact['abook_profile']), '$multiprofs' => $multiprofs, '$contact_id' => $contact['abook_id'], '$name' => $contact['xchan_name'])); $arr = array('contact' => $contact, 'output' => $o); call_hooks('contact_edit', $arr); return $arr['output']; } }
function get() { $o = ''; nav_set_selected('settings'); if (!local_channel() || $_SESSION['delegate']) { notice(t('Permission denied.') . EOL); return login(); } $channel = \App::get_channel(); if ($channel) { head_set_icon($channel['xchan_photo_s']); } $yes_no = array(t('No'), t('Yes')); if (argc() > 1 && argv(1) === 'oauth') { if (argc() > 2 && argv(2) === 'add') { $tpl = get_markup_template("settings_oauth_edit.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_oauth"), '$title' => t('Add application'), '$submit' => t('Submit'), '$cancel' => t('Cancel'), '$name' => array('name', t('Name'), '', t('Name of application')), '$key' => array('key', t('Consumer Key'), random_string(16), t('Automatically generated - change if desired. Max length 20')), '$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')), '$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')), '$icon' => array('icon', t('Icon url'), '', t('Optional')))); return $o; } if (argc() > 3 && argv(2) === 'edit') { $r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d", dbesc(argv(3)), local_channel()); if (!count($r)) { notice(t('Application not found.')); return; } $app = $r[0]; $tpl = get_markup_template("settings_oauth_edit.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_oauth"), '$title' => t('Add application'), '$submit' => t('Update'), '$cancel' => t('Cancel'), '$name' => array('name', t('Name'), $app['clname'], ''), '$key' => array('key', t('Consumer Key'), $app['client_id'], ''), '$secret' => array('secret', t('Consumer Secret'), $app['pw'], ''), '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], ''), '$icon' => array('icon', t('Icon url'), $app['icon'], ''))); return $o; } if (argc() > 3 && argv(2) === 'delete') { check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't'); $r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d", dbesc(argv(3)), local_channel()); goaway(z_root() . "/settings/oauth/"); return; } $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my \n\t\t\t\t\tFROM clients\n\t\t\t\t\tLEFT JOIN tokens ON clients.client_id=tokens.client_id\n\t\t\t\t\tWHERE clients.uid IN (%d,0)", local_channel(), local_channel()); $tpl = get_markup_template("settings_oauth.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_oauth"), '$baseurl' => z_root(), '$title' => t('Connected Apps'), '$add' => t('Add application'), '$edit' => t('Edit'), '$delete' => t('Delete'), '$consumerkey' => t('Client key starts with'), '$noname' => t('No name'), '$remove' => t('Remove authorization'), '$apps' => $r)); return $o; } if (argc() > 1 && argv(1) === 'featured') { $settings_addons = ""; $o = ''; $r = q("SELECT * FROM `hook` WHERE `hook` = 'feature_settings' "); if (!$r) { $settings_addons = t('No feature settings configured'); } call_hooks('feature_settings', $settings_addons); $tpl = get_markup_template("settings_addons.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_featured"), '$title' => t('Feature/Addon Settings'), '$settings_addons' => $settings_addons)); return $o; } /* * ACCOUNT SETTINGS */ if (argc() > 1 && argv(1) === 'account') { $account_settings = ""; call_hooks('account_settings', $account_settings); $email = \App::$account['account_email']; $tpl = get_markup_template("settings_account.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_account"), '$title' => t('Account Settings'), '$origpass' => array('origpass', t('Current Password'), ' ', ''), '$password1' => array('npassword', t('Enter New Password'), '', ''), '$password2' => array('confirm', t('Confirm New Password'), '', t('Leave password fields blank unless changing')), '$submit' => t('Submit'), '$email' => array('email', t('Email Address:'), $email, ''), '$removeme' => t('Remove Account'), '$removeaccount' => t('Remove this account including all its channels'), '$account_settings' => $account_settings)); return $o; } if (argc() > 1 && argv(1) === 'tokens') { $atoken = null; $atoken_xchan = ''; if (argc() > 2) { $id = argv(2); $atoken = q("select * from atoken where atoken_id = %d and atoken_uid = %d", intval($id), intval(local_channel())); if ($atoken) { $atoken = $atoken[0]; $atoken_xchan = substr($channel['channel_hash'], 0, 16) . '.' . $atoken['atoken_name']; } if ($atoken && argc() > 3 && argv(3) === 'drop') { atoken_delete($id); $atoken = null; $atoken_xchan = ''; } } $t = q("select * from atoken where atoken_uid = %d", intval(local_channel())); $desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content.'); $desc2 = t('You may also provide <em>dropbox</em> style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:'); $global_perms = \Zotlabs\Access\Permissions::Perms(); $existing = get_all_perms(local_channel(), $atoken_xchan ? $atoken_xchan : ''); if ($atoken_xchan) { $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", intval(local_channel()), dbesc($atoken_xchan)); $their_perms = array(); if ($theirs) { foreach ($theirs as $t) { $their_perms[$t['k']] = $t['v']; } } } foreach ($global_perms as $k => $v) { $thisperm = get_abconfig(local_channel(), $contact['abook_xchan'], 'my_perms', $k); //fixme $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(), $k); if ($existing[$k]) { $thisperm = "1"; } $perms[] = array('perms_' . $k, $v, array_key_exists($k, $their_perms) ? intval($their_perms[$k]) : '', $thisperm, 1, $checkinherited & PERMS_SPECIFIC ? '' : '1', '', $checkinherited); } $tpl = get_markup_template("settings_tokens.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_tokens"), '$title' => t('Guest Access Tokens'), '$desc' => $desc, '$desc2' => $desc2, '$tokens' => $t, '$atoken' => $atoken, '$url1' => z_root() . '/channel/' . $channel['channel_address'], '$url2' => z_root() . '/photos/' . $channel['channel_address'], '$name' => array('name', t('Login Name') . ' <span class="required">*</span>', $atoken ? $atoken['atoken_name'] : '', ''), '$token' => array('token', t('Login Password') . ' <span class="required">*</span>', $atoken ? $atoken['atoken_token'] : autoname(8), ''), '$expires' => array('expires', t('Expires (yyyy-mm-dd)'), $atoken['atoken_expires'] && $atoken['atoken_expires'] != NULL_DATE ? datetime_convert('UTC', date_default_timezone_get(), $atoken['atoken_expires']) : '', ''), '$them' => t('Their Settings'), '$me' => t('My Settings'), '$perms' => $perms, '$inherited' => t('inherited'), '$notself' => '1', '$permlbl' => t('Individual Permissions'), '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'), '$submit' => t('Submit'))); return $o; } if (argc() > 1 && argv(1) === 'features') { $arr = array(); $features = get_features(); foreach ($features as $fname => $fdata) { $arr[$fname] = array(); $arr[$fname][0] = $fdata[0]; foreach (array_slice($fdata, 1) as $f) { $arr[$fname][1][] = array('feature_' . $f[0], $f[1], intval(feature_enabled(local_channel(), $f[0])) ? "1" : '', $f[2], array(t('Off'), t('On'))); } } $tpl = get_markup_template("settings_features.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_features"), '$title' => t('Additional Features'), '$features' => $arr, '$submit' => t('Submit'))); return $o; } if (argc() > 1 && argv(1) === 'connectors') { $settings_connectors = ""; call_hooks('connector_settings', $settings_connectors); $r = null; $tpl = get_markup_template("settings_connectors.tpl"); $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("settings_connectors"), '$title' => t('Connector Settings'), '$submit' => t('Submit'), '$settings_connectors' => $settings_connectors)); call_hooks('display_settings', $o); return $o; } /* * DISPLAY SETTINGS */ if (argc() > 1 && argv(1) === 'display') { $default_theme = get_config('system', 'theme'); if (!$default_theme) { $default_theme = 'default'; } $default_mobile_theme = get_config('system', 'mobile_theme'); if (!$mobile_default_theme) { $mobile_default_theme = 'none'; } $allowed_themes_str = get_config('system', 'allowed_themes'); $allowed_themes_raw = explode(',', $allowed_themes_str); $allowed_themes = array(); if (count($allowed_themes_raw)) { foreach ($allowed_themes_raw as $x) { if (strlen(trim($x)) && is_dir("view/theme/{$x}")) { $allowed_themes[] = trim($x); } } } $themes = array(); $files = glob('view/theme/*'); if ($allowed_themes) { foreach ($allowed_themes as $th) { $f = $th; $is_experimental = file_exists('view/theme/' . $th . '/experimental'); $unsupported = file_exists('view/theme/' . $th . '/unsupported'); $is_mobile = file_exists('view/theme/' . $th . '/mobile'); $is_library = file_exists('view/theme/' . $th . '/library'); $mobile_themes["---"] = t("No special theme for mobile devices"); if (!$is_experimental or $is_experimental && (get_config('experimentals', 'exp_themes') == 1 or get_config('experimentals', 'exp_themes') === false)) { $theme_name = $is_experimental ? sprintf(t('%s - (Experimental)'), $f) : $f; if (!$is_library) { if ($is_mobile) { $mobile_themes[$f] = $themes[$f] = $theme_name . ' (' . t('mobile') . ')'; } else { $mobile_themes[$f] = $themes[$f] = $theme_name; } } } } } $theme_selected = !x($_SESSION, 'theme') ? $default_theme : $_SESSION['theme']; $mobile_theme_selected = !x($_SESSION, 'mobile_theme') ? $default_mobile_theme : $_SESSION['mobile_theme']; $preload_images = get_pconfig(local_channel(), 'system', 'preload_images'); $preload_images = $preload_images === false ? '0' : $preload_images; // default if not set: 0 $user_scalable = get_pconfig(local_channel(), 'system', 'user_scalable'); $user_scalable = $user_scalable === false ? '1' : $user_scalable; // default if not set: 1 $browser_update = intval(get_pconfig(local_channel(), 'system', 'update_interval')); $browser_update = $browser_update == 0 ? 80 : $browser_update / 1000; // default if not set: 40 seconds $itemspage = intval(get_pconfig(local_channel(), 'system', 'itemspage')); $itemspage = $itemspage > 0 && $itemspage < 101 ? $itemspage : 20; // default if not set: 20 items $nosmile = get_pconfig(local_channel(), 'system', 'no_smilies'); $nosmile = $nosmile === false ? '0' : $nosmile; // default if not set: 0 $title_tosource = get_pconfig(local_channel(), 'system', 'title_tosource'); $title_tosource = $title_tosource === false ? '0' : $title_tosource; // default if not set: 0 $theme_config = ""; if (($themeconfigfile = $this->get_theme_config_file($theme_selected)) != null) { require_once $themeconfigfile; $theme_config = theme_content($a); } $tpl = get_markup_template("settings_display.tpl"); $o = replace_macros($tpl, array('$ptitle' => t('Display Settings'), '$d_tset' => t('Theme Settings'), '$d_ctset' => t('Custom Theme Settings'), '$d_cset' => t('Content Settings'), '$form_security_token' => get_form_security_token("settings_display"), '$submit' => t('Submit'), '$baseurl' => z_root(), '$uid' => local_channel(), '$theme' => $themes ? array('theme', t('Display Theme:'), $theme_selected, '', $themes, 'preview') : false, '$mobile_theme' => $mobile_themes ? array('mobile_theme', t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, '') : false, '$preload_images' => array('preload_images', t("Preload images before rendering the page"), $preload_images, t("The subjective page load time will be longer but the page will be ready when displayed"), $yes_no), '$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, '', $yes_no), '$ajaxint' => array('browser_update', t("Update browser every xx seconds"), $browser_update, t('Minimum of 10 seconds, no maximum')), '$itemspage' => array('itemspage', t("Maximum number of conversations to load at any time:"), $itemspage, t('Maximum of 100 items')), '$nosmile' => array('nosmile', t("Show emoticons (smilies) as images"), 1 - intval($nosmile), '', $yes_no), '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no), '$layout_editor' => t('System Page Layout Editor - (advanced)'), '$theme_config' => $theme_config, '$expert' => feature_enabled(local_channel(), 'expert'), '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_channel(), 'system', 'channel_list_mode'), t('(comments displayed separately)'), $yes_no), '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on grid page'), get_pconfig(local_channel(), 'system', 'network_list_mode'), t('(comments displayed separately)'), $yes_no), '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), get_pconfig(local_channel(), 'system', 'channel_divmore_height') ? get_pconfig(local_channel(), 'system', 'channel_divmore_height') : 400, t('click to expand content exceeding this height')), '$network_divmore_height' => array('network_divmore_height', t('Grid page max height of content (in pixels)'), get_pconfig(local_channel(), 'system', 'network_divmore_height') ? get_pconfig(local_channel(), 'system', 'network_divmore_height') : 400, t('click to expand content exceeding this height')))); return $o; } if (argv(1) === 'channel') { require_once 'include/acl_selectors.php'; require_once 'include/permissions.php'; $p = q("SELECT * FROM `profile` WHERE `is_default` = 1 AND `uid` = %d LIMIT 1", intval(local_channel())); if (count($p)) { $profile = $p[0]; } load_pconfig(local_channel(), 'expire'); $channel = \App::get_channel(); $global_perms = \Zotlabs\Access\Permissions::Perms(); $permiss = array(); $perm_opts = array(array(t('Nobody except yourself'), 0), array(t('Only those you specifically allow'), PERMS_SPECIFIC), array(t('Approved connections'), PERMS_CONTACTS), array(t('Any connections'), PERMS_PENDING), array(t('Anybody on this website'), PERMS_SITE), array(t('Anybody in this network'), PERMS_NETWORK), array(t('Anybody authenticated'), PERMS_AUTHED), array(t('Anybody on the internet'), PERMS_PUBLIC)); $limits = \Zotlabs\Access\PermissionLimits::Get(local_channel()); foreach ($global_perms as $k => $perm) { $options = array(); foreach ($perm_opts as $opt) { $options[$opt[1]] = $opt[0]; } $permiss[] = array($k, $perm, $limits[$k], '', $options); } //logger('permiss: ' . print_r($permiss,true)); $username = $channel['channel_name']; $nickname = $channel['channel_address']; $timezone = $channel['channel_timezone']; $notify = $channel['channel_notifyflags']; $defloc = $channel['channel_location']; $maxreq = $channel['channel_max_friend_req']; $expire = $channel['channel_expire_days']; $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT); $sys_expire = get_config('system', 'default_expire_days'); // $unkmail = \App::$user['unkmail']; // $cntunkmail = \App::$user['cntunkmail']; $hide_presence = intval(get_pconfig(local_channel(), 'system', 'hide_online_status')); $expire_items = get_pconfig(local_channel(), 'expire', 'items'); $expire_items = $expire_items === false ? '1' : $expire_items; // default if not set: 1 $expire_notes = get_pconfig(local_channel(), 'expire', 'notes'); $expire_notes = $expire_notes === false ? '1' : $expire_notes; // default if not set: 1 $expire_starred = get_pconfig(local_channel(), 'expire', 'starred'); $expire_starred = $expire_starred === false ? '1' : $expire_starred; // default if not set: 1 $expire_photos = get_pconfig(local_channel(), 'expire', 'photos'); $expire_photos = $expire_photos === false ? '0' : $expire_photos; // default if not set: 0 $expire_network_only = get_pconfig(local_channel(), 'expire', 'network_only'); $expire_network_only = $expire_network_only === false ? '0' : $expire_network_only; // default if not set: 0 $suggestme = get_pconfig(local_channel(), 'system', 'suggestme'); $suggestme = $suggestme === false ? '0' : $suggestme; // default if not set: 0 $post_newfriend = get_pconfig(local_channel(), 'system', 'post_newfriend'); $post_newfriend = $post_newfriend === false ? '0' : $post_newfriend; // default if not set: 0 $post_joingroup = get_pconfig(local_channel(), 'system', 'post_joingroup'); $post_joingroup = $post_joingroup === false ? '0' : $post_joingroup; // default if not set: 0 $post_profilechange = get_pconfig(local_channel(), 'system', 'post_profilechange'); $post_profilechange = $post_profilechange === false ? '0' : $post_profilechange; // default if not set: 0 $blocktags = get_pconfig(local_channel(), 'system', 'blocktags'); $blocktags = $blocktags === false ? '0' : $blocktags; $timezone = date_default_timezone_get(); $opt_tpl = get_markup_template("field_checkbox.tpl"); if (get_config('system', 'publish_all')) { $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />'; } else { $profile_in_dir = replace_macros($opt_tpl, array('$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no))); } $suggestme = replace_macros($opt_tpl, array('$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no))); $subdir = strlen(\App::get_path()) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : ''; $tpl_addr = get_markup_template("settings_nick_set.tpl"); $prof_addr = replace_macros($tpl_addr, array('$desc' => t('Your channel address is'), '$nickname' => $nickname, '$subdir' => $subdir, '$basepath' => \App::get_hostname())); $stpl = get_markup_template('settings.tpl'); $acl = new \Zotlabs\Access\AccessList($channel); $perm_defaults = $acl->get(); require_once 'include/group.php'; $group_select = mini_group_select(local_channel(), $channel['channel_default_group']); require_once 'include/menu.php'; $m1 = menu_list(local_channel()); $menu = false; if ($m1) { $menu = array(); $current = get_pconfig(local_channel(), 'system', 'channel_menu'); $menu[] = array('name' => '', 'selected' => !$current ? true : false); foreach ($m1 as $m) { $menu[] = array('name' => htmlspecialchars($m['menu_name'], ENT_COMPAT, 'UTF-8'), 'selected' => $m['menu_name'] === $current ? ' selected="selected" ' : false); } } $evdays = get_pconfig(local_channel(), 'system', 'evdays'); if (!$evdays) { $evdays = 3; } $permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role'); if (!$permissions_role) { $permissions_role = 'custom'; } $permissions_set = $permissions_role != 'custom' ? true : false; $vnotify = get_pconfig(local_channel(), 'system', 'vnotify'); $always_show_in_notices = get_pconfig(local_channel(), 'system', 'always_show_in_notices'); if ($vnotify === false) { $vnotify = -1; } $o .= replace_macros($stpl, array('$ptitle' => t('Channel Settings'), '$submit' => t('Submit'), '$baseurl' => z_root(), '$uid' => local_channel(), '$form_security_token' => get_form_security_token("settings"), '$nickname_block' => $prof_addr, '$h_basic' => t('Basic Settings'), '$username' => array('username', t('Full Name:'), $username, ''), '$email' => array('email', t('Email Address:'), $email, ''), '$timezone' => array('timezone_select', t('Your Timezone:'), $timezone, '', get_timezones()), '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')), '$allowloc' => array('allow_location', t('Use Browser Location:'), get_pconfig(local_channel(), 'system', 'use_browser_location') ? 1 : '', '', $yes_no), '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no), '$h_prv' => t('Security and Privacy Settings'), '$permissions_set' => $permissions_set, '$server_role' => \Zotlabs\Lib\System::get_server_role(), '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'), '$hide_presence' => array('hide_presence', t('Hide my online presence'), $hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no), '$lbl_pmacro' => t('Simple Privacy Settings:'), '$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'), '$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'), '$pmacro1' => t('Private - <em>default private, never open or public</em>'), '$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'), '$permiss_arr' => $permiss, '$blocktags' => array('blocktags', t('Allow others to tag your posts'), 1 - $blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no), '$lbl_p2macro' => t('Advanced Privacy Settings'), '$expire' => array('expire', t('Expire other channel content after this many days'), $expire, t('0 or blank to use the website limit.') . ' ' . (intval($sys_expire) ? sprintf(t('This website expires after %d days.'), intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')), '$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']), t('May reduce spam activity')), '$permissions' => t('Default Post and Publish Permissions'), '$permdesc' => t("(click to open/close)"), '$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))), '$allow_cid' => acl2json($perm_defaults['allow_cid']), '$allow_gid' => acl2json($perm_defaults['allow_gid']), '$deny_cid' => acl2json($perm_defaults['deny_cid']), '$deny_gid' => acl2json($perm_defaults['deny_gid']), '$suggestme' => $suggestme, '$group_select' => $group_select, '$role' => array('permissions_role', t('Channel permissions category:'), $permissions_role, '', get_roles()), '$profile_in_dir' => $profile_in_dir, '$hide_friends' => $hide_friends, '$hide_wall' => $hide_wall, '$unkmail' => $unkmail, '$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']), t("Useful to reduce spamming")), '$h_not' => t('Notification Settings'), '$activity_options' => t('By default post a status message when:'), '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no), '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no), '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no), '$lbl_not' => t('Send a notification email when:'), '$notify1' => array('notify1', t('You receive a connection request'), $notify & NOTIFY_INTRO, NOTIFY_INTRO, '', $yes_no), '$notify2' => array('notify2', t('Your connections are confirmed'), $notify & NOTIFY_CONFIRM, NOTIFY_CONFIRM, '', $yes_no), '$notify3' => array('notify3', t('Someone writes on your profile wall'), $notify & NOTIFY_WALL, NOTIFY_WALL, '', $yes_no), '$notify4' => array('notify4', t('Someone writes a followup comment'), $notify & NOTIFY_COMMENT, NOTIFY_COMMENT, '', $yes_no), '$notify5' => array('notify5', t('You receive a private message'), $notify & NOTIFY_MAIL, NOTIFY_MAIL, '', $yes_no), '$notify6' => array('notify6', t('You receive a friend suggestion'), $notify & NOTIFY_SUGGEST, NOTIFY_SUGGEST, '', $yes_no), '$notify7' => array('notify7', t('You are tagged in a post'), $notify & NOTIFY_TAGSELF, NOTIFY_TAGSELF, '', $yes_no), '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), $notify & NOTIFY_POKE, NOTIFY_POKE, '', $yes_no), '$lbl_vnot' => t('Show visual notifications including:'), '$vnotify1' => array('vnotify1', t('Unseen grid activity'), $vnotify & VNOTIFY_NETWORK, VNOTIFY_NETWORK, '', $yes_no), '$vnotify2' => array('vnotify2', t('Unseen channel activity'), $vnotify & VNOTIFY_CHANNEL, VNOTIFY_CHANNEL, '', $yes_no), '$vnotify3' => array('vnotify3', t('Unseen private messages'), $vnotify & VNOTIFY_MAIL, VNOTIFY_MAIL, t('Recommended'), $yes_no), '$vnotify4' => array('vnotify4', t('Upcoming events'), $vnotify & VNOTIFY_EVENT, VNOTIFY_EVENT, '', $yes_no), '$vnotify5' => array('vnotify5', t('Events today'), $vnotify & VNOTIFY_EVENTTODAY, VNOTIFY_EVENTTODAY, '', $yes_no), '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), $vnotify & VNOTIFY_BIRTHDAY, VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no), '$vnotify7' => array('vnotify7', t('System (personal) notifications'), $vnotify & VNOTIFY_SYSTEM, VNOTIFY_SYSTEM, '', $yes_no), '$vnotify8' => array('vnotify8', t('System info messages'), $vnotify & VNOTIFY_INFO, VNOTIFY_INFO, t('Recommended'), $yes_no), '$vnotify9' => array('vnotify9', t('System critical alerts'), $vnotify & VNOTIFY_ALERT, VNOTIFY_ALERT, t('Recommended'), $yes_no), '$vnotify10' => array('vnotify10', t('New connections'), $vnotify & VNOTIFY_INTRO, VNOTIFY_INTRO, t('Recommended'), $yes_no), '$vnotify11' => array('vnotify11', t('System Registrations'), $vnotify & VNOTIFY_REGISTER, VNOTIFY_REGISTER, '', $yes_no), '$always_show_in_notices' => array('always_show_in_notices', t('Also show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no), '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')), '$h_advn' => t('Advanced Account/Page Type Settings'), '$h_descadvn' => t('Change the behaviour of this account for special situations'), '$pagetype' => $pagetype, '$expert' => feature_enabled(local_channel(), 'expert'), '$hint' => t('Please enable expert mode (in <a href="settings/features">Settings > Additional features</a>) to adjust!'), '$lbl_misc' => t('Miscellaneous Settings'), '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(), 'system', 'photo_path'), t('%Y - current year, %m - current month')), '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(), 'system', 'attach_path'), t('%Y - current year, %m - current month')), '$menus' => $menu, '$menu_desc' => t('Personal menu to display in your channel pages'), '$removeme' => t('Remove Channel'), '$removechannel' => t('Remove this channel.'), '$firefoxshare' => t('Firefox Share $Projectname provider'), '$cal_first_day' => array('first_day', t('Start calendar week on monday'), get_pconfig(local_channel(), 'system', 'cal_first_day') ? 1 : '', '', $yes_no))); call_hooks('settings_form', $o); //$o .= '</form>' . "\r\n"; return $o; } }