/**
  * 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;
 }
Esempio n. 2
0
 public static function BlockedAnonPerms()
 {
     // Perms from the above list that are blocked from anonymous observers.
     // e.g. you must be authenticated.
     $res = array();
     $perms = PermissionLimits::Std_limits();
     foreach ($perms as $perm => $limit) {
         if ($limit != PERMS_PUBLIC) {
             $res[] = $perm;
         }
     }
     $x = array('permissions' => $res);
     call_hooks('write_perms', $x);
     return $x['permissions'];
 }
Esempio n. 3
0
 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;
 }
Esempio n. 4
0
/**
 * Sourced and tag-delivered posts are re-targetted for delivery to the connections of the channel
 * receiving the post. This starts the second delivery chain, by resetting permissions and ensuring
 * that ITEM_UPLINK is set on the parent post, and storing the current owner_xchan as the source_xchan.
 * We'll become the new owner. If called without $parent, this *is* the parent post.
 *
 * @param array $channel
 * @param array $item
 * @param int $item_id
 * @param boolean $parent
 */
function start_delivery_chain($channel, $item, $item_id, $parent)
{
    $sourced = check_item_source($channel['channel_id'], $item);
    if ($sourced) {
        $r = q("select * from source where src_channel_id = %d and ( src_xchan = '%s' or src_xchan = '*' ) limit 1", intval($channel['channel_id']), dbesc($item['source_xchan'] ? $item['source_xchan'] : $item['owner_xchan']));
        if ($r) {
            $t = trim($r[0]['src_tag']);
            if ($t) {
                $tags = explode(',', $t);
                if ($tags) {
                    foreach ($tags as $tt) {
                        $tt = trim($tt);
                        if ($tt) {
                            q("insert into term (uid,oid,otype,ttype,term,url)\n                \t\t\t\tvalues(%d,%d,%d,%d,'%s','%s') ", intval($channel['channel_id']), intval($item_id), intval(TERM_OBJ_POST), intval(TERM_CATEGORY), dbesc($tt), dbesc(z_root() . '/channel/' . $channel['channel_address'] . '?f=&cat=' . urlencode($tt)));
                        }
                    }
                }
            }
        }
    }
    // Change this copy of the post to a forum head message and deliver to all the tgroup members
    // also reset all the privacy bits to the forum default permissions
    $private = $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid'] ? 1 : 0;
    $new_public_policy = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_stream'), true);
    if (!$private && $new_public_policy) {
        $private = 1;
    }
    $item_wall = 1;
    $item_origin = 1;
    $item_uplink = 0;
    $item_nocomment = 0;
    $item_obscured = 0;
    $flag_bits = $item['item_flags'];
    // maintain the original source, which will be the original item owner and was stored in source_xchan
    // when we created the delivery fork
    if ($parent) {
        $r = q("update item set source_xchan = '%s' where id = %d", dbesc($parent['source_xchan']), intval($item_id));
    } else {
        $item_uplink = 1;
        $r = q("update item set source_xchan = owner_xchan where id = %d", intval($item_id));
    }
    $title = $item['title'];
    $body = $item['body'];
    $r = q("update item set item_uplink = %d, item_nocomment = %d, item_obscured = %d, item_flags = %d, owner_xchan = '%s', allow_cid = '%s', allow_gid = '%s', \n\t\tdeny_cid = '%s', deny_gid = '%s', item_private = %d, public_policy = '%s', comment_policy = '%s', title = '%s', body = '%s', item_wall = %d, item_origin = %d  where id = %d", intval($item_uplink), intval($item_nocomment), intval($item_obscured), intval($flag_bits), dbesc($channel['channel_hash']), dbesc($channel['channel_allow_cid']), dbesc($channel['channel_allow_gid']), dbesc($channel['channel_deny_cid']), dbesc($channel['channel_deny_gid']), intval($private), dbesc($new_public_policy), dbesc(map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'post_comments'))), dbesc($title), dbesc($body), intval($item_wall), intval($item_origin), intval($item_id));
    if ($r) {
        Zotlabs\Daemon\Master::Summon(array('Notifier', 'tgroup', $item_id));
    } else {
        logger('start_delivery_chain: failed to update item');
        // reset the source xchan to prevent loops
        $r = q("update item set source_xchan = '' where id = %d", intval($item_id));
    }
}
Esempio n. 5
0
function is_public_profile()
{
    if (!local_channel()) {
        return false;
    }
    if (intval(get_config('system', 'block_public'))) {
        return false;
    }
    $channel = App::get_channel();
    if ($channel) {
        $perm = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_profile');
        if ($perm == PERMS_PUBLIC) {
            return true;
        }
    }
    return false;
}
Esempio n. 6
0
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);
    }
}
Esempio n. 7
0
 function get()
 {
     $o = '';
     $channel = \App::get_channel();
     if (!local_channel()) {
         notice(t('Permission denied.') . EOL);
         return;
     }
     require_once 'include/channel.php';
     $profile_fields_basic = get_profile_fields_basic();
     $profile_fields_advanced = get_profile_fields_advanced();
     if (argc() > 1 && intval(argv(1)) || !feature_enabled(local_channel(), 'multi_profiles')) {
         if (feature_enabled(local_channel(), 'multi_profiles')) {
             $id = \App::$argv[1];
         } else {
             $x = q("select id from profile where uid = %d and is_default = 1", intval(local_channel()));
             if ($x) {
                 $id = $x[0]['id'];
             }
         }
         $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($id), intval(local_channel()));
         if (!count($r)) {
             notice(t('Profile not found.') . EOL);
             return;
         }
         $editselect = 'none';
         \App::$page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), array('$baseurl' => z_root(), '$editselect' => $editselect));
         $advanced = feature_enabled(local_channel(), 'advanced_profiles') ? true : false;
         if ($advanced) {
             $fields = $profile_fields_advanced;
         } else {
             $fields = $profile_fields_basic;
         }
         $hide_friends = array('hide_friends', t('Hide your connections list from viewers of this profile'), $r[0]['hide_friends'], '', array(t('No'), t('Yes')));
         $q = q("select * from profdef where true");
         if ($q) {
             $extra_fields = array();
             foreach ($q as $qq) {
                 $mine = q("select v from profext where k = '%s' and hash = '%s' and channel_id = %d limit 1", dbesc($qq['field_name']), dbesc($r[0]['profile_guid']), intval(local_channel()));
                 if (array_key_exists($qq['field_name'], $fields)) {
                     $extra_fields[] = array($qq['field_name'], $qq['field_desc'], $mine ? $mine[0]['v'] : '', $qq['field_help']);
                 }
             }
         }
         //logger('extra_fields: ' . print_r($extra_fields,true));
         $f = get_config('system', 'birthday_input_format');
         if (!$f) {
             $f = 'ymd';
         }
         $is_default = $r[0]['is_default'] ? 1 : 0;
         $tpl = get_markup_template("profile_edit.tpl");
         $o .= replace_macros($tpl, array('$form_security_token' => get_form_security_token("profile_edit"), '$profile_clone_link' => feature_enabled(local_channel(), 'multi_profiles') ? 'profiles/clone/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_clone") : '', '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_drop"), '$fields' => $fields, '$guid' => $r[0]['profile_guid'], '$banner' => t('Edit Profile Details'), '$submit' => t('Submit'), '$viewprof' => t('View this profile'), '$editvis' => t('Edit visibility'), '$tools_label' => t('Profile Tools'), '$coverpic' => t('Change cover photo'), '$profpic' => t('Change profile photo'), '$cr_prof' => t('Create a new profile using these settings'), '$cl_prof' => t('Clone this profile'), '$del_prof' => t('Delete this profile'), '$addthing' => t('Add profile things'), '$personal' => t('Personal'), '$location' => t('Location'), '$relation' => t('Relation'), '$miscellaneous' => t('Miscellaneous'), '$exportable' => feature_enabled(local_channel(), 'profile_export'), '$lbl_import' => t('Import profile from file'), '$lbl_export' => t('Export profile to file'), '$lbl_gender' => t('Your gender'), '$lbl_marital' => t('Marital status'), '$lbl_sexual' => t('Sexual preference'), '$baseurl' => z_root(), '$profile_id' => $r[0]['id'], '$profile_name' => array('profile_name', t('Profile name'), $r[0]['profile_name'], t('Required'), '*'), '$is_default' => $is_default, '$default' => t('This is your default profile.') . EOL . translate_scope(map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_profile'))), '$advanced' => $advanced, '$name' => array('name', t('Your full name'), $r[0]['fullname'], t('Required'), '*'), '$pdesc' => array('pdesc', t('Title/Description'), $r[0]['pdesc']), '$dob' => dob($r[0]['dob']), '$hide_friends' => $hide_friends, '$address' => array('address', t('Street address'), $r[0]['address']), '$locality' => array('locality', t('Locality/City'), $r[0]['locality']), '$region' => array('region', t('Region/State'), $r[0]['region']), '$postal_code' => array('postal_code', t('Postal/Zip code'), $r[0]['postal_code']), '$country_name' => array('country_name', t('Country'), $r[0]['country_name']), '$gender' => gender_selector($r[0]['gender']), '$gender_min' => gender_selector_min($r[0]['gender']), '$marital' => marital_selector($r[0]['marital']), '$marital_min' => marital_selector_min($r[0]['marital']), '$with' => array('with', t("Who (if applicable)"), $r[0]['partner'], t('Examples: cathy123, Cathy Williams, cathy@example.com')), '$howlong' => array('howlong', t('Since (date)'), $r[0]['howlong'] === NULL_DATE ? '' : datetime_convert('UTC', date_default_timezone_get(), $r[0]['howlong'])), '$sexual' => sexpref_selector($r[0]['sexual']), '$sexual_min' => sexpref_selector_min($r[0]['sexual']), '$about' => array('about', t('Tell us about yourself'), $r[0]['about']), '$homepage' => array('homepage', t('Homepage URL'), $r[0]['homepage']), '$hometown' => array('hometown', t('Hometown'), $r[0]['hometown']), '$politic' => array('politic', t('Political views'), $r[0]['politic']), '$religion' => array('religion', t('Religious views'), $r[0]['religion']), '$keywords' => array('keywords', t('Keywords used in directory listings'), $r[0]['keywords'], t('Example: fishing photography software')), '$likes' => array('likes', t('Likes'), $r[0]['likes']), '$dislikes' => array('dislikes', t('Dislikes'), $r[0]['dislikes']), '$music' => array('music', t('Musical interests'), $r[0]['music']), '$book' => array('book', t('Books, literature'), $r[0]['book']), '$tv' => array('tv', t('Television'), $r[0]['tv']), '$film' => array('film', t('Film/Dance/Culture/Entertainment'), $r[0]['film']), '$interest' => array('interest', t('Hobbies/Interests'), $r[0]['interest']), '$romance' => array('romance', t('Love/Romance'), $r[0]['romance']), '$work' => array('work', t('Work/Employment'), $r[0]['employment']), '$education' => array('education', t('School/Education'), $r[0]['education']), '$contact' => array('contact', t('Contact information and social networks'), $r[0]['contact']), '$channels' => array('channels', t('My other channels'), $r[0]['channels']), '$extra_fields' => $extra_fields));
         $arr = array('profile' => $r[0], 'entry' => $o);
         call_hooks('profile_edit', $arr);
         return $o;
     } else {
         $r = q("SELECT * FROM `profile` WHERE `uid` = %d", local_channel());
         if ($r) {
             $tpl = get_markup_template('profile_entry.tpl');
             foreach ($r as $rr) {
                 $profiles .= replace_macros($tpl, array('$photo' => $rr['thumb'], '$id' => $rr['id'], '$alt' => t('Profile Image'), '$profile_name' => $rr['profile_name'], '$visible' => $rr['is_default'] ? '<strong>' . translate_scope(map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_profile'))) . '</strong>' : '<a href="' . z_root() . '/profperm/' . $rr['id'] . '" />' . t('Edit visibility') . '</a>'));
             }
             $tpl_header = get_markup_template('profile_listing_header.tpl');
             $o .= replace_macros($tpl_header, array('$header' => t('Edit Profiles'), '$cr_new' => t('Create New'), '$cr_new_link' => 'profiles/new?t=' . get_form_security_token("profile_new"), '$profiles' => $profiles));
         }
         return $o;
     }
 }
Esempio n. 8
0
 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;
 }
Esempio n. 9
0
 static function role_perms($role)
 {
     $ret = array();
     $ret['role'] = $role;
     switch ($role) {
         case 'social':
             $ret['perms_auto'] = false;
             $ret['default_collection'] = false;
             $ret['directory_publish'] = true;
             $ret['online'] = true;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'send_stream', 'post_wall', 'post_comments', 'post_mail', 'chat', 'post_like', 'republish'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             break;
         case 'social_restricted':
             $ret['perms_auto'] = false;
             $ret['default_collection'] = true;
             $ret['directory_publish'] = true;
             $ret['online'] = true;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'send_stream', 'post_wall', 'post_comments', 'post_mail', 'chat', 'post_like'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             break;
         case 'social_private':
             $ret['perms_auto'] = false;
             $ret['default_collection'] = true;
             $ret['directory_publish'] = false;
             $ret['online'] = false;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'send_stream', 'post_wall', 'post_comments', 'post_mail', 'post_like'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             $ret['limits']['view_contacts'] = PERMS_SPECIFIC;
             $ret['limits']['view_storage'] = PERMS_SPECIFIC;
             break;
         case 'forum':
             $ret['perms_auto'] = true;
             $ret['default_collection'] = false;
             $ret['directory_publish'] = true;
             $ret['online'] = false;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'post_wall', 'post_comments', 'tag_deliver', 'post_mail', 'post_like', 'republish', 'chat'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             break;
         case 'forum_restricted':
             $ret['perms_auto'] = false;
             $ret['default_collection'] = true;
             $ret['directory_publish'] = true;
             $ret['online'] = false;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'post_wall', 'post_comments', 'tag_deliver', 'post_mail', 'post_like', 'chat'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             break;
         case 'forum_private':
             $ret['perms_auto'] = false;
             $ret['default_collection'] = true;
             $ret['directory_publish'] = false;
             $ret['online'] = false;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'post_wall', 'post_comments', 'post_mail', 'post_like', 'chat'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             $ret['limits']['view_profile'] = PERMS_SPECIFIC;
             $ret['limits']['view_contacts'] = PERMS_SPECIFIC;
             $ret['limits']['view_storage'] = PERMS_SPECIFIC;
             $ret['limits']['view_pages'] = PERMS_SPECIFIC;
             break;
         case 'feed':
             $ret['perms_auto'] = true;
             $ret['default_collection'] = false;
             $ret['directory_publish'] = true;
             $ret['online'] = false;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'send_stream', 'post_wall', 'post_comments', 'post_mail', 'post_like', 'republish'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             break;
         case 'feed_restricted':
             $ret['perms_auto'] = false;
             $ret['default_collection'] = true;
             $ret['directory_publish'] = false;
             $ret['online'] = false;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'send_stream', 'post_wall', 'post_comments', 'post_mail', 'post_like', 'republish'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             break;
         case 'soapbox':
             $ret['perms_auto'] = true;
             $ret['default_collection'] = false;
             $ret['directory_publish'] = true;
             $ret['online'] = false;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'post_like', 'republish'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             break;
         case 'repository':
             $ret['perms_auto'] = true;
             $ret['default_collection'] = false;
             $ret['directory_publish'] = true;
             $ret['online'] = false;
             $ret['perms_connect'] = ['view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'write_storage', 'write_pages', 'post_wall', 'post_comments', 'tag_deliver', 'post_mail', 'post_like', 'republish', 'chat'];
             $ret['limits'] = PermissionLimits::Std_Limits();
             break;
         default:
             break;
     }
     $x = get_config('system', 'role_perms');
     // let system settings over-ride any or all
     if ($x && is_array($x) && array_key_exists($role, $x)) {
         $ret = array_merge($ret, $x[$role]);
     }
     call_hooks('get_role_perms', $ret);
     return $ret;
 }
Esempio n. 10
0
 function post()
 {
     // This will change. Figure out who the observer is and whether or not
     // they have permission to post here. Else ignore the post.
     if (!local_channel() && !remote_channel() && !x($_REQUEST, 'commenter')) {
         return;
     }
     require_once 'include/security.php';
     $uid = local_channel();
     $channel = null;
     $observer = null;
     /**
      * Is this a reply to something?
      */
     $parent = x($_REQUEST, 'parent') ? intval($_REQUEST['parent']) : 0;
     $parent_mid = x($_REQUEST, 'parent_mid') ? trim($_REQUEST['parent_mid']) : '';
     $remote_xchan = x($_REQUEST, 'remote_xchan') ? trim($_REQUEST['remote_xchan']) : false;
     $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($remote_xchan));
     if ($r) {
         $remote_observer = $r[0];
     } else {
         $remote_xchan = $remote_observer = false;
     }
     $profile_uid = x($_REQUEST, 'profile_uid') ? intval($_REQUEST['profile_uid']) : 0;
     require_once 'include/channel.php';
     $sys = get_sys_channel();
     if ($sys && $profile_uid && $sys['channel_id'] == $profile_uid && is_site_admin()) {
         $uid = intval($sys['channel_id']);
         $channel = $sys;
         $observer = $sys;
     }
     if (x($_REQUEST, 'dropitems')) {
         require_once 'include/items.php';
         $arr_drop = explode(',', $_REQUEST['dropitems']);
         drop_items($arr_drop);
         $json = array('success' => 1);
         echo json_encode($json);
         killme();
     }
     call_hooks('post_local_start', $_REQUEST);
     //	 logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
     $api_source = x($_REQUEST, 'api_source') && $_REQUEST['api_source'] ? true : false;
     $consensus = intval($_REQUEST['consensus']);
     $nocomment = intval($_REQUEST['nocomment']);
     // 'origin' (if non-zero) indicates that this network is where the message originated,
     // for the purpose of relaying comments to other conversation members.
     // If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset.
     // If the API is used from another network with its own distribution
     // and deliveries, you may wish to set origin to 0 or false and allow the other
     // network to relay comments.
     // If you are unsure, it is prudent (and important) to leave it unset.
     $origin = $api_source && array_key_exists('origin', $_REQUEST) ? intval($_REQUEST['origin']) : 1;
     // To represent message-ids on other networks - this will create an iconfig record
     $namespace = $api_source && array_key_exists('namespace', $_REQUEST) ? strip_tags($_REQUEST['namespace']) : '';
     $remote_id = $api_source && array_key_exists('remote_id', $_REQUEST) ? strip_tags($_REQUEST['remote_id']) : '';
     $owner_hash = null;
     $message_id = x($_REQUEST, 'message_id') && $api_source ? strip_tags($_REQUEST['message_id']) : '';
     $created = x($_REQUEST, 'created') ? datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['created']) : datetime_convert();
     $post_id = x($_REQUEST, 'post_id') ? intval($_REQUEST['post_id']) : 0;
     $app = x($_REQUEST, 'source') ? strip_tags($_REQUEST['source']) : '';
     $return_path = x($_REQUEST, 'return') ? $_REQUEST['return'] : '';
     $preview = x($_REQUEST, 'preview') ? intval($_REQUEST['preview']) : 0;
     $categories = x($_REQUEST, 'category') ? escape_tags($_REQUEST['category']) : '';
     $webpage = x($_REQUEST, 'webpage') ? intval($_REQUEST['webpage']) : 0;
     $pagetitle = x($_REQUEST, 'pagetitle') ? escape_tags(urlencode($_REQUEST['pagetitle'])) : '';
     $layout_mid = x($_REQUEST, 'layout_mid') ? escape_tags($_REQUEST['layout_mid']) : '';
     $plink = x($_REQUEST, 'permalink') ? escape_tags($_REQUEST['permalink']) : '';
     $obj_type = x($_REQUEST, 'obj_type') ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE;
     // allow API to bulk load a bunch of imported items with sending out a bunch of posts.
     $nopush = x($_REQUEST, 'nopush') ? intval($_REQUEST['nopush']) : 0;
     /*
      * Check service class limits
      */
     if ($uid && !x($_REQUEST, 'parent') && !x($_REQUEST, 'post_id')) {
         $ret = $this->item_check_service_class($uid, $_REQUEST['webpage'] == ITEM_TYPE_WEBPAGE ? true : false);
         if (!$ret['success']) {
             notice(t($ret['message']) . EOL);
             if (x($_REQUEST, 'return')) {
                 goaway(z_root() . "/" . $return_path);
             }
             killme();
         }
     }
     if ($pagetitle) {
         require_once 'library/urlify/URLify.php';
         $pagetitle = strtolower(\URLify::transliterate($pagetitle));
     }
     $item_flags = $item_restrict = 0;
     $route = '';
     $parent_item = null;
     $parent_contact = null;
     $thr_parent = '';
     $parid = 0;
     $r = false;
     if ($parent || $parent_mid) {
         if (!x($_REQUEST, 'type')) {
             $_REQUEST['type'] = 'net-comment';
         }
         if ($obj_type == ACTIVITY_OBJ_POST) {
             $obj_type = ACTIVITY_OBJ_COMMENT;
         }
         if ($parent) {
             $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($parent));
         } elseif ($parent_mid && $uid) {
             // This is coming from an API source, and we are logged in
             $r = q("SELECT * FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1", dbesc($parent_mid), intval($uid));
         }
         // if this isn't the real parent of the conversation, find it
         if ($r !== false && count($r)) {
             $parid = $r[0]['parent'];
             $parent_mid = $r[0]['mid'];
             if ($r[0]['id'] != $r[0]['parent']) {
                 $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1", intval($parid));
             }
         }
         if ($r === false || !count($r)) {
             notice(t('Unable to locate original post.') . EOL);
             if (x($_REQUEST, 'return')) {
                 goaway(z_root() . "/" . $return_path);
             }
             killme();
         }
         // can_comment_on_post() needs info from the following xchan_query
         // This may be from the discover tab which means we need to correct the effective uid
         xchan_query($r, true, $r[0]['uid'] == local_channel() ? 0 : local_channel());
         $parent_item = $r[0];
         $parent = $r[0]['id'];
         // multi-level threading - preserve the info but re-parent to our single level threading
         $thr_parent = $parent_mid;
         $route = $parent_item['route'];
     }
     if (!$observer) {
         $observer = \App::get_observer();
     }
     if ($parent) {
         logger('mod_item: item_post parent=' . $parent);
         $can_comment = false;
         if (array_key_exists('owner', $parent_item) && intval($parent_item['owner']['abook_self'])) {
             $can_comment = perm_is_allowed($profile_uid, $observer['xchan_hash'], 'post_comments');
         } else {
             $can_comment = can_comment_on_post($observer['xchan_hash'], $parent_item);
         }
         if (!$can_comment) {
             notice(t('Permission denied.') . EOL);
             if (x($_REQUEST, 'return')) {
                 goaway(z_root() . "/" . $return_path);
             }
             killme();
         }
     } else {
         if (!perm_is_allowed($profile_uid, $observer['xchan_hash'], $webpage ? 'write_pages' : 'post_wall')) {
             notice(t('Permission denied.') . EOL);
             if (x($_REQUEST, 'return')) {
                 goaway(z_root() . "/" . $return_path);
             }
             killme();
         }
     }
     // is this an edited post?
     $orig_post = null;
     if ($namespace && $remote_id) {
         // It wasn't an internally generated post - see if we've got an item matching this remote service id
         $i = q("select iid from iconfig where cat = 'system' and k = '%s' and v = '%s' limit 1", dbesc($namespace), dbesc($remote_id));
         if ($i) {
             $post_id = $i[0]['iid'];
         }
     }
     $iconfig = null;
     if ($post_id) {
         $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval($profile_uid), intval($post_id));
         if (!count($i)) {
             killme();
         }
         $orig_post = $i[0];
         $iconfig = q("select * from iconfig where iid = %d", intval($post_id));
     }
     if (!$channel) {
         if ($uid && $uid == $profile_uid) {
             $channel = \App::get_channel();
         } else {
             // posting as yourself but not necessarily to a channel you control
             $r = q("select * from channel left join account on channel_account_id = account_id where channel_id = %d LIMIT 1", intval($profile_uid));
             if ($r) {
                 $channel = $r[0];
             }
         }
     }
     if (!$channel) {
         logger("mod_item: no channel.");
         if (x($_REQUEST, 'return')) {
             goaway(z_root() . "/" . $return_path);
         }
         killme();
     }
     $owner_xchan = null;
     $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($channel['channel_hash']));
     if ($r && count($r)) {
         $owner_xchan = $r[0];
     } else {
         logger("mod_item: no owner.");
         if (x($_REQUEST, 'return')) {
             goaway(z_root() . "/" . $return_path);
         }
         killme();
     }
     $walltowall = false;
     $walltowall_comment = false;
     if ($remote_xchan) {
         $observer = $remote_observer;
     }
     if ($observer) {
         logger('mod_item: post accepted from ' . $observer['xchan_name'] . ' for ' . $owner_xchan['xchan_name'], LOGGER_DEBUG);
         // wall-to-wall detection.
         // For top-level posts, if the author and owner are different it's a wall-to-wall
         // For comments, We need to additionally look at the parent and see if it's a wall post that originated locally.
         if ($observer['xchan_name'] != $owner_xchan['xchan_name']) {
             if ($parent_item && ($parent_item['item_wall'] && $parent_item['item_origin'])) {
                 $walltowall_comment = true;
                 $walltowall = true;
             }
             if (!$parent) {
                 $walltowall = true;
             }
         }
     }
     $acl = new \Zotlabs\Access\AccessList($channel);
     $view_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_stream');
     $comment_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'post_comments');
     $public_policy = x($_REQUEST, 'public_policy') ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy, true);
     if ($webpage) {
         $public_policy = '';
     }
     if ($public_policy) {
         $private = 1;
     }
     if ($orig_post) {
         $private = 0;
         // webpages are allowed to change ACLs after the fact. Normal conversation items aren't.
         if ($webpage) {
             $acl->set_from_array($_REQUEST);
         } else {
             $acl->set($orig_post);
             $public_policy = $orig_post['public_policy'];
             $private = $orig_post['item_private'];
         }
         if ($private || $public_policy || $acl->is_private()) {
             $private = 1;
         }
         $location = $orig_post['location'];
         $coord = $orig_post['coord'];
         $verb = $orig_post['verb'];
         $app = $orig_post['app'];
         $title = escape_tags(trim($_REQUEST['title']));
         $body = trim($_REQUEST['body']);
         $item_flags = $orig_post['item_flags'];
         $item_origin = $orig_post['item_origin'];
         $item_unseen = $orig_post['item_unseen'];
         $item_starred = $orig_post['item_starred'];
         $item_uplink = $orig_post['item_uplink'];
         $item_consensus = $orig_post['item_consensus'];
         $item_wall = $orig_post['item_wall'];
         $item_thread_top = $orig_post['item_thread_top'];
         $item_notshown = $orig_post['item_notshown'];
         $item_nsfw = $orig_post['item_nsfw'];
         $item_relay = $orig_post['item_relay'];
         $item_mentionsme = $orig_post['item_mentionsme'];
         $item_nocomment = $orig_post['item_nocomment'];
         $item_obscured = $orig_post['item_obscured'];
         $item_verified = $orig_post['item_verified'];
         $item_retained = $orig_post['item_retained'];
         $item_rss = $orig_post['item_rss'];
         $item_deleted = $orig_post['item_deleted'];
         $item_type = $orig_post['item_type'];
         $item_hidden = $orig_post['item_hidden'];
         $item_unpublished = $orig_post['item_unpublished'];
         $item_delayed = $orig_post['item_delayed'];
         $item_pending_remove = $orig_post['item_pending_remove'];
         $item_blocked = $orig_post['item_blocked'];
         $postopts = $orig_post['postopts'];
         $created = $orig_post['created'];
         $mid = $orig_post['mid'];
         $parent_mid = $orig_post['parent_mid'];
         $plink = $orig_post['plink'];
     } else {
         if (!$walltowall) {
             if (array_key_exists('contact_allow', $_REQUEST) || array_key_exists('group_allow', $_REQUEST) || array_key_exists('contact_deny', $_REQUEST) || array_key_exists('group_deny', $_REQUEST)) {
                 $acl->set_from_array($_REQUEST);
             } elseif (!$api_source) {
                 // if no ACL has been defined and we aren't using the API, the form
                 // didn't send us any parameters. This means there's no ACL or it has
                 // been reset to the default audience.
                 // If $api_source is set and there are no ACL parameters, we default
                 // to the channel permissions which were set in the ACL contructor.
                 $acl->set(array('allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''));
             }
         }
         $location = notags(trim($_REQUEST['location']));
         $coord = notags(trim($_REQUEST['coord']));
         $verb = notags(trim($_REQUEST['verb']));
         $title = escape_tags(trim($_REQUEST['title']));
         $body = trim($_REQUEST['body']);
         $body .= trim($_REQUEST['attachment']);
         $postopts = '';
         $private = intval($acl->is_private() || $public_policy);
         // If this is a comment, set the permissions from the parent.
         if ($parent_item) {
             $private = 0;
             $acl->set($parent_item);
             $private = intval($acl->is_private() || $parent_item['item_private']);
             $public_policy = $parent_item['public_policy'];
             $owner_hash = $parent_item['owner_xchan'];
         }
         if (!strlen($body)) {
             if ($preview) {
                 killme();
             }
             info(t('Empty post discarded.') . EOL);
             if (x($_REQUEST, 'return')) {
                 goaway(z_root() . "/" . $return_path);
             }
             killme();
         }
     }
     $expires = NULL_DATE;
     if (feature_enabled($profile_uid, 'content_expire')) {
         if (x($_REQUEST, 'expire')) {
             $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['expire']);
             if ($expires <= datetime_convert()) {
                 $expires = NULL_DATE;
             }
         }
     }
     $mimetype = notags(trim($_REQUEST['mimetype']));
     if (!$mimetype) {
         $mimetype = 'text/bbcode';
     }
     if ($preview) {
         $body = z_input_filter($profile_uid, $body, $mimetype);
     }
     // Verify ability to use html or php!!!
     $execflag = false;
     if ($mimetype !== 'text/bbcode') {
         $z = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1", intval($profile_uid));
         if ($z && ($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE || $z[0]['channel_pageflags'] & PAGE_ALLOWCODE)) {
             if ($uid && get_account_id() == $z[0]['account_id']) {
                 $execflag = true;
             } else {
                 notice(t('Executable content type not permitted to this channel.') . EOL);
                 if (x($_REQUEST, 'return')) {
                     goaway(z_root() . "/" . $return_path);
                 }
                 killme();
             }
         }
     }
     $gacl = $acl->get();
     $str_contact_allow = $gacl['allow_cid'];
     $str_group_allow = $gacl['allow_gid'];
     $str_contact_deny = $gacl['deny_cid'];
     $str_group_deny = $gacl['deny_gid'];
     if ($mimetype === 'text/bbcode') {
         require_once 'include/text.php';
         // Markdown doesn't work correctly. Do not re-enable unless you're willing to fix it and support it.
         // Sample that will probably give you grief - you must preserve the linebreaks
         // and provide the correct markdown interpretation and you cannot allow unfiltered HTML
         // Markdown
         // ========
         //
         // **bold** abcde
         // fghijkl
         // *italic*
         // <img src="javascript:alert('hacked');" />
         //		if($uid && $uid == $profile_uid && feature_enabled($uid,'markdown')) {
         //			require_once('include/bb2diaspora.php');
         //			$body = escape_tags(trim($body));
         //			$body = str_replace("\n",'<br />', $body);
         //			$body = preg_replace_callback('/\[share(.*?)\]/ism','\share_shield',$body);
         //			$body = diaspora2bb($body,true);
         //			$body = preg_replace_callback('/\[share(.*?)\]/ism','\share_unshield',$body);
         //		}
         // BBCODE alert: the following functions assume bbcode input
         // and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
         // we may need virtual or template classes to implement the possible alternatives
         // Work around doubled linefeeds in Tinymce 3.5b2
         // First figure out if it's a status post that would've been
         // created using tinymce. Otherwise leave it alone.
         $plaintext = true;
         //		$plaintext = ((feature_enabled($profile_uid,'richtext')) ? false : true);
         //		if((! $parent) && (! $api_source) && (! $plaintext)) {
         //			$body = fix_mce_lf($body);
         //		}
         // If we're sending a private top-level message with a single @-taggable channel as a recipient, @-tag it, if our pconfig is set.
         if (!$parent && get_pconfig($profile_uid, 'system', 'tagifonlyrecip') && substr_count($str_contact_allow, '<') == 1 && $str_group_allow == '' && $str_contact_deny == '' && $str_group_deny == '') {
             $x = q("select abook_id, abconfig.v from abook left join abconfig on abook_xchan = abconfig.xchan and abook_channel = abconfig.chan and cat= 'their_perms' and abconfig.k = 'tag_deliver' and abconfig.v = 1 and abook_xchan = '%s' and abook_channel = %d limit 1", dbesc(str_replace(array('<', '>'), array('', ''), $str_contact_allow)), intval($profile_uid));
             if ($x) {
                 $body .= "\n\n@group+" . $x[0]['abook_id'] . "\n";
             }
         }
         /**
          * fix naked links by passing through a callback to see if this is a hubzilla site
          * (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both.
          * First protect any url inside certain bbcode tags so we don't double link it.
          */
         $body = preg_replace_callback('/\\[code(.*?)\\[\\/(code)\\]/ism', '\\red_escape_codeblock', $body);
         $body = preg_replace_callback('/\\[url(.*?)\\[\\/(url)\\]/ism', '\\red_escape_codeblock', $body);
         $body = preg_replace_callback('/\\[zrl(.*?)\\[\\/(zrl)\\]/ism', '\\red_escape_codeblock', $body);
         $body = preg_replace_callback("/([^\\]\\='" . '"' . "\\/]|^|\\#\\^)(https?\\:\\/\\/[a-zA-Z0-9\\:\\/\\-\\?\\&\\;\\.\\=\\@\\_\\~\\#\\%\$\\!\\+\\,]+)/ism", 'nakedoembed', $body);
         $body = preg_replace_callback("/([^\\]\\='" . '"' . "\\/]|^|\\#\\^)(https?\\:\\/\\/[a-zA-Z0-9\\:\\/\\-\\?\\&\\;\\.\\=\\@\\_\\~\\#\\%\$\\!\\+\\,]+)/ism", '\\red_zrl_callback', $body);
         $body = preg_replace_callback('/\\[\\$b64zrl(.*?)\\[\\/(zrl)\\]/ism', '\\red_unescape_codeblock', $body);
         $body = preg_replace_callback('/\\[\\$b64url(.*?)\\[\\/(url)\\]/ism', '\\red_unescape_codeblock', $body);
         $body = preg_replace_callback('/\\[\\$b64code(.*?)\\[\\/(code)\\]/ism', '\\red_unescape_codeblock', $body);
         // fix any img tags that should be zmg
         $body = preg_replace_callback('/\\[img(.*?)\\](.*?)\\[\\/img\\]/ism', '\\red_zrlify_img_callback', $body);
         $body = bb_translate_video($body);
         /**
          * Fold multi-line [code] sequences
          */
         $body = preg_replace('/\\[\\/code\\]\\s*\\[code\\]/ism', "\n", $body);
         $body = scale_external_images($body, false);
         // Look for tags and linkify them
         $results = linkify_tags($a, $body, $uid ? $uid : $profile_uid);
         if ($results) {
             // Set permissions based on tag replacements
             set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private);
             $post_tags = array();
             foreach ($results as $result) {
                 $success = $result['success'];
                 if ($success['replaced']) {
                     $post_tags[] = array('uid' => $profile_uid, 'ttype' => $success['termtype'], 'otype' => TERM_OBJ_POST, 'term' => $success['term'], 'url' => $success['url']);
                 }
             }
         }
         /**
          *
          * When a photo was uploaded into the message using the (profile wall) ajax 
          * uploader, The permissions are initially set to disallow anybody but the
          * owner from seeing it. This is because the permissions may not yet have been
          * set for the post. If it's private, the photo permissions should be set
          * appropriately. But we didn't know the final permissions on the post until
          * now. So now we'll look for links of uploaded photos and attachments that are in the
          * post and set them to the same permissions as the post itself.
          *
          * If the post was end-to-end encrypted we can't find images and attachments in the body,
          * use our media_str input instead which only contains these elements - but only do this
          * when encrypted content exists because the photo/attachment may have been removed from 
          * the post and we should keep it private. If it's encrypted we have no way of knowing
          * so we'll set the permissions regardless and realise that the media may not be 
          * referenced in the post. 
          *
          * What is preventing us from being able to upload photos into comments is dealing with
          * the photo and attachment permissions, since we don't always know who was in the 
          * distribution for the top level post.
          * 
          * We might be able to provide this functionality with a lot of fiddling:
          * - if the top level post is public (make the photo public)
          * - if the top level post was written by us or a wall post that belongs to us (match the top level post)
          * - if the top level post has privacy mentions, add those to the permissions.
          * - otherwise disallow the photo *or* make the photo public. This is the part that gets messy. 
          */
         if (!$preview) {
             fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], strpos($body, '[/crypt]') ? $_POST['media_str'] : $body, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
             fix_attached_file_permissions($channel, $observer['xchan_hash'], strpos($body, '[/crypt]') ? $_POST['media_str'] : $body, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
         }
         $attachments = '';
         $match = false;
         if (preg_match_all('/(\\[attachment\\](.*?)\\[\\/attachment\\])/', $body, $match)) {
             $attachments = array();
             $i = 0;
             foreach ($match[2] as $mtch) {
                 $attach_link = '';
                 $hash = substr($mtch, 0, strpos($mtch, ','));
                 $rev = intval(substr($mtch, strpos($mtch, ',')));
                 $r = attach_by_hash_nodata($hash, $rev);
                 if ($r['success']) {
                     $attachments[] = array('href' => z_root() . '/attach/' . $r['data']['hash'], 'length' => $r['data']['filesize'], 'type' => $r['data']['filetype'], 'title' => urlencode($r['data']['filename']), 'revision' => $r['data']['revision']);
                 }
                 $ext = substr($r['data']['filename'], strrpos($r['data']['filename'], '.'));
                 if (strpos($r['data']['filetype'], 'audio/') !== false) {
                     $attach_link = '[audio]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . ($ext ? $ext : '') . '[/audio]';
                 } elseif (strpos($r['data']['filetype'], 'video/') !== false) {
                     $attach_link = '[video]' . z_root() . '/attach/' . $r['data']['hash'] . '/' . $r['data']['revision'] . ($ext ? $ext : '') . '[/video]';
                 }
                 $body = str_replace($match[1][$i], $attach_link, $body);
                 $i++;
             }
         }
     }
     // BBCODE end alert
     if (strlen($categories)) {
         $cats = explode(',', $categories);
         foreach ($cats as $cat) {
             $post_tags[] = array('uid' => $profile_uid, 'ttype' => TERM_CATEGORY, 'otype' => TERM_OBJ_POST, 'term' => trim($cat), 'url' => $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat)));
         }
     }
     if ($orig_post) {
         // preserve original tags
         $t = q("select * from term where oid = %d and otype = %d and uid = %d and ttype in ( %d, %d, %d )", intval($orig_post['id']), intval(TERM_OBJ_POST), intval($profile_uid), intval(TERM_UNKNOWN), intval(TERM_FILE), intval(TERM_COMMUNITYTAG));
         if ($t) {
             foreach ($t as $t1) {
                 $post_tags[] = array('uid' => $profile_uid, 'ttype' => $t1['type'], 'otype' => TERM_OBJ_POST, 'term' => $t1['term'], 'url' => $t1['url']);
             }
         }
     }
     $item_unseen = local_channel() != $profile_uid ? 1 : 0;
     $item_wall = $post_type === 'wall' || $post_type === 'wall-comment' ? 1 : 0;
     $item_origin = $origin ? 1 : 0;
     $item_consensus = $consensus ? 1 : 0;
     $item_nocomment = $nocomment ? 1 : 0;
     // determine if this is a wall post
     if ($parent) {
         $item_wall = $parent_item['item_wall'];
     } else {
         if (!$webpage) {
             $item_wall = 1;
         }
     }
     if ($moderated) {
         $item_blocked = ITEM_MODERATED;
     }
     if (!strlen($verb)) {
         $verb = ACTIVITY_POST;
     }
     $notify_type = $parent ? 'comment-new' : 'wall-new';
     if (!$mid) {
         $mid = $message_id ? $message_id : item_message_id();
     }
     if (!$parent_mid) {
         $parent_mid = $mid;
     }
     if ($parent_item) {
         $parent_mid = $parent_item['mid'];
     }
     // Fallback so that we alway have a thr_parent
     if (!$thr_parent) {
         $thr_parent = $mid;
     }
     $datarray = array();
     $item_thread_top = !$parent ? 1 : 0;
     if (!$plink && $item_thread_top) {
         $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $mid;
     }
     $datarray['aid'] = $channel['channel_account_id'];
     $datarray['uid'] = $profile_uid;
     $datarray['owner_xchan'] = $owner_hash ? $owner_hash : $owner_xchan['xchan_hash'];
     $datarray['author_xchan'] = $observer['xchan_hash'];
     $datarray['created'] = $created;
     $datarray['edited'] = $orig_post ? datetime_convert() : $created;
     $datarray['expires'] = $expires;
     $datarray['commented'] = $orig_post ? datetime_convert() : $created;
     $datarray['received'] = $orig_post ? datetime_convert() : $created;
     $datarray['changed'] = $orig_post ? datetime_convert() : $created;
     $datarray['mid'] = $mid;
     $datarray['parent_mid'] = $parent_mid;
     $datarray['mimetype'] = $mimetype;
     $datarray['title'] = $title;
     $datarray['body'] = $body;
     $datarray['app'] = $app;
     $datarray['location'] = $location;
     $datarray['coord'] = $coord;
     $datarray['verb'] = $verb;
     $datarray['obj_type'] = $obj_type;
     $datarray['allow_cid'] = $str_contact_allow;
     $datarray['allow_gid'] = $str_group_allow;
     $datarray['deny_cid'] = $str_contact_deny;
     $datarray['deny_gid'] = $str_group_deny;
     $datarray['attach'] = $attachments;
     $datarray['thr_parent'] = $thr_parent;
     $datarray['postopts'] = $postopts;
     $datarray['item_unseen'] = intval($item_unseen);
     $datarray['item_wall'] = intval($item_wall);
     $datarray['item_origin'] = intval($item_origin);
     $datarray['item_type'] = $webpage;
     $datarray['item_private'] = intval($private);
     $datarray['item_thread_top'] = intval($item_thread_top);
     $datarray['item_unseen'] = intval($item_unseen);
     $datarray['item_starred'] = intval($item_starred);
     $datarray['item_uplink'] = intval($item_uplink);
     $datarray['item_consensus'] = intval($item_consensus);
     $datarray['item_notshown'] = intval($item_notshown);
     $datarray['item_nsfw'] = intval($item_nsfw);
     $datarray['item_relay'] = intval($item_relay);
     $datarray['item_mentionsme'] = intval($item_mentionsme);
     $datarray['item_nocomment'] = intval($item_nocomment);
     $datarray['item_obscured'] = intval($item_obscured);
     $datarray['item_verified'] = intval($item_verified);
     $datarray['item_retained'] = intval($item_retained);
     $datarray['item_rss'] = intval($item_rss);
     $datarray['item_deleted'] = intval($item_deleted);
     $datarray['item_hidden'] = intval($item_hidden);
     $datarray['item_unpublished'] = intval($item_unpublished);
     $datarray['item_delayed'] = intval($item_delayed);
     $datarray['item_pending_remove'] = intval($item_pending_remove);
     $datarray['item_blocked'] = intval($item_blocked);
     $datarray['layout_mid'] = $layout_mid;
     $datarray['public_policy'] = $public_policy;
     $datarray['comment_policy'] = map_scope($comment_policy);
     $datarray['term'] = $post_tags;
     $datarray['plink'] = $plink;
     $datarray['route'] = $route;
     if ($iconfig) {
         $datarray['iconfig'] = $iconfig;
     }
     // preview mode - prepare the body for display and send it via json
     if ($preview) {
         require_once 'include/conversation.php';
         $datarray['owner'] = $owner_xchan;
         $datarray['author'] = $observer;
         $datarray['attach'] = json_encode($datarray['attach']);
         $o = conversation($a, array($datarray), 'search', false, 'preview');
         //		logger('preview: ' . $o, LOGGER_DEBUG);
         echo json_encode(array('preview' => $o));
         killme();
     }
     if ($orig_post) {
         $datarray['edit'] = true;
     }
     // suppress duplicates, *unless* you're editing an existing post. This could get picked up
     // as a duplicate if you're editing it very soon after posting it initially and you edited
     // some attribute besides the content, such as title or categories.
     if (feature_enabled($profile_uid, 'suppress_duplicates') && !$orig_post) {
         $z = q("select created from item where uid = %d and created > %s - INTERVAL %s and body = '%s' limit 1", intval($profile_uid), db_utcnow(), db_quoteinterval('2 MINUTE'), dbesc($body));
         if ($z) {
             $datarray['cancel'] = 1;
             notice(t('Duplicate post suppressed.') . EOL);
             logger('Duplicate post. Faking plugin cancel.');
         }
     }
     call_hooks('post_local', $datarray);
     if (x($datarray, 'cancel')) {
         logger('mod_item: post cancelled by plugin or duplicate suppressed.');
         if ($return_path) {
             goaway(z_root() . "/" . $return_path);
         }
         $json = array('cancel' => 1);
         $json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
         echo json_encode($json);
         killme();
     }
     if (mb_strlen($datarray['title']) > 255) {
         $datarray['title'] = mb_substr($datarray['title'], 0, 255);
     }
     if (array_key_exists('item_private', $datarray) && $datarray['item_private']) {
         $datarray['body'] = trim(z_input_filter($datarray['uid'], $datarray['body'], $datarray['mimetype']));
         if ($uid) {
             if ($channel['channel_hash'] === $datarray['author_xchan']) {
                 $datarray['sig'] = base64url_encode(rsa_sign($datarray['body'], $channel['channel_prvkey']));
                 $datarray['item_verified'] = 1;
             }
         }
     }
     if ($webpage) {
         Zlib\IConfig::Set($datarray, 'system', webpage_to_namespace($webpage), $pagetitle ? $pagetitle : substr($datarray['mid'], 0, 16), true);
     } elseif ($namespace) {
         Zlib\IConfig::Set($datarray, 'system', $namespace, $remote_id ? $remote_id : substr($datarray['mid'], 0, 16), true);
     }
     if ($orig_post) {
         $datarray['id'] = $post_id;
         $x = item_store_update($datarray, $execflag);
         if (!$parent) {
             $r = q("select * from item where id = %d", intval($post_id));
             if ($r) {
                 xchan_query($r);
                 $sync_item = fetch_post_tags($r);
                 build_sync_packet($profile_uid, array('item' => array(encode_item($sync_item[0], true))));
             }
         }
         if (!$nopush) {
             \Zotlabs\Daemon\Master::Summon(array('Notifier', 'edit_post', $post_id));
         }
         if (x($_REQUEST, 'return') && strlen($return_path)) {
             logger('return: ' . $return_path);
             goaway(z_root() . "/" . $return_path);
         }
         killme();
     } else {
         $post_id = 0;
     }
     $post = item_store($datarray, $execflag);
     $post_id = $post['item_id'];
     $datarray = $post['item'];
     if ($post_id) {
         logger('mod_item: saved item ' . $post_id);
         if ($parent) {
             // only send comment notification if this is a wall-to-wall comment,
             // otherwise it will happen during delivery
             if ($datarray['owner_xchan'] != $datarray['author_xchan'] && intval($parent_item['item_wall'])) {
                 Zlib\Enotify::submit(array('type' => NOTIFY_COMMENT, 'from_xchan' => $datarray['author_xchan'], 'to_xchan' => $datarray['owner_xchan'], 'item' => $datarray, 'link' => z_root() . '/display/' . $datarray['mid'], 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, 'parent_mid' => $parent_item['mid']));
             }
         } else {
             $parent = $post_id;
             if ($datarray['owner_xchan'] != $datarray['author_xchan'] && $datarray['item_type'] == ITEM_TYPE_POST) {
                 Zlib\Enotify::submit(array('type' => NOTIFY_WALL, 'from_xchan' => $datarray['author_xchan'], 'to_xchan' => $datarray['owner_xchan'], 'item' => $datarray, 'link' => z_root() . '/display/' . $datarray['mid'], 'verb' => ACTIVITY_POST, 'otype' => 'item'));
             }
             if ($uid && $uid == $profile_uid && is_item_normal($datarray)) {
                 q("update channel set channel_lastpost = '%s' where channel_id = %d", dbesc(datetime_convert()), intval($uid));
             }
         }
         // photo comments turn the corresponding item visible to the profile wall
         // This way we don't see every picture in your new photo album posted to your wall at once.
         // They will show up as people comment on them.
         if (intval($parent_item['item_hidden'])) {
             $r = q("UPDATE item SET item_hidden = 0 WHERE id = %d", intval($parent_item['id']));
         }
     } else {
         logger('mod_item: unable to retrieve post that was just stored.');
         notice(t('System error. Post not saved.') . EOL);
         goaway(z_root() . "/" . $return_path);
         // NOTREACHED
     }
     if ($parent && $parent != $post_id) {
         // Store the comment signature information in case we need to relay to Diaspora
         //$ditem = $datarray;
         //$ditem['author'] = $observer;
         //store_diaspora_comment_sig($ditem,$channel,$parent_item, $post_id, (($walltowall_comment) ? 1 : 0));
     } else {
         $r = q("select * from item where id = %d", intval($post_id));
         if ($r) {
             xchan_query($r);
             $sync_item = fetch_post_tags($r);
             build_sync_packet($profile_uid, array('item' => array(encode_item($sync_item[0], true))));
         }
     }
     $datarray['id'] = $post_id;
     $datarray['llink'] = z_root() . '/display/' . $channel['channel_address'] . '/' . $post_id;
     call_hooks('post_local_end', $datarray);
     if (!$nopush) {
         \Zotlabs\Daemon\Master::Summon(array('Notifier', $notify_type, $post_id));
     }
     logger('post_complete');
     // figure out how to return, depending on from whence we came
     if ($api_source) {
         return $post;
     }
     if ($return_path) {
         goaway(z_root() . "/" . $return_path);
     }
     $json = array('success' => 1);
     if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) {
         $json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
     }
     logger('post_json: ' . print_r($json, true), LOGGER_DEBUG);
     echo json_encode($json);
     killme();
     // NOTREACHED
 }
Esempio n. 11
0
/**
 * @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;
}
Esempio n. 12
0
/**
 * @brief
 *
 * @param array $channel
 * @param array $observer
 * @param array $args
 * @return array
 */
function photo_upload($channel, $observer, $args)
{
    $ret = array('success' => false);
    $channel_id = $channel['channel_id'];
    $account_id = $channel['channel_account_id'];
    if (!perm_is_allowed($channel_id, $observer['xchan_hash'], 'write_storage')) {
        $ret['message'] = t('Permission denied.');
        return $ret;
    }
    //	call_hooks('photo_upload_begin', $args);
    /*
     * Determine the album to use
     */
    $album = $args['album'];
    if (intval($args['visible']) || $args['visible'] === 'true') {
        $visible = 1;
    } else {
        $visible = 0;
    }
    $deliver = true;
    if (array_key_exists('deliver', $args)) {
        $deliver = intval($args['deliver']);
    }
    // Set to default channel permissions. If the parent directory (album) has permissions set,
    // use those instead. If we have specific permissions supplied, they take precedence over
    // all other settings. 'allow_cid' being passed from an external source takes priority over channel settings.
    // ...messy... needs re-factoring once the photos/files integration stabilises
    $acl = new Zotlabs\Access\AccessList($channel);
    if (array_key_exists('directory', $args) && $args['directory']) {
        $acl->set($args['directory']);
    }
    if (array_key_exists('allow_cid', $args)) {
        $acl->set($args);
    }
    if (array_key_exists('group_allow', $args) || array_key_exists('contact_allow', $args) || array_key_exists('group_deny', $args) || array_key_exists('contact_deny', $args)) {
        $acl->set_from_array($args);
    }
    $ac = $acl->get();
    $os_storage = 0;
    if ($args['os_path'] && $args['getimagesize']) {
        $imagedata = @file_get_contents($args['os_path']);
        $filename = $args['filename'];
        $filesize = strlen($imagedata);
        // this is going to be deleted if it exists
        $src = '/tmp/deletemenow';
        $type = $args['getimagesize']['mime'];
        $os_storage = 1;
    } elseif ($args['data'] || $args['content']) {
        // allow an import from a binary string representing the image.
        // This bypasses the upload step and max size limit checking
        $imagedata = $args['content'] ? $args['content'] : $args['data'];
        $filename = $args['filename'];
        $filesize = strlen($imagedata);
        // this is going to be deleted if it exists
        $src = '/tmp/deletemenow';
        $type = $args['mimetype'] ? $args['mimetype'] : $args['type'];
    } else {
        $f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => '');
        //		call_hooks('photo_upload_file',$f);
        if (x($f, 'src') && x($f, 'filesize')) {
            $src = $f['src'];
            $filename = $f['filename'];
            $filesize = $f['filesize'];
            $type = $f['type'];
        } else {
            $src = $_FILES['userfile']['tmp_name'];
            $filename = basename($_FILES['userfile']['name']);
            $filesize = intval($_FILES['userfile']['size']);
            $type = $_FILES['userfile']['type'];
        }
        if (!$type) {
            $type = guess_image_type($filename);
        }
        logger('photo_upload: received file: ' . $filename . ' as ' . $src . ' (' . $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG);
        $maximagesize = get_config('system', 'maximagesize');
        if ($maximagesize && $filesize > $maximagesize) {
            $ret['message'] = sprintf(t('Image exceeds website size limit of %lu bytes'), $maximagesize);
            @unlink($src);
            call_hooks('photo_upload_end', $ret);
            return $ret;
        }
        if (!$filesize) {
            $ret['message'] = t('Image file is empty.');
            @unlink($src);
            call_hooks('photo_post_end', $ret);
            return $ret;
        }
        logger('photo_upload: loading the contents of ' . $src, LOGGER_DEBUG);
        $imagedata = @file_get_contents($src);
    }
    $r = q("select sum(filesize) as total from photo where aid = %d and imgscale = 0 ", intval($account_id));
    $limit = engr_units_to_bytes(service_class_fetch($channel_id, 'photo_upload_limit'));
    if ($r && $limit !== false && $r[0]['total'] + strlen($imagedata) > $limit) {
        $ret['message'] = upgrade_message();
        @unlink($src);
        call_hooks('photo_post_end', $ret);
        return $ret;
    }
    $ph = photo_factory($imagedata, $type);
    if (!$ph->is_valid()) {
        $ret['message'] = t('Unable to process image');
        logger('photo_upload: unable to process image');
        @unlink($src);
        call_hooks('photo_upload_end', $ret);
        return $ret;
    }
    $exif = $ph->orient($args['os_path'] ? $args['os_path'] : $src);
    @unlink($src);
    $max_length = get_config('system', 'max_image_length');
    if (!$max_length) {
        $max_length = MAX_IMAGE_LENGTH;
    }
    if ($max_length > 0) {
        $ph->scaleImage($max_length);
    }
    $width = $ph->getWidth();
    $height = $ph->getHeight();
    $smallest = 0;
    $photo_hash = $args['resource_id'] ? $args['resource_id'] : photo_new_resource();
    $visitor = '';
    if ($channel['channel_hash'] !== $observer['xchan_hash']) {
        $visitor = $observer['xchan_hash'];
    }
    $errors = false;
    $p = array('aid' => $account_id, 'uid' => $channel_id, 'xchan' => $visitor, 'resource_id' => $photo_hash, 'filename' => $filename, 'album' => $album, 'imgscale' => 0, 'photo_usage' => PHOTO_NORMAL, 'allow_cid' => $ac['allow_cid'], 'allow_gid' => $ac['allow_gid'], 'deny_cid' => $ac['deny_cid'], 'deny_gid' => $ac['deny_gid'], 'os_storage' => $os_storage, 'os_path' => $args['os_path']);
    if ($args['created']) {
        $p['created'] = $args['created'];
    }
    if ($args['edited']) {
        $p['edited'] = $args['edited'];
    }
    if ($args['title']) {
        $p['title'] = $args['title'];
    }
    if ($args['description']) {
        $p['description'] = $args['description'];
    }
    $link = array();
    $r0 = $ph->save($p);
    $link[0] = array('rel' => 'alternate', 'type' => 'text/html', 'href' => z_root() . '/photo/' . $photo_hash . '-0.' . $ph->getExt(), 'width' => $ph->getWidth(), 'height' => $ph->getHeight());
    if (!$r0) {
        $errors = true;
    }
    unset($p['os_storage']);
    unset($p['os_path']);
    if (($width > 1024 || $height > 1024) && !$errors) {
        $ph->scaleImage(1024);
    }
    $p['imgscale'] = 1;
    $r1 = $ph->save($p);
    $link[1] = array('rel' => 'alternate', 'type' => 'text/html', 'href' => z_root() . '/photo/' . $photo_hash . '-1.' . $ph->getExt(), 'width' => $ph->getWidth(), 'height' => $ph->getHeight());
    if (!$r1) {
        $errors = true;
    }
    if (($width > 640 || $height > 640) && !$errors) {
        $ph->scaleImage(640);
    }
    $p['imgscale'] = 2;
    $r2 = $ph->save($p);
    $link[2] = array('rel' => 'alternate', 'type' => 'text/html', 'href' => z_root() . '/photo/' . $photo_hash . '-2.' . $ph->getExt(), 'width' => $ph->getWidth(), 'height' => $ph->getHeight());
    if (!$r2) {
        $errors = true;
    }
    if (($width > 320 || $height > 320) && !$errors) {
        $ph->scaleImage(320);
    }
    $p['imgscale'] = 3;
    $r3 = $ph->save($p);
    $link[3] = array('rel' => 'alternate', 'type' => 'text/html', 'href' => z_root() . '/photo/' . $photo_hash . '-3.' . $ph->getExt(), 'width' => $ph->getWidth(), 'height' => $ph->getHeight());
    if (!$r3) {
        $errors = true;
    }
    if ($errors) {
        q("delete from photo where resource_id = '%s' and uid = %d", dbesc($photo_hash), intval($channel_id));
        $ret['message'] = t('Photo storage failed.');
        logger('photo_upload: photo store failed.');
        call_hooks('photo_upload_end', $ret);
        return $ret;
    }
    $item_hidden = $visible ? 0 : 1;
    $lat = $lon = null;
    if ($exif && $exif['GPS']) {
        if (feature_enabled($channel_id, 'photo_location')) {
            $lat = getGps($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef']);
            $lon = getGps($exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef']);
        }
    }
    $title = $args['description'] ? $args['description'] : $args['filename'];
    $large_photos = feature_enabled($channel['channel_id'], 'large_photos');
    linkify_tags($a, $args['body'], $channel_id);
    if ($large_photos) {
        $scale = 1;
        $width = $link[1]['width'];
        $height = $link[1]['height'];
        $tag = $r1 ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]';
    } else {
        $scale = 2;
        $width = $link[2]['width'];
        $height = $link[2]['height'];
        $tag = $r2 ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]';
    }
    $author_link = '[zrl=' . z_root() . '/channel/' . $channel['channel_address'] . ']' . $channel['channel_name'] . '[/zrl]';
    $photo_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' . t('a new photo') . '[/zrl]';
    $album_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album) . ']' . (strlen($album) ? $album : '/') . '[/zrl]';
    $activity_format = sprintf(t('%1$s posted %2$s to %3$s', 'photo_upload'), $author_link, $photo_link, $album_link);
    $summary = ($args['body'] ? $args['body'] : '') . '[footer]' . $activity_format . '[/footer]';
    $obj_body = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' . $tag . z_root() . "/photo/{$photo_hash}-{$scale}." . $ph->getExt() . '[/zmg]' . '[/zrl]';
    // Create item object
    $object = array('type' => ACTIVITY_OBJ_PHOTO, 'title' => $title, 'created' => $p['created'], 'edited' => $p['edited'], 'id' => z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash, 'link' => $link, 'body' => $obj_body);
    $target = array('type' => ACTIVITY_OBJ_ALBUM, 'title' => $album ? $album : '/', 'id' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album));
    // Create item container
    if ($args['item']) {
        foreach ($args['item'] as $i) {
            $item = get_item_elements($i);
            $force = false;
            if ($item['mid'] === $item['parent_mid']) {
                $item['body'] = $summary;
                $item['obj_type'] = ACTIVITY_OBJ_PHOTO;
                $item['obj'] = json_encode($object);
                $item['tgt_type'] = ACTIVITY_OBJ_ALBUM;
                $item['target'] = json_encode($target);
                if ($item['author_xchan'] === $channel['channel_hash']) {
                    $item['sig'] = base64url_encode(rsa_sign($item['body'], $channel['channel_prvkey']));
                    $item['item_verified'] = 1;
                } else {
                    $item['sig'] = '';
                }
                $force = true;
            }
            $r = q("select id, edited from item where mid = '%s' and uid = %d limit 1", dbesc($item['mid']), intval($channel['channel_id']));
            if ($r) {
                if ($item['edited'] > $r[0]['edited'] || $force) {
                    $item['id'] = $r[0]['id'];
                    $item['uid'] = $channel['channel_id'];
                    item_store_update($item, false, $deliver);
                    continue;
                }
            } else {
                $item['aid'] = $channel['channel_account_id'];
                $item['uid'] = $channel['channel_id'];
                $item_result = item_store($item, false, $deliver);
            }
        }
    } else {
        $mid = item_message_id();
        $arr = array();
        if ($lat && $lon) {
            $arr['coord'] = $lat . ' ' . $lon;
        }
        $arr['aid'] = $account_id;
        $arr['uid'] = $channel_id;
        $arr['mid'] = $mid;
        $arr['parent_mid'] = $mid;
        $arr['item_hidden'] = $item_hidden;
        $arr['resource_type'] = 'photo';
        $arr['resource_id'] = $photo_hash;
        $arr['owner_xchan'] = $channel['channel_hash'];
        $arr['author_xchan'] = $observer['xchan_hash'];
        $arr['title'] = $title;
        $arr['allow_cid'] = $ac['allow_cid'];
        $arr['allow_gid'] = $ac['allow_gid'];
        $arr['deny_cid'] = $ac['deny_cid'];
        $arr['deny_gid'] = $ac['deny_gid'];
        $arr['verb'] = ACTIVITY_POST;
        $arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
        $arr['obj'] = json_encode($object);
        $arr['tgt_type'] = ACTIVITY_OBJ_ALBUM;
        $arr['target'] = json_encode($target);
        $arr['item_wall'] = 1;
        $arr['item_origin'] = 1;
        $arr['item_thread_top'] = 1;
        $arr['item_private'] = intval($acl->is_private());
        $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
        $arr['body'] = $summary;
        // this one is tricky because the item and the photo have the same permissions, those of the photo.
        // Use the channel read_stream permissions to get the correct public_policy for the item and recalculate the
        // private flag accordingly. This may cause subtle bugs due to custom permissions roles. We want to use
        // public policy when federating items to other sites, but should probably ignore them when accessing the item
        // in the photos pages - using the photos permissions instead. We need the public policy to keep the photo
        // linked item from leaking into the feed when somebody has a channel with read_stream restrictions.
        $arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_stream'), true);
        if ($arr['public_policy']) {
            $arr['item_private'] = 1;
        }
        $result = item_store($arr, false, $deliver);
        $item_id = $result['item_id'];
        if ($visible && $deliver) {
            Zotlabs\Daemon\Master::Summon(array('Notifier', 'wall-new', $item_id));
        }
    }
    $ret['success'] = true;
    $ret['item'] = $arr;
    $ret['body'] = $obj_body;
    $ret['resource_id'] = $photo_hash;
    $ret['photoitem_id'] = $item_id;
    call_hooks('photo_upload_end', $ret);
    return $ret;
}
Esempio n. 13
0
 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'];
     }
 }
Esempio n. 14
0
 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;
     }
 }