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; }
/** * 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; }
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 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; }
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); } }
/** * @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; } }