function post() { if ($_POST['room_name']) { $room = strip_tags(trim($_POST['room_name'])); } if (!$room || !local_channel()) { return; } $channel = \App::get_channel(); if ($_POST['action'] === 'drop') { logger('delete chatroom'); Zlib\Chatroom::destroy($channel, array('cr_name' => $room)); goaway(z_root() . '/chat/' . $channel['channel_address']); } $acl = new \Zotlabs\Access\AccessList($channel); $acl->set_from_array($_REQUEST); $arr = $acl->get(); $arr['name'] = $room; $arr['expire'] = intval($_POST['chat_expire']); if (intval($arr['expire']) < 0) { $arr['expire'] = 0; } Zlib\Chatroom::create($channel, $arr); $x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1", dbesc($room), intval(local_channel())); build_sync_packet(0, array('chatroom' => $x)); if ($x) { goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']); } // that failed. Try again perhaps? goaway(z_root() . '/chat/' . $channel['channel_address'] . '/new'); }
/** * * @param object &$a */ function filestorage_post(&$a) { $channel_id = x($_POST, 'uid') ? intval($_POST['uid']) : 0; if (!$channel_id || !local_channel() || $channel_id != local_channel()) { notice(t('Permission denied.') . EOL); return; } $recurse = x($_POST, 'recurse') ? intval($_POST['recurse']) : 0; $resource = x($_POST, 'filehash') ? notags($_POST['filehash']) : ''; $notify = x($_POST, 'notify') ? intval($_POST['notify']) : 0; if (!$resource) { notice(t('Item not found.') . EOL); return; } $channel = App::get_channel(); $acl = new Zotlabs\Access\AccessList($channel); $acl->set_from_array($_REQUEST); $x = $acl->get(); $cloudPath = get_parent_cloudpath($channel_id, $channel['channel_address'], $resource); //get the object before permissions change so we can catch eventual former allowed members $object = get_file_activity_object($channel_id, $resource, $cloudPath); attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse); file_activity($channel_id, $object, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], 'post', $notify); goaway($cloudPath); }
function thing_init(&$a) { if (!local_channel()) { return; } $channel = App::get_channel(); $term_hash = $_REQUEST['term_hash'] ? $_REQUEST['term_hash'] : ''; $name = escape_tags($_REQUEST['term']); $verb = escape_tags($_REQUEST['verb']); $activity = intval($_REQUEST['activity']); $profile_guid = escape_tags($_REQUEST['profile_assign']); $url = $_REQUEST['link']; $photo = $_REQUEST['img']; $hash = random_string(); $verbs = obj_verbs(); /** * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants" * We use the first person form when creating an activity, but the third person for use in activities * @FIXME There is no accounting for verb gender for languages where this is significant. We may eventually * require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module. */ $translated_verb = $verbs[$verb][1]; /* * The site administrator can do things that normals cannot. * This is restricted because it will likely cause * an activitystreams protocol violation and the activity might * choke in some other network and result in unnecessary * support requests. It isn't because we're trying to be heavy-handed * about what you can and can't do. */ if (!$translated_verb) { if (is_site_admin()) { $translated_verb = $verb; } } /* * Things, objects: We do not provide definite (a, an) or indefinite (the) articles or singular/plural designators * That needs to be specified in your thing. e.g. Mike has "a carrot", Greg wants "balls", Bob likes "the Boston Red Sox". */ /* * Future work on this module might produce more complex activities with targets, e.g. Phillip likes Karen's moustache * and to describe other non-thing objects like channels, such as Karl wants Susan - where Susan represents a channel profile. */ if (!$name || !$translated_verb) { return; } $acl = new Zotlabs\Access\AccessList($channel); 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); } $x = $acl->get(); if ($term_hash) { $t = q("select * from obj where obj_obj = '%s' and obj_channel = %d limit 1", dbesc($term_hash), intval(local_channel())); if (!$t) { notice(t('Item not found.') . EOL); return; } $orig_record = $t[0]; if ($photo != $orig_record['obj_imgurl']) { $arr = import_xchan_photo($photo, get_observer_hash(), true); $local_photo = $arr[0]; $local_photo_type = $arr[3]; } else { $local_photo = $orig_record['obj_imgurl']; } $r = q("update obj set obj_term = '%s', obj_url = '%s', obj_imgurl = '%s', obj_edited = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where obj_obj = '%s' and obj_channel = %d ", dbesc($name), dbesc($url ? $url : z_root() . '/thing/' . $term_hash), dbesc($local_photo), dbesc(datetime_convert()), dbesc($x['allow_cid']), dbesc($x['allow_gid']), dbesc($x['deny_cid']), dbesc($x['deny_gid']), dbesc($term_hash), intval(local_channel())); info(t('Thing updated') . EOL); $r = q("select * from obj where obj_channel = %d and obj_obj = '%s' limit 1", intval(local_channel()), dbesc($term_hash)); if ($r) { build_sync_packet(0, array('obj' => $r)); } return; } $sql = $profile_guid ? " and profile_guid = '" . dbesc($profile_guid) . "' " : " and is_default = 1 "; $p = q("select profile_guid, is_default from profile where uid = %d {$sql} limit 1", intval(local_channel())); if ($p) { $profile = $p[0]; } else { return; } $local_photo = null; if ($photo) { $arr = import_xchan_photo($photo, get_observer_hash(), true); $local_photo = $arr[0]; $local_photo_type = $arr[3]; } $created = datetime_convert(); $url = $url ? $url : z_root() . '/thing/' . $hash; $r = q("insert into obj ( obj_page, obj_verb, obj_type, obj_channel, obj_obj, obj_term, obj_url, obj_imgurl, obj_created, obj_edited, allow_cid, allow_gid, deny_cid, deny_gid ) values ('%s','%s', %d, %d, '%s','%s','%s','%s','%s','%s','%s','%s','%s','%s') ", dbesc($profile['profile_guid']), dbesc($verb), intval(TERM_OBJ_THING), intval(local_channel()), dbesc($hash), dbesc($name), dbesc($url), dbesc($photo ? $local_photo : ''), dbesc($created), dbesc($created), dbesc($x['allow_cid']), dbesc($x['allow_gid']), dbesc($x['deny_cid']), dbesc($x['deny_gid'])); if (!$r) { notice(t('Object store: failed')); return; } info(t('Thing added')); $r = q("select * from obj where obj_channel = %d and obj_obj = '%s' limit 1", intval(local_channel()), dbesc($hash)); if ($r) { build_sync_packet(0, array('obj' => $r)); } if ($activity) { $arr = array(); $links = array(array('rel' => 'alternate', 'type' => 'text/html', 'href' => $url)); if ($local_photo) { $links[] = array('rel' => 'photo', 'type' => $local_photo_type, 'href' => $local_photo); } $objtype = ACTIVITY_OBJ_THING; $obj = json_encode(array('type' => $objtype, 'id' => $url, 'link' => $links, 'title' => $name, 'content' => $name)); $bodyverb = str_replace('OBJ: ', '', t('OBJ: %1$s %2$s %3$s')); $arr['owner_xchan'] = $channel['channel_hash']; $arr['author_xchan'] = $channel['channel_hash']; $arr['item_origin'] = 1; $arr['item_wall'] = 1; $arr['item_thread_top'] = 1; $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]'; $plink = '[zrl=' . $url . ']' . $name . '[/zrl]'; $arr['body'] = sprintf($bodyverb, $ulink, $translated_verb, $plink); if ($local_photo) { $arr['body'] .= "\n\n[zmg]" . $local_photo . "[/zmg]"; } $arr['verb'] = $verb; $arr['obj_type'] = $objtype; $arr['object'] = $obj; if (!$profile['is_default']) { $arr['item_private'] = true; $str = ''; $r = q("select abook_xchan from abook where abook_channel = %d and abook_profile = '%s'", intval(local_channel()), dbesc($profile_guid)); if ($r) { $arr['allow_cid'] = ''; foreach ($r as $rr) { $arr['allow_cid'] .= '<' . $rr['abook_xchan'] . '>'; } } else { $arr['allow_cid'] = '<' . get_observer_hash() . '>'; } } $ret = post_activity_item($arr); } }
function post() { $channel = \App::get_channel(); check_form_security_token_redirectOnErr('/settings', 'settings'); call_hooks('settings_post', $_POST); $set_perms = ''; $role = x($_POST, 'permissions_role') ? notags(trim($_POST['permissions_role'])) : ''; $oldrole = get_pconfig(local_channel(), 'system', 'permissions_role'); if ($role != $oldrole || $role === 'custom') { if ($role === 'custom') { $hide_presence = x($_POST, 'hide_presence') && intval($_POST['hide_presence']) == 1 ? 1 : 0; $publish = x($_POST, 'profile_in_directory') && intval($_POST['profile_in_directory']) == 1 ? 1 : 0; $def_group = x($_POST, 'group-selection') ? notags(trim($_POST['group-selection'])) : ''; $r = q("update channel set channel_default_group = '%s' where channel_id = %d", dbesc($def_group), intval(local_channel())); $global_perms = \Zotlabs\Access\Permissions::Perms(); foreach ($global_perms as $k => $v) { \Zotlabs\Access\PermissionLimits::Set(local_channel(), $k, intval($_POST[$k])); } $acl = new \Zotlabs\Access\AccessList($channel); $acl->set_from_array($_POST); $x = $acl->get(); $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s', \n\t\t\t\t\tchannel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d", dbesc($x['allow_cid']), dbesc($x['allow_gid']), dbesc($x['deny_cid']), dbesc($x['deny_gid']), intval(local_channel())); } else { $role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($_POST['permissions_role']); if (!$role_permissions) { notice('Permissions category could not be found.'); return; } $hide_presence = 1 - intval($role_permissions['online']); if ($role_permissions['default_collection']) { $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc(t('Friends'))); if (!$r) { require_once 'include/group.php'; group_add(local_channel(), t('Friends')); group_add_member(local_channel(), t('Friends'), $channel['channel_hash']); $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc(t('Friends'))); } if ($r) { q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d", dbesc($r[0]['hash']), dbesc('<' . $r[0]['hash'] . '>'), intval(local_channel())); } else { notice(sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL); return; } } else { q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '', \n\t\t\t\t\t\tchannel_deny_cid = '' where channel_id = %d", intval(local_channel())); } $x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']); foreach ($x as $k => $v) { set_abconfig(local_channel(), $channel['channel_hash'], 'my_perms', $k, $v); if ($role_permissions['perms_auto']) { set_pconfig(local_channel(), 'autoperms', $k, $v); } else { del_pconfig(local_channel(), 'autoperms', $k); } } if ($role_permissions['limits']) { foreach ($role_permissions['limits'] as $k => $v) { \Zotlabs\Access\PermissionLimits::Set(local_channel(), $k, $v); } } if (array_key_exists('directory_publish', $role_permissions)) { $publish = intval($role_permissions['directory_publish']); } } set_pconfig(local_channel(), 'system', 'hide_online_status', $hide_presence); set_pconfig(local_channel(), 'system', 'permissions_role', $role); } $username = x($_POST, 'username') ? notags(trim($_POST['username'])) : ''; $timezone = x($_POST, 'timezone_select') ? notags(trim($_POST['timezone_select'])) : ''; $defloc = x($_POST, 'defloc') ? notags(trim($_POST['defloc'])) : ''; $openid = x($_POST, 'openid_url') ? notags(trim($_POST['openid_url'])) : ''; $maxreq = x($_POST, 'maxreq') ? intval($_POST['maxreq']) : 0; $expire = x($_POST, 'expire') ? intval($_POST['expire']) : 0; $evdays = x($_POST, 'evdays') ? intval($_POST['evdays']) : 3; $photo_path = x($_POST, 'photo_path') ? escape_tags(trim($_POST['photo_path'])) : ''; $attach_path = x($_POST, 'attach_path') ? escape_tags(trim($_POST['attach_path'])) : ''; $channel_menu = x($_POST['channel_menu']) ? htmlspecialchars_decode(trim($_POST['channel_menu']), ENT_QUOTES) : ''; $expire_items = x($_POST, 'expire_items') ? intval($_POST['expire_items']) : 0; $expire_starred = x($_POST, 'expire_starred') ? intval($_POST['expire_starred']) : 0; $expire_photos = x($_POST, 'expire_photos') ? intval($_POST['expire_photos']) : 0; $expire_network_only = x($_POST, 'expire_network_only') ? intval($_POST['expire_network_only']) : 0; $allow_location = x($_POST, 'allow_location') && intval($_POST['allow_location']) == 1 ? 1 : 0; $blocktags = x($_POST, 'blocktags') && intval($_POST['blocktags']) == 1 ? 0 : 1; // this setting is inverted! $unkmail = x($_POST, 'unkmail') && intval($_POST['unkmail']) == 1 ? 1 : 0; $cntunkmail = x($_POST, 'cntunkmail') ? intval($_POST['cntunkmail']) : 0; $suggestme = x($_POST, 'suggestme') ? intval($_POST['suggestme']) : 0; $post_newfriend = $_POST['post_newfriend'] == 1 ? 1 : 0; $post_joingroup = $_POST['post_joingroup'] == 1 ? 1 : 0; $post_profilechange = $_POST['post_profilechange'] == 1 ? 1 : 0; $adult = $_POST['adult'] == 1 ? 1 : 0; $cal_first_day = x($_POST, 'first_day') && intval($_POST['first_day']) == 1 ? 1 : 0; $pageflags = $channel['channel_pageflags']; $existing_adult = $pageflags & PAGE_ADULT ? 1 : 0; if ($adult != $existing_adult) { $pageflags = $pageflags ^ PAGE_ADULT; } $notify = 0; if (x($_POST, 'notify1')) { $notify += intval($_POST['notify1']); } if (x($_POST, 'notify2')) { $notify += intval($_POST['notify2']); } if (x($_POST, 'notify3')) { $notify += intval($_POST['notify3']); } if (x($_POST, 'notify4')) { $notify += intval($_POST['notify4']); } if (x($_POST, 'notify5')) { $notify += intval($_POST['notify5']); } if (x($_POST, 'notify6')) { $notify += intval($_POST['notify6']); } if (x($_POST, 'notify7')) { $notify += intval($_POST['notify7']); } if (x($_POST, 'notify8')) { $notify += intval($_POST['notify8']); } $vnotify = 0; if (x($_POST, 'vnotify1')) { $vnotify += intval($_POST['vnotify1']); } if (x($_POST, 'vnotify2')) { $vnotify += intval($_POST['vnotify2']); } if (x($_POST, 'vnotify3')) { $vnotify += intval($_POST['vnotify3']); } if (x($_POST, 'vnotify4')) { $vnotify += intval($_POST['vnotify4']); } if (x($_POST, 'vnotify5')) { $vnotify += intval($_POST['vnotify5']); } if (x($_POST, 'vnotify6')) { $vnotify += intval($_POST['vnotify6']); } if (x($_POST, 'vnotify7')) { $vnotify += intval($_POST['vnotify7']); } if (x($_POST, 'vnotify8')) { $vnotify += intval($_POST['vnotify8']); } if (x($_POST, 'vnotify9')) { $vnotify += intval($_POST['vnotify9']); } if (x($_POST, 'vnotify10')) { $vnotify += intval($_POST['vnotify10']); } if (x($_POST, 'vnotify11')) { $vnotify += intval($_POST['vnotify11']); } $always_show_in_notices = x($_POST, 'always_show_in_notices') ? 1 : 0; $err = ''; $name_change = false; if ($username != $channel['channel_name']) { $name_change = true; require_once 'include/channel.php'; $err = validate_channelname($username); if ($err) { notice($err); return; } } if ($timezone != $channel['channel_timezone']) { if (strlen($timezone)) { date_default_timezone_set($timezone); } } set_pconfig(local_channel(), 'system', 'use_browser_location', $allow_location); set_pconfig(local_channel(), 'system', 'suggestme', $suggestme); set_pconfig(local_channel(), 'system', 'post_newfriend', $post_newfriend); set_pconfig(local_channel(), 'system', 'post_joingroup', $post_joingroup); set_pconfig(local_channel(), 'system', 'post_profilechange', $post_profilechange); set_pconfig(local_channel(), 'system', 'blocktags', $blocktags); set_pconfig(local_channel(), 'system', 'channel_menu', $channel_menu); set_pconfig(local_channel(), 'system', 'vnotify', $vnotify); set_pconfig(local_channel(), 'system', 'always_show_in_notices', $always_show_in_notices); set_pconfig(local_channel(), 'system', 'evdays', $evdays); set_pconfig(local_channel(), 'system', 'photo_path', $photo_path); set_pconfig(local_channel(), 'system', 'attach_path', $attach_path); set_pconfig(local_channel(), 'system', 'cal_first_day', $cal_first_day); $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d {$set_perms} where channel_id = %d", dbesc($username), intval($pageflags), dbesc($timezone), dbesc($defloc), intval($notify), intval($unkmail), intval($maxreq), intval($expire), intval(local_channel())); if ($r) { info(t('Settings updated.') . EOL); } if (!is_null($publish)) { $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d", intval($publish), intval(local_channel())); } if ($name_change) { $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'", dbesc($username), dbesc(datetime_convert()), dbesc($channel['channel_hash'])); $r = q("update profile set fullname = '%s' where uid = %d and is_default = 1", dbesc($username), intval($channel['channel_id'])); } \Zotlabs\Daemon\Master::Summon(array('Directory', local_channel())); build_sync_packet(); if ($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) { // FIXME - set to un-verified, blocked and redirect to logout // Why? Are we verifying people or email addresses? } goaway(z_root() . '/settings'); return; // NOTREACHED }
function post() { if (!local_channel()) { return; } if ($_SESSION['delegate']) { return; } $channel = \App::get_channel(); logger('mod_settings: ' . print_r($_REQUEST, true)); if (argc() > 1 && argv(1) === 'oauth' && x($_POST, 'remove')) { check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); $key = $_POST['remove']; q("DELETE FROM tokens WHERE id='%s' AND uid=%d", dbesc($key), local_channel()); goaway(z_root() . "/settings/oauth/"); return; } if (argc() > 2 && argv(1) === 'oauth' && (argv(2) === 'edit' || argv(2) === 'add') && x($_POST, 'submit')) { check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); $name = x($_POST, 'name') ? $_POST['name'] : ''; $key = x($_POST, 'key') ? $_POST['key'] : ''; $secret = x($_POST, 'secret') ? $_POST['secret'] : ''; $redirect = x($_POST, 'redirect') ? $_POST['redirect'] : ''; $icon = x($_POST, 'icon') ? $_POST['icon'] : ''; $ok = true; if ($name == '') { $ok = false; notice(t('Name is required') . EOL); } if ($key == '' || $secret == '') { $ok = false; notice(t('Key and Secret are required') . EOL); } if ($ok) { if ($_POST['submit'] == t("Update")) { $r = q("UPDATE clients SET\n\t\t\t\t\t\t\t\tclient_id='%s',\n\t\t\t\t\t\t\t\tpw='%s',\n\t\t\t\t\t\t\t\tclname='%s',\n\t\t\t\t\t\t\t\tredirect_uri='%s',\n\t\t\t\t\t\t\t\ticon='%s',\n\t\t\t\t\t\t\t\tuid=%d\n\t\t\t\t\t\t\tWHERE client_id='%s'", dbesc($key), dbesc($secret), dbesc($name), dbesc($redirect), dbesc($icon), intval(local_channel()), dbesc($key)); } else { $r = q("INSERT INTO clients (client_id, pw, clname, redirect_uri, icon, uid)\n\t\t\t\t\t\tVALUES ('%s','%s','%s','%s','%s',%d)", dbesc($key), dbesc($secret), dbesc($name), dbesc($redirect), dbesc($icon), intval(local_channel())); $r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ", dbesc($key), intval(local_channel()), dbesc('all')); } } goaway(z_root() . "/settings/oauth/"); return; } if (argc() > 1 && argv(1) == 'featured') { check_form_security_token_redirectOnErr('/settings/featured', 'settings_featured'); call_hooks('feature_settings_post', $_POST); build_sync_packet(); return; } if (argc() > 1 && argv(1) == 'tokens') { check_form_security_token_redirectOnErr('/settings/tokens', 'settings_tokens'); $token_errs = 0; if (array_key_exists('token', $_POST)) { $atoken_id = $_POST['atoken_id'] ? intval($_POST['atoken_id']) : 0; $name = trim(escape_tags($_POST['name'])); $token = trim($_POST['token']); if (!$name || !$token) { $token_errs++; } if (trim($_POST['expires'])) { $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_POST['expires']); } else { $expires = NULL_DATE; } $max_atokens = service_class_fetch(local_channel(), 'access_tokens'); if ($max_atokens) { $r = q("select count(atoken_id) as total where atoken_uid = %d", intval(local_channel())); if ($r && intval($r[0]['total']) >= $max_tokens) { notice(sprintf(t('This channel is limited to %d tokens'), $max_tokens) . EOL); return; } } } if ($token_errs) { notice(t('Name and Password are required.') . EOL); return; } if ($atoken_id) { $r = q("update atoken set atoken_name = '%s', atoken_token = '%s' atoken_expires = '%s' \n\t\t\t\t\twhere atoken_id = %d and atoken_uid = %d", dbesc($name), dbesc($token), dbesc($expires), intval($atoken_id), intval($channel['channel_id'])); } else { $r = q("insert into atoken ( atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires )\n\t\t\t\t\tvalues ( %d, %d, '%s', '%s', '%s' ) ", intval($channel['channel_account_id']), intval($channel['channel_id']), dbesc($name), dbesc($token), dbesc($expires)); } info(t('Token saved.') . EOL); return; } if (argc() > 1 && argv(1) === 'features') { check_form_security_token_redirectOnErr('/settings/features', 'settings_features'); // Build list of features and check which are set $features = get_features(); $all_features = array(); foreach ($features as $k => $v) { foreach ($v as $f) { $all_features[] = $f[0]; } } foreach ($all_features as $k) { if (x($_POST, "feature_{$k}")) { set_pconfig(local_channel(), 'feature', $k, 1); } else { set_pconfig(local_channel(), 'feature', $k, 0); } } build_sync_packet(); return; } if (argc() > 1 && argv(1) == 'display') { check_form_security_token_redirectOnErr('/settings/display', 'settings_display'); $theme = x($_POST, 'theme') ? notags(trim($_POST['theme'])) : \App::$channel['channel_theme']; $mobile_theme = x($_POST, 'mobile_theme') ? notags(trim($_POST['mobile_theme'])) : ''; $preload_images = x($_POST, 'preload_images') ? intval($_POST['preload_images']) : 0; $user_scalable = x($_POST, 'user_scalable') ? intval($_POST['user_scalable']) : 0; $nosmile = x($_POST, 'nosmile') ? intval($_POST['nosmile']) : 0; $title_tosource = x($_POST, 'title_tosource') ? intval($_POST['title_tosource']) : 0; $channel_list_mode = x($_POST, 'channel_list_mode') ? intval($_POST['channel_list_mode']) : 0; $network_list_mode = x($_POST, 'network_list_mode') ? intval($_POST['network_list_mode']) : 0; $channel_divmore_height = x($_POST, 'channel_divmore_height') ? intval($_POST['channel_divmore_height']) : 400; if ($channel_divmore_height < 50) { $channel_divmore_height = 50; } $network_divmore_height = x($_POST, 'network_divmore_height') ? intval($_POST['network_divmore_height']) : 400; if ($network_divmore_height < 50) { $network_divmore_height = 50; } $browser_update = x($_POST, 'browser_update') ? intval($_POST['browser_update']) : 0; $browser_update = $browser_update * 1000; if ($browser_update < 10000) { $browser_update = 10000; } $itemspage = x($_POST, 'itemspage') ? intval($_POST['itemspage']) : 20; if ($itemspage > 100) { $itemspage = 100; } if ($mobile_theme == "---") { del_pconfig(local_channel(), 'system', 'mobile_theme'); } else { set_pconfig(local_channel(), 'system', 'mobile_theme', $mobile_theme); } set_pconfig(local_channel(), 'system', 'preload_images', $preload_images); set_pconfig(local_channel(), 'system', 'user_scalable', $user_scalable); set_pconfig(local_channel(), 'system', 'update_interval', $browser_update); set_pconfig(local_channel(), 'system', 'itemspage', $itemspage); set_pconfig(local_channel(), 'system', 'no_smilies', 1 - intval($nosmile)); set_pconfig(local_channel(), 'system', 'title_tosource', $title_tosource); set_pconfig(local_channel(), 'system', 'channel_list_mode', $channel_list_mode); set_pconfig(local_channel(), 'system', 'network_list_mode', $network_list_mode); set_pconfig(local_channel(), 'system', 'channel_divmore_height', $channel_divmore_height); set_pconfig(local_channel(), 'system', 'network_divmore_height', $network_divmore_height); if ($theme == \App::$channel['channel_theme']) { // call theme_post only if theme has not been changed if (($themeconfigfile = $this->get_theme_config_file($theme)) != null) { require_once $themeconfigfile; theme_post($a); } } $r = q("UPDATE channel SET channel_theme = '%s' WHERE channel_id = %d", dbesc($theme), intval(local_channel())); call_hooks('display_settings_post', $_POST); build_sync_packet(); goaway(z_root() . '/settings/display'); return; // NOTREACHED } if (argc() > 1 && argv(1) === 'account') { check_form_security_token_redirectOnErr('/settings/account', 'settings_account'); call_hooks('account_settings_post', $_POST); // call_hooks('settings_account', $_POST); $errs = array(); $email = x($_POST, 'email') ? trim(notags($_POST['email'])) : ''; $account = \App::get_account(); if ($email != $account['account_email']) { if (!valid_email($email)) { $errs[] = t('Not valid email.'); } $adm = trim(get_config('system', 'admin_email')); if ($adm && strcasecmp($email, $adm) == 0) { $errs[] = t('Protected email address. Cannot change to that email.'); $email = \App::$user['email']; } if (!$errs) { $r = q("update account set account_email = '%s' where account_id = %d", dbesc($email), intval($account['account_id'])); if (!$r) { $errs[] = t('System failure storing new email. Please try again.'); } } } if ($errs) { foreach ($errs as $err) { notice($err . EOL); } $errs = array(); } if (x($_POST, 'npassword') || x($_POST, 'confirm')) { $origpass = trim($_POST['origpass']); require_once 'include/auth.php'; if (!account_verify_password($email, $origpass)) { $errs[] = t('Password verification failed.'); } $newpass = trim($_POST['npassword']); $confirm = trim($_POST['confirm']); if ($newpass != $confirm) { $errs[] = t('Passwords do not match. Password unchanged.'); } if (!x($newpass) || !x($confirm)) { $errs[] = t('Empty passwords are not allowed. Password unchanged.'); } if (!$errs) { $salt = random_string(32); $password_encoded = hash('whirlpool', $salt . $newpass); $r = q("update account set account_salt = '%s', account_password = '******', account_password_changed = '%s' \n\t\t\t\t\t\twhere account_id = %d", dbesc($salt), dbesc($password_encoded), dbesc(datetime_convert()), intval(get_account_id())); if ($r) { info(t('Password changed.') . EOL); } else { $errs[] = t('Password update failed. Please try again.'); } } } if ($errs) { foreach ($errs as $err) { notice($err . EOL); } } goaway(z_root() . '/settings/account'); } check_form_security_token_redirectOnErr('/settings', 'settings'); call_hooks('settings_post', $_POST); $set_perms = ''; $role = x($_POST, 'permissions_role') ? notags(trim($_POST['permissions_role'])) : ''; $oldrole = get_pconfig(local_channel(), 'system', 'permissions_role'); if ($role != $oldrole || $role === 'custom') { if ($role === 'custom') { $hide_presence = x($_POST, 'hide_presence') && intval($_POST['hide_presence']) == 1 ? 1 : 0; $publish = x($_POST, 'profile_in_directory') && intval($_POST['profile_in_directory']) == 1 ? 1 : 0; $def_group = x($_POST, 'group-selection') ? notags(trim($_POST['group-selection'])) : ''; $r = q("update channel set channel_default_group = '%s' where channel_id = %d", dbesc($def_group), intval(local_channel())); $global_perms = get_perms(); foreach ($global_perms as $k => $v) { $set_perms .= ', ' . $v[0] . ' = ' . intval($_POST[$k]) . ' '; } $acl = new \Zotlabs\Access\AccessList($channel); $acl->set_from_array($_POST); $x = $acl->get(); $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s', \n\t\t\t\t\tchannel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d", dbesc($x['allow_cid']), dbesc($x['allow_gid']), dbesc($x['deny_cid']), dbesc($x['deny_gid']), intval(local_channel())); } else { $role_permissions = get_role_perms($_POST['permissions_role']); if (!$role_permissions) { notice('Permissions category could not be found.'); return; } $hide_presence = 1 - intval($role_permissions['online']); if ($role_permissions['default_collection']) { $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc(t('Friends'))); if (!$r) { require_once 'include/group.php'; group_add(local_channel(), t('Friends')); group_add_member(local_channel(), t('Friends'), $channel['channel_hash']); $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc(t('Friends'))); } if ($r) { q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d", dbesc($r[0]['hash']), dbesc('<' . $r[0]['hash'] . '>'), intval(local_channel())); } else { notice(sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL); return; } } else { q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '', \n\t\t\t\t\t\tchannel_deny_cid = '' where channel_id = %d", intval(local_channel())); } $r = q("update abook set abook_my_perms = %d where abook_channel = %d and abook_self = 1", intval(array_key_exists('perms_accept', $role_permissions) ? $role_permissions['perms_accept'] : 0), intval(local_channel())); set_pconfig(local_channel(), 'system', 'autoperms', $role_permissions['perms_auto'] ? intval($role_permissions['perms_accept']) : 0); foreach ($role_permissions as $p => $v) { if (strpos($p, 'channel_') !== false) { $set_perms .= ', ' . $p . ' = ' . intval($v) . ' '; } if ($p === 'directory_publish') { $publish = intval($v); } } } set_pconfig(local_channel(), 'system', 'hide_online_status', $hide_presence); set_pconfig(local_channel(), 'system', 'permissions_role', $role); } $username = x($_POST, 'username') ? notags(trim($_POST['username'])) : ''; $timezone = x($_POST, 'timezone_select') ? notags(trim($_POST['timezone_select'])) : ''; $defloc = x($_POST, 'defloc') ? notags(trim($_POST['defloc'])) : ''; $openid = x($_POST, 'openid_url') ? notags(trim($_POST['openid_url'])) : ''; $maxreq = x($_POST, 'maxreq') ? intval($_POST['maxreq']) : 0; $expire = x($_POST, 'expire') ? intval($_POST['expire']) : 0; $evdays = x($_POST, 'evdays') ? intval($_POST['evdays']) : 3; $photo_path = x($_POST, 'photo_path') ? escape_tags(trim($_POST['photo_path'])) : ''; $attach_path = x($_POST, 'attach_path') ? escape_tags(trim($_POST['attach_path'])) : ''; $channel_menu = x($_POST['channel_menu']) ? htmlspecialchars_decode(trim($_POST['channel_menu']), ENT_QUOTES) : ''; $expire_items = x($_POST, 'expire_items') ? intval($_POST['expire_items']) : 0; $expire_starred = x($_POST, 'expire_starred') ? intval($_POST['expire_starred']) : 0; $expire_photos = x($_POST, 'expire_photos') ? intval($_POST['expire_photos']) : 0; $expire_network_only = x($_POST, 'expire_network_only') ? intval($_POST['expire_network_only']) : 0; $allow_location = x($_POST, 'allow_location') && intval($_POST['allow_location']) == 1 ? 1 : 0; $blocktags = x($_POST, 'blocktags') && intval($_POST['blocktags']) == 1 ? 0 : 1; // this setting is inverted! $unkmail = x($_POST, 'unkmail') && intval($_POST['unkmail']) == 1 ? 1 : 0; $cntunkmail = x($_POST, 'cntunkmail') ? intval($_POST['cntunkmail']) : 0; $suggestme = x($_POST, 'suggestme') ? intval($_POST['suggestme']) : 0; $post_newfriend = $_POST['post_newfriend'] == 1 ? 1 : 0; $post_joingroup = $_POST['post_joingroup'] == 1 ? 1 : 0; $post_profilechange = $_POST['post_profilechange'] == 1 ? 1 : 0; $adult = $_POST['adult'] == 1 ? 1 : 0; $cal_first_day = x($_POST, 'first_day') && intval($_POST['first_day']) == 1 ? 1 : 0; $channel = \App::get_channel(); $pageflags = $channel['channel_pageflags']; $existing_adult = $pageflags & PAGE_ADULT ? 1 : 0; if ($adult != $existing_adult) { $pageflags = $pageflags ^ PAGE_ADULT; } $notify = 0; if (x($_POST, 'notify1')) { $notify += intval($_POST['notify1']); } if (x($_POST, 'notify2')) { $notify += intval($_POST['notify2']); } if (x($_POST, 'notify3')) { $notify += intval($_POST['notify3']); } if (x($_POST, 'notify4')) { $notify += intval($_POST['notify4']); } if (x($_POST, 'notify5')) { $notify += intval($_POST['notify5']); } if (x($_POST, 'notify6')) { $notify += intval($_POST['notify6']); } if (x($_POST, 'notify7')) { $notify += intval($_POST['notify7']); } if (x($_POST, 'notify8')) { $notify += intval($_POST['notify8']); } $vnotify = 0; if (x($_POST, 'vnotify1')) { $vnotify += intval($_POST['vnotify1']); } if (x($_POST, 'vnotify2')) { $vnotify += intval($_POST['vnotify2']); } if (x($_POST, 'vnotify3')) { $vnotify += intval($_POST['vnotify3']); } if (x($_POST, 'vnotify4')) { $vnotify += intval($_POST['vnotify4']); } if (x($_POST, 'vnotify5')) { $vnotify += intval($_POST['vnotify5']); } if (x($_POST, 'vnotify6')) { $vnotify += intval($_POST['vnotify6']); } if (x($_POST, 'vnotify7')) { $vnotify += intval($_POST['vnotify7']); } if (x($_POST, 'vnotify8')) { $vnotify += intval($_POST['vnotify8']); } if (x($_POST, 'vnotify9')) { $vnotify += intval($_POST['vnotify9']); } if (x($_POST, 'vnotify10')) { $vnotify += intval($_POST['vnotify10']); } if (x($_POST, 'vnotify11')) { $vnotify += intval($_POST['vnotify11']); } $always_show_in_notices = x($_POST, 'always_show_in_notices') ? 1 : 0; $channel = \App::get_channel(); $err = ''; $name_change = false; if ($username != $channel['channel_name']) { $name_change = true; require_once 'include/channel.php'; $err = validate_channelname($username); if ($err) { notice($err); return; } } if ($timezone != $channel['channel_timezone']) { if (strlen($timezone)) { date_default_timezone_set($timezone); } } set_pconfig(local_channel(), 'system', 'use_browser_location', $allow_location); set_pconfig(local_channel(), 'system', 'suggestme', $suggestme); set_pconfig(local_channel(), 'system', 'post_newfriend', $post_newfriend); set_pconfig(local_channel(), 'system', 'post_joingroup', $post_joingroup); set_pconfig(local_channel(), 'system', 'post_profilechange', $post_profilechange); set_pconfig(local_channel(), 'system', 'blocktags', $blocktags); set_pconfig(local_channel(), 'system', 'channel_menu', $channel_menu); set_pconfig(local_channel(), 'system', 'vnotify', $vnotify); set_pconfig(local_channel(), 'system', 'always_show_in_notices', $always_show_in_notices); set_pconfig(local_channel(), 'system', 'evdays', $evdays); set_pconfig(local_channel(), 'system', 'photo_path', $photo_path); set_pconfig(local_channel(), 'system', 'attach_path', $attach_path); set_pconfig(local_channel(), 'system', 'cal_first_day', $cal_first_day); $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d {$set_perms} where channel_id = %d", dbesc($username), intval($pageflags), dbesc($timezone), dbesc($defloc), intval($notify), intval($unkmail), intval($maxreq), intval($expire), intval(local_channel())); if ($r) { info(t('Settings updated.') . EOL); } if (!is_null($publish)) { $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d", intval($publish), intval(local_channel())); } if ($name_change) { $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'", dbesc($username), dbesc(datetime_convert()), dbesc($channel['channel_hash'])); $r = q("update profile set fullname = '%s' where uid = %d and is_default = 1", dbesc($username), intval($channel['channel_id'])); } \Zotlabs\Daemon\Master::Summon(array('Directory', local_channel())); build_sync_packet(); //$_SESSION['theme'] = $theme; if ($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) { // FIXME - set to un-verified, blocked and redirect to logout // Why? Are we verifying people or email addresses? } goaway(z_root() . '/settings'); return; // NOTREACHED }
function post() { logger('post: ' . print_r($_REQUEST, true), LOGGER_DATA); if (!local_channel()) { return; } if ($_FILES && array_key_exists('userfile', $_FILES) && intval($_FILES['userfile']['size'])) { $src = $_FILES['userfile']['tmp_name']; if ($src) { $result = parse_ical_file($src, local_channel()); if ($result) { info(t('Calendar entries imported.') . EOL); } else { notice(t('No calendar entries found.') . EOL); } @unlink($src); } goaway(z_root() . '/events'); } $event_id = x($_POST, 'event_id') ? intval($_POST['event_id']) : 0; $event_hash = x($_POST, 'event_hash') ? $_POST['event_hash'] : ''; $xchan = x($_POST, 'xchan') ? dbesc($_POST['xchan']) : ''; $uid = local_channel(); $start_text = escape_tags($_REQUEST['start_text']); $finish_text = escape_tags($_REQUEST['finish_text']); $adjust = intval($_POST['adjust']); $nofinish = intval($_POST['nofinish']); $categories = escape_tags(trim($_POST['category'])); // only allow editing your own events. if ($xchan && $xchan !== get_observer_hash()) { return; } if ($start_text) { $start = $start_text; } else { $start = sprintf('%d-%d-%d %d:%d:0', $startyear, $startmonth, $startday, $starthour, $startminute); } if ($nofinish) { $finish = NULL_DATE; } if ($finish_text) { $finish = $finish_text; } else { $finish = sprintf('%d-%d-%d %d:%d:0', $finishyear, $finishmonth, $finishday, $finishhour, $finishminute); } if ($adjust) { $start = datetime_convert(date_default_timezone_get(), 'UTC', $start); if (!$nofinish) { $finish = datetime_convert(date_default_timezone_get(), 'UTC', $finish); } } else { $start = datetime_convert('UTC', 'UTC', $start); if (!$nofinish) { $finish = datetime_convert('UTC', 'UTC', $finish); } } // Don't allow the event to finish before it begins. // It won't hurt anything, but somebody will file a bug report // and we'll waste a bunch of time responding to it. Time that // could've been spent doing something else. $summary = escape_tags(trim($_POST['summary'])); $desc = escape_tags(trim($_POST['desc'])); $location = escape_tags(trim($_POST['location'])); $type = escape_tags(trim($_POST['type'])); require_once 'include/text.php'; linkify_tags($a, $desc, local_channel()); linkify_tags($a, $location, local_channel()); //$action = ($event_hash == '') ? 'new' : "event/" . $event_hash; //fixme: this url gives a wsod if there is a linebreak detected in one of the variables ($desc or $location) //$onerror_url = z_root() . "/events/" . $action . "?summary=$summary&description=$desc&location=$location&start=$start_text&finish=$finish_text&adjust=$adjust&nofinish=$nofinish&type=$type"; $onerror_url = z_root() . "/events"; if (strcmp($finish, $start) < 0 && !$nofinish) { notice(t('Event can not end before it has started.') . EOL); if (intval($_REQUEST['preview'])) { echo t('Unable to generate preview.'); killme(); } goaway($onerror_url); } if (!$summary || !$start) { notice(t('Event title and start time are required.') . EOL); if (intval($_REQUEST['preview'])) { echo t('Unable to generate preview.'); killme(); } goaway($onerror_url); } $share = intval($_POST['share']) ? intval($_POST['share']) : 0; $channel = \App::get_channel(); $acl = new \Zotlabs\Access\AccessList(false); if ($event_id) { $x = q("select * from event where id = %d and uid = %d limit 1", intval($event_id), intval(local_channel())); if (!$x) { notice(t('Event not found.') . EOL); if (intval($_REQUEST['preview'])) { echo t('Unable to generate preview.'); killme(); } return; } $acl->set($x[0]); $created = $x[0]['created']; $edited = datetime_convert(); if ($x[0]['allow_cid'] === '<' . $channel['channel_hash'] . '>' && $x[0]['allow_gid'] === '' && $x[0]['deny_cid'] === '' && $x[0]['deny_gid'] === '') { $share = false; } else { $share = true; } } else { $created = $edited = datetime_convert(); if ($share) { $acl->set_from_array($_POST); } else { $acl->set(array('allow_cid' => '<' . $channel['channel_hash'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '')); } } $post_tags = array(); $channel = \App::get_channel(); $ac = $acl->get(); 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' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))); } } $datarray = array(); $datarray['dtstart'] = $start; $datarray['dtend'] = $finish; $datarray['summary'] = $summary; $datarray['description'] = $desc; $datarray['location'] = $location; $datarray['etype'] = $type; $datarray['adjust'] = $adjust; $datarray['nofinish'] = $nofinish; $datarray['uid'] = local_channel(); $datarray['account'] = get_account_id(); $datarray['event_xchan'] = $channel['channel_hash']; $datarray['allow_cid'] = $ac['allow_cid']; $datarray['allow_gid'] = $ac['allow_gid']; $datarray['deny_cid'] = $ac['deny_cid']; $datarray['deny_gid'] = $ac['deny_gid']; $datarray['private'] = $acl->is_private() ? 1 : 0; $datarray['id'] = $event_id; $datarray['created'] = $created; $datarray['edited'] = $edited; if (intval($_REQUEST['preview'])) { $html = format_event_html($datarray); echo $html; killme(); } $event = event_store_event($datarray); if ($post_tags) { $datarray['term'] = $post_tags; } $item_id = event_store_item($datarray, $event); if ($item_id) { $r = q("select * from item where id = %d", intval($item_id)); if ($r) { xchan_query($r); $sync_item = fetch_post_tags($r); $z = q("select * from event where event_hash = '%s' and uid = %d limit 1", dbesc($r[0]['resource_id']), intval($channel['channel_id'])); if ($z) { build_sync_packet($channel['channel_id'], array('event_item' => array(encode_item($sync_item[0], true)), 'event' => $z)); } } } if ($share) { \Zotlabs\Daemon\Master::Summon(array('Notifier', 'event', $item_id)); } }
/** * @brief This function provides the API endpoints, primarily called by the * JavaScript functions via $.post() calls. * * @return json JSON-formatted structures with a "status" indicator for success * as well as other requested data */ function chess_post(&$a) { if (argc() > 1) { switch (argv(1)) { // API: /chess/settings // Updates game settings for the observer case 'settings': $observer = App::get_observer(); $settings = x($_POST, 'settings') ? $_POST['settings'] : null; $settings = json_decode($settings, true); if (!isset($settings['notify_enabled'])) { json_return_and_die(array('errormsg' => 'Invalid settings', 'status' => false)); } $notify_enable = intval($settings['notify_enabled']); set_xconfig($observer['xchan_hash'], 'chess', 'notifications', $notify_enable); json_return_and_die(array('status' => true)); // API: /chess/resume // Resumes a game specified by "game_id" allowing further moves // API: /chess/resume // Resumes a game specified by "game_id" allowing further moves case 'resume': $observer = App::get_observer(); $game_id = x($_POST, 'game_id') ? $_POST['game_id'] : ''; $g = chess_get_game($game_id); if (!$g['status']) { json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false)); } // Verify that observer is a valid player $game = json_decode($g['game']['obj'], true); if (!in_array($observer['xchan_hash'], $game['players'])) { json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false)); } $success = chess_resume_game($g['game']); if (!$success) { json_return_and_die(array('errormsg' => 'Error resuming game', 'status' => false)); } else { json_return_and_die(array('status' => true)); } // API: /chess/end // Ends a game specified by "game_id" preventing further moves // API: /chess/end // Ends a game specified by "game_id" preventing further moves case 'end': $observer = App::get_observer(); $game_id = x($_POST, 'game_id') ? $_POST['game_id'] : ''; $g = chess_get_game($game_id); if (!$g['status']) { json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false)); } // Verify that observer is a valid player $game = json_decode($g['game']['obj'], true); if (!in_array($observer['xchan_hash'], $game['players'])) { json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false)); } $success = chess_end_game($g['game']); if (!$success) { json_return_and_die(array('errormsg' => 'Error ending game', 'status' => false)); } else { json_return_and_die(array('status' => true)); } // API: /chess/delete // Deletes a game specified by "game_id" // API: /chess/delete // Deletes a game specified by "game_id" case 'delete': if (!local_channel()) { json_return_and_die(array('errormsg' => 'Must be local channel.', 'status' => false)); } $channel = App::get_channel(); $game_id = x($_POST, 'game_id') ? $_POST['game_id'] : ''; $d = chess_delete_game($game_id, $channel); if (!$d['status']) { json_return_and_die(array('errormsg' => 'Error deleting game', 'status' => false)); } else { json_return_and_die(array('status' => true)); } // API: /chess/revert // Reverts a game specified by "game_id" to a previous board position // specified by the "mid" of the child post of the original game post // in the item table // TODO: Determine why the board position in the game item is not actually // being reverted // API: /chess/revert // Reverts a game specified by "game_id" to a previous board position // specified by the "mid" of the child post of the original game post // in the item table // TODO: Determine why the board position in the game item is not actually // being reverted case 'revert': $observer = App::get_observer(); $game_id = $_POST['game_id']; $g = chess_get_game($game_id); if (!$g['status']) { json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false)); } // Verify that observer is a valid player $game = json_decode($g['game']['obj'], true); if (!in_array($observer['xchan_hash'], $game['players'])) { json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false)); } $active = $game['active'] === $observer['xchan_hash'] ? true : false; if (!$active) { json_return_and_die(array('errormsg' => 'It is not your turn', 'status' => false)); } $r = chess_revert_position($g['game'], $observer, $_POST['mid']); if (!$r['status']) { json_return_and_die(array('errormsg' => 'Error reverting game', 'status' => false)); } json_return_and_die(array('status' => true)); // API: /chess/history // Retrieves all the board positions for a game in order to populate the // history viewer in the control panel // API: /chess/history // Retrieves all the board positions for a game in order to populate the // history viewer in the control panel case 'history': $observer = App::get_observer(); $game_id = $_POST['game_id']; $g = chess_get_game($game_id); if (!$g['status']) { json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false)); } // Verify that observer is a valid player $game = json_decode($g['game']['obj'], true); if (!in_array($observer['xchan_hash'], $game['players'])) { json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false)); } $player = array_search($observer['xchan_hash'], $game['players']); $h = chess_get_history($g['game']); if (!$h['status']) { json_return_and_die(array('errormsg' => 'Error retrieving game history', 'status' => false)); } json_return_and_die(array('history' => $h['history'], 'status' => true)); // API: /chess/update // Updates a game specified by "game_id" with a new board position specified // by "newPosFEN" in FEN-format // API: /chess/update // Updates a game specified by "game_id" with a new board position specified // by "newPosFEN" in FEN-format case 'update': $observer = App::get_observer(); $game_id = $_POST['game_id']; $g = chess_get_game($game_id); if (!$g['status']) { json_return_and_die(array('errormsg' => 'Invalid game', 'status' => false)); } // Verify that observer is a valid player $game = json_decode($g['game']['obj'], true); if (!in_array($observer['xchan_hash'], $game['players'])) { json_return_and_die(array('errormsg' => 'You are not a valid player', 'status' => false)); } $player = array_search($observer['xchan_hash'], $game['players']); $active = $game['active'] === $game['players'][$player] ? true : false; json_return_and_die(array('position' => $game['position'], 'myturn' => $active, 'ended' => $game['ended'], 'status' => true)); // API: /chess/move // Adds a new board position by creating a child post for the original // game item. // API: /chess/move // Adds a new board position by creating a child post for the original // game item. case 'move': $observer = App::get_observer(); $game_id = $_POST['game_id']; $newPosFEN = $_POST['newPosFEN']; $g = chess_get_game($game_id); if (!$g['status']) { notice(t('Invalid game.') . EOL); json_return_and_die(array('errormsg' => 'Invalid game ID', 'status' => false)); } // Verify that observer is a valid player $game = json_decode($g['game']['obj'], true); if (!in_array($observer['xchan_hash'], $game['players'])) { notice(t('You are not a player in this game.') . EOL); goaway('/chess'); } $player = array_search($observer['xchan_hash'], $game['players']); $color = $game['colors'][$player]; $active = $game['active'] === $observer['xchan_hash'] ? true : false; if (!$active) { json_return_and_die(array('errormsg' => 'It is not your turn', 'status' => false)); } if (x($game, 'ended') && intval($game['ended']) === 1) { json_return_and_die(array('errormsg' => 'The game is over', 'status' => false)); } $move = chess_make_move($observer, $newPosFEN, $g['game']); if ($move['status']) { $active_xchan = $game['players'][0] === $observer['xchan_hash'] ? $game['players'][1] : $game['players'][0]; if (chess_set_position(chess_get_game($game_id)['game'], $newPosFEN)) { chess_set_active(chess_get_game($game_id)['game'], $active_xchan); } json_return_and_die(array('status' => true)); } else { json_return_and_die(array('errormsg' => 'Move failed', 'status' => false)); } default: break; } } if (argc() > 2) { switch (argv(2)) { // API: /chess/[channelname]/new/ // This endpoint handles the new game form submission and creates a new // game between two channels specified by the standard ACL case 'new': if (!local_channel()) { notice(t('You must be a local channel to create a game.') . EOL); return; } // Ensure ACL specifies exactly one other channel $channel = App::get_channel(); $acl = new Zotlabs\Access\AccessList($channel); $acl->set_from_array($_REQUEST); $perms = $acl->get(); $allow_cid = expand_acl($perms['allow_cid']); $valid = 0; if (count($allow_cid) > 1) { foreach ($allow_cid as $allow) { if ($allow == $channel['channel_hash']) { continue; } $valid++; } } if ($valid != 1) { notice(t('You must select one opponent that is not yourself.') . EOL); return; } else { info(t('Creating new game...') . EOL); // Get the game owner's color choice $color = ''; if ($_POST['color'] === 'white' || $_POST['color'] === 'black') { $color = $_POST['color']; } else { notice(t('You must select white or black.') . EOL); return; } $game = chess_create_game($channel, $color, $acl); if ($game['status']) { goaway('/chess/' . $channel['channel_address'] . '/' . $game['item']['resource_id']); } else { notice(t('Error creating new game.') . EOL); } return; } default: break; } } }
function menu_edit_item($menu_id, $uid, $arr) { $mitem_id = intval($arr['mitem_id']); $mitem_link = escape_tags($arr['mitem_link']); $mitem_desc = escape_tags($arr['mitem_desc']); $mitem_order = intval($arr['mitem_order']); $mitem_flags = intval($arr['mitem_flags']); if (local_channel() == $uid) { $channel = App::get_channel(); } $acl = new Zotlabs\Access\AccessList($channel); $acl->set_from_array($arr); $p = $acl->get(); $r = q("update menu_item set mitem_link = '%s', mitem_desc = '%s', mitem_flags = %d, allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', mitem_order = %d where mitem_channel_id = %d and mitem_menu_id = %d and mitem_id = %d", dbesc($mitem_link), dbesc($mitem_desc), intval($mitem_flags), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), intval($mitem_order), intval($uid), intval($menu_id), intval($mitem_id)); $x = q("update menu set menu_edited = '%s' where menu_id = %d and menu_channel_id = %d", dbesc(datetime_convert()), intval($menu_id), intval($uid)); return $r; }
function post() { logger('mod-photos: photos_post: begin', LOGGER_DEBUG); logger('mod_photos: REQUEST ' . print_r($_REQUEST, true), LOGGER_DATA); logger('mod_photos: FILES ' . print_r($_FILES, true), LOGGER_DATA); $ph = photo_factory(''); $phototypes = $ph->supportedTypes(); $can_post = false; $page_owner_uid = \App::$data['channel']['channel_id']; if (perm_is_allowed($page_owner_uid, get_observer_hash(), 'write_storage')) { $can_post = true; } if (!$can_post) { notice(t('Permission denied.') . EOL); if (is_ajax()) { killme(); } return; } $s = abook_self($page_owner_uid); if (!$s) { notice(t('Page owner information could not be retrieved.') . EOL); logger('mod_photos: post: unable to locate contact record for page owner. uid=' . $page_owner_uid); if (is_ajax()) { killme(); } return; } $owner_record = $s[0]; $acl = new \Zotlabs\Access\AccessList(\App::$data['channel']); if (argc() > 3 && argv(2) === 'album') { $album = hex2bin(argv(3)); if ($album === t('Profile Photos')) { // not allowed goaway(z_root() . '/' . $_SESSION['photo_return']); } if (!photos_album_exists($page_owner_uid, $album)) { notice(t('Album not found.') . EOL); goaway(z_root() . '/' . $_SESSION['photo_return']); } /* * DELETE photo album and all its photos */ if ($_REQUEST['dropalbum'] == t('Delete Album')) { // This is dangerous because we combined file storage and photos into one interface // This function will remove all photos from any directory with the same name since // we have not passed the path value. // The correct solution would be to use a full pathname from your storage root for 'album' // We also need to prevent/block removing the storage root folder. $folder_hash = ''; $r = q("select * from attach where is_dir = 1 and uid = %d and filename = '%s'", intval($page_owner_uid), dbesc($album)); if (!$r) { notice(t('Album not found.') . EOL); return; } if (count($r) > 1) { notice(t('Multiple storage folders exist with this album name, but within different directories. Please remove the desired folder or folders using the Files manager') . EOL); return; } else { $folder_hash = $r[0]['hash']; } $res = array(); // get the list of photos we are about to delete if (remote_channel() && !local_channel()) { $str = photos_album_get_db_idstr($page_owner_uid, $album, remote_channel()); } elseif (local_channel()) { $str = photos_album_get_db_idstr(local_channel(), $album); } else { $str = null; } if (!$str) { goaway(z_root() . '/' . $_SESSION['photo_return']); } $r = q("select id from item where resource_id in ( {$str} ) and resource_type = 'photo' and uid = %d " . item_normal(), intval($page_owner_uid)); if ($r) { foreach ($r as $i) { attach_delete($page_owner_uid, $i['resource_id'], 1); } } // remove the associated photos in case they weren't attached to an item q("delete from photo where resource_id in ( {$str} ) and uid = %d", intval($page_owner_uid)); // @FIXME do the same for the linked attach if ($folder_hash) { attach_delete($page_owner_uid, $folder_hash, 1); $sync = attach_export_data(\App::$data['channel'], $folder_hash, true); if ($sync) { build_sync_packet($page_owner_uid, array('file' => array($sync))); } } } goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); } if (argc() > 2 && x($_REQUEST, 'delete') && $_REQUEST['delete'] === t('Delete Photo')) { // same as above but remove single photo $ob_hash = get_observer_hash(); if (!$ob_hash) { goaway(z_root() . '/' . $_SESSION['photo_return']); } $r = q("SELECT `id`, `resource_id` FROM `photo` WHERE ( xchan = '%s' or `uid` = %d ) AND `resource_id` = '%s' LIMIT 1", dbesc($ob_hash), intval(local_channel()), dbesc(\App::$argv[2])); if ($r) { attach_delete($page_owner_uid, $r[0]['resource_id'], 1); $sync = attach_export_data(\App::$data['channel'], $r[0]['resource_id'], true); if ($sync) { build_sync_packet($page_owner_uid, array('file' => array($sync))); } } goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $_SESSION['album_return']); } if (argc() > 2 && array_key_exists('move_to_album', $_POST)) { $m = q("select folder from attach where hash = '%s' and uid = %d limit 1", dbesc(argv(2)), intval($page_owner_uid)); if ($m && $m[0]['folder'] != $_POST['move_to_album']) { attach_move($page_owner_uid, argv(2), $_POST['move_to_album']); if (!($_POST['desc'] && $_POST['newtag'])) { goaway(z_root() . '/' . $_SESSION['photo_return']); } } } if (argc() > 2 && (x($_POST, 'desc') !== false || x($_POST, 'newtag') !== false)) { $desc = x($_POST, 'desc') ? notags(trim($_POST['desc'])) : ''; $rawtags = x($_POST, 'newtag') ? notags(trim($_POST['newtag'])) : ''; $item_id = x($_POST, 'item_id') ? intval($_POST['item_id']) : 0; $is_nsfw = x($_POST, 'adult') ? intval($_POST['adult']) : 0; $acl->set_from_array($_POST); $perm = $acl->get(); $resource_id = argv(2); if (x($_POST, 'rotate') !== false && (intval($_POST['rotate']) == 1 || intval($_POST['rotate']) == 2)) { logger('rotate'); $r = q("select * from photo where `resource_id` = '%s' and uid = %d and imgscale = 0 limit 1", dbesc($resource_id), intval($page_owner_uid)); if (count($r)) { $d = $r[0]['os_storage'] ? @file_get_contents($r[0]['content']) : dbunescbin($r[0]['content']); $ph = photo_factory($d, $r[0]['mimetype']); if ($ph->is_valid()) { $rotate_deg = intval($_POST['rotate']) == 1 ? 270 : 90; $ph->rotate($rotate_deg); $width = $ph->getWidth(); $height = $ph->getHeight(); if (intval($r[0]['os_storage'])) { @file_put_contents($r[0]['content'], $ph->imageString()); $data = $r[0]['content']; $fsize = @filesize($r[0]['content']); q("update attach set filesize = %d where hash = '%s' and uid = %d limit 1", intval($fsize), dbesc($resource_id), intval($page_owner_uid)); } else { $data = $ph->imageString(); $fsize = strlen($data); } $x = q("update photo set content = '%s', filesize = %d, height = %d, width = %d where `resource_id` = '%s' and uid = %d and imgscale = 0", dbescbin($data), intval($fsize), intval($height), intval($width), dbesc($resource_id), intval($page_owner_uid)); if ($width > 1024 || $height > 1024) { $ph->scaleImage(1024); } $width = $ph->getWidth(); $height = $ph->getHeight(); $x = q("update photo set content = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and imgscale = 1", dbescbin($ph->imageString()), intval($height), intval($width), dbesc($resource_id), intval($page_owner_uid)); if ($width > 640 || $height > 640) { $ph->scaleImage(640); } $width = $ph->getWidth(); $height = $ph->getHeight(); $x = q("update photo set content = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and imgscale = 2", dbescbin($ph->imageString()), intval($height), intval($width), dbesc($resource_id), intval($page_owner_uid)); if ($width > 320 || $height > 320) { $ph->scaleImage(320); } $width = $ph->getWidth(); $height = $ph->getHeight(); $x = q("update photo set content = '%s', height = %d, width = %d where `resource_id` = '%s' and uid = %d and imgscale = 3", dbescbin($ph->imageString()), intval($height), intval($width), dbesc($resource_id), intval($page_owner_uid)); } } } $p = q("SELECT mimetype, is_nsfw, description, resource_id, imgscale, allow_cid, allow_gid, deny_cid, deny_gid FROM photo WHERE resource_id = '%s' AND uid = %d ORDER BY imgscale DESC", dbesc($resource_id), intval($page_owner_uid)); if ($p) { $ext = $phototypes[$p[0]['mimetype']]; $r = q("UPDATE `photo` SET `description` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource_id` = '%s' AND `uid` = %d", dbesc($desc), dbesc($perm['allow_cid']), dbesc($perm['allow_gid']), dbesc($perm['deny_cid']), dbesc($perm['deny_gid']), dbesc($resource_id), intval($page_owner_uid)); } $item_private = $str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny ? true : false; $old_is_nsfw = $p[0]['is_nsfw']; if ($old_is_nsfw != $is_nsfw) { $r = q("update photo set is_nsfw = %d where resource_id = '%s' and uid = %d", intval($is_nsfw), dbesc($resource_id), intval($page_owner_uid)); } /* Don't make the item visible if the only change was the album name */ $visibility = 0; if ($p[0]['description'] !== $desc || strlen($rawtags)) { $visibility = 1; } if (!$item_id) { $item_id = photos_create_item(\App::$data['channel'], get_observer_hash(), $p[0], $visibility); } if ($item_id) { $r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item_id), intval($page_owner_uid)); if ($r) { $old_tag = $r[0]['tag']; $old_inform = $r[0]['inform']; } } // make sure the linked item has the same permissions as the photo regardless of any other changes $x = q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d\n\t\t\t\twhere id = %d", dbesc($perm['allow_cid']), dbesc($perm['allow_gid']), dbesc($perm['deny_cid']), dbesc($perm['deny_gid']), intval($acl->is_private()), intval($item_id)); // make sure the attach has the same permissions as the photo regardless of any other changes $x = q("update attach set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where hash = '%s' and uid = %d and is_photo = 1", dbesc($perm['allow_cid']), dbesc($perm['allow_gid']), dbesc($perm['deny_cid']), dbesc($perm['deny_gid']), dbesc($resource_id), intval($page_owner_uid)); if (strlen($rawtags)) { $str_tags = ''; $inform = ''; // if the new tag doesn't have a namespace specifier (@foo or #foo) give it a mention $x = substr($rawtags, 0, 1); if ($x !== '@' && $x !== '#') { $rawtags = '@' . $rawtags; } require_once 'include/text.php'; $profile_uid = \App::$profile['profile_uid']; $results = linkify_tags($a, $rawtags, local_channel() ? local_channel() : $profile_uid); $success = $results['success']; $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']); } } $r = q("select * from item where id = %d and uid = %d limit 1", intval($item_id), intval($page_owner_uid)); if ($r) { $r = fetch_post_tags($r, true); $datarray = $r[0]; if ($post_tags) { if (!array_key_exists('term', $datarray) || !is_array($datarray['term'])) { $datarray['term'] = $post_tags; } else { $datarray['term'] = array_merge($datarray['term'], $post_tags); } } item_store_update($datarray, $execflag); } } $sync = attach_export_data(\App::$data['channel'], $resource_id); if ($sync) { build_sync_packet($page_owner_uid, array('file' => array($sync))); } goaway(z_root() . '/' . $_SESSION['photo_return']); return; // NOTREACHED } /** * default post action - upload a photo */ $channel = \App::$data['channel']; $observer = \App::$data['observer']; $_REQUEST['source'] = 'photos'; require_once 'include/attach.php'; if (!local_channel()) { $_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']); $_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']); $_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']); $_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']); } $r = attach_store($channel, get_observer_hash(), '', $_REQUEST); if (!$r['success']) { notice($r['message'] . EOL); } if ($_REQUEST['newalbum']) { goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($_REQUEST['newalbum'])); } else { goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex(datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y'))); } }
/** * @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($channel['channel_r_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; }
function item_post(&$a) { // 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/identity.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']); // '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 item_id 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 = 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 xchan_query($r); $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 item_id where service = '%s' and sid = '%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); $public_policy = x($_REQUEST, 'public_policy') ? escape_tags($_REQUEST['public_policy']) : map_scope($channel['channel_r_stream'], 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, abook_their_perms from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc(str_replace(array('<', '>'), array('', ''), $str_contact_allow)), intval($profile_uid)); if ($x && $x[0]['abook_their_perms'] & PERMS_W_TAGWALL) { $body .= "\n\n@group+" . $x[0]['abook_id'] . "\n"; } } /** * fix naked links by passing through a callback to see if this is a red 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", '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, 'type' => $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, 'type' => 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 type 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, 'type' => $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; // 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['item_private'] = $private; $datarray['item_wall'] = $item_wall; $datarray['attach'] = $attachments; $datarray['thr_parent'] = $thr_parent; $datarray['postopts'] = $postopts; $datarray['item_unseen'] = $item_unseen; $datarray['item_wall'] = $item_wall; $datarray['item_origin'] = $item_origin; $datarray['item_type'] = $webpage; $datarray['item_thread_top'] = $item_thread_top; $datarray['item_unseen'] = $item_unseen; $datarray['item_starred'] = $item_starred; $datarray['item_uplink'] = $item_uplink; $datarray['item_consensus'] = $item_consensus; $datarray['item_notshown'] = $item_notshown; $datarray['item_nsfw'] = $item_nsfw; $datarray['item_relay'] = $item_relay; $datarray['item_mentionsme'] = $item_mentionsme; $datarray['item_nocomment'] = $item_nocomment; $datarray['item_obscured'] = $item_obscured; $datarray['item_verified'] = $item_verified; $datarray['item_retained'] = $item_retained; $datarray['item_rss'] = $item_rss; $datarray['item_deleted'] = $item_deleted; $datarray['item_hidden'] = $item_hidden; $datarray['item_unpublished'] = $item_unpublished; $datarray['item_delayed'] = $item_delayed; $datarray['item_pending_remove'] = $item_pending_remove; $datarray['item_blocked'] = $item_blocked; $datarray['layout_mid'] = $layout_mid; $datarray['public_policy'] = $public_policy; $datarray['comment_policy'] = map_scope($channel['channel_w_comment']); $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; } if (feature_enabled($profile_uid, 'suppress_duplicates') && !$orig_post) { $z = q("select created from item where uid = %d and body = '%s'", intval($profile_uid), dbesc($body)); if ($z) { foreach ($z as $zz) { if ($zz['created'] > datetime_convert('UTC', 'UTC', 'now - 2 minutes')) { $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 ($orig_post) { $datarray['id'] = $post_id; item_store_update($datarray, $execflag); update_remote_id($channel, $post_id, $webpage, $pagetitle, $namespace, $remote_id, $mid); if (!$parent) { $r = q("select * from item where id = %d", intval($post_id)); if ($r) { xchan_query($r); $sync_item = fetch_post_tags($r); $rid = q("select * from item_id where iid = %d", intval($post_id)); build_sync_packet($uid, array('item' => array(encode_item($sync_item[0], true)), 'item_id' => $rid)); } } if (!$nopush) { proc_run('php', "include/notifier.php", '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']; 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'])) { notification(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) { notification(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 } update_remote_id($channel, $post_id, $webpage, $pagetitle, $namespace, $remote_id, $mid); 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); $rid = q("select * from item_id where iid = %d", intval($post_id)); build_sync_packet($uid, array('item' => array(encode_item($sync_item[0], true)), 'item_id' => $rid)); } } $datarray['id'] = $post_id; $datarray['llink'] = z_root() . '/display/' . $channel['channel_address'] . '/' . $post_id; call_hooks('post_local_end', $datarray); if (!$nopush) { proc_run('php', 'include/notifier.php', $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 }
function post() { require_once 'include/wiki.php'; // /wiki/channel/preview // Render mardown-formatted text in HTML for preview if (argc() > 2 && argv(2) === 'preview') { $content = $_POST['content']; $resource_id = $_POST['resource_id']; require_once 'library/markdown.php'; $html = wiki_generate_toc(purify_html(Markdown($content))); $w = wiki_get_wiki($resource_id); $wikiURL = argv(0) . '/' . argv(1) . '/' . $w['urlName']; $html = wiki_convert_links($html, $wikiURL); json_return_and_die(array('html' => $html, 'success' => true)); } // Create a new wiki // /wiki/channel/create/wiki if (argc() > 3 && argv(2) === 'create' && argv(3) === 'wiki') { $nick = argv(1); $channel = get_channel_by_nick($nick); // Determine if observer has permission to create wiki $observer_hash = get_observer_hash(); // Only the channel owner can create a wiki, at least until we create a // more detail permissions framework if (local_channel() !== intval($channel['channel_id'])) { goaway('/' . argv(0) . '/' . $nick . '/'); } $wiki = array(); // Generate new wiki info from input name $wiki['postVisible'] = intval($_POST['postVisible']) === 0 ? 0 : 1; $wiki['rawName'] = $_POST['wikiName']; $wiki['htmlName'] = escape_tags($_POST['wikiName']); $wiki['urlName'] = urlencode($_POST['wikiName']); if ($wiki['urlName'] === '') { notice('Error creating wiki. Invalid name.'); goaway('/wiki'); } // Get ACL for permissions $acl = new \Zotlabs\Access\AccessList($channel); $acl->set_from_array($_POST); $r = wiki_create_wiki($channel, $observer_hash, $wiki, $acl); if ($r['success']) { $homePage = wiki_create_page('Home', $r['item']['resource_id']); if (!$homePage['success']) { notice('Wiki created, but error creating Home page.'); goaway('/wiki/' . $nick . '/' . $wiki['urlName']); } goaway('/wiki/' . $nick . '/' . $wiki['urlName'] . '/' . $homePage['page']['urlName']); } else { notice('Error creating wiki'); goaway('/wiki'); } } // Delete a wiki if (argc() > 3 && argv(2) === 'delete' && argv(3) === 'wiki') { $nick = argv(1); $channel = get_channel_by_nick($nick); // Only the channel owner can delete a wiki, at least until we create a // more detail permissions framework if (local_channel() !== intval($channel['channel_id'])) { logger('Wiki delete permission denied.' . EOL); json_return_and_die(array('message' => 'Wiki delete permission denied.', 'success' => false)); } $resource_id = $_POST['resource_id']; $deleted = wiki_delete_wiki($resource_id); if ($deleted['success']) { json_return_and_die(array('message' => '', 'success' => true)); } else { logger('Error deleting wiki: ' . $resource_id); json_return_and_die(array('message' => 'Error deleting wiki', 'success' => false)); } } // Create a page if (argc() === 4 && argv(2) === 'create' && argv(3) === 'page') { $nick = argv(1); $resource_id = $_POST['resource_id']; // Determine if observer has permission to create a page $channel = get_channel_by_nick($nick); if (local_channel() !== intval($channel['channel_id'])) { $observer_hash = get_observer_hash(); $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash); if (!$perms['write']) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); } } $name = $_POST['name']; //Get new page name if (urlencode(escape_tags($_POST['name'])) === '') { json_return_and_die(array('message' => 'Error creating page. Invalid name.', 'success' => false)); } $page = wiki_create_page($name, $resource_id); if ($page['success']) { json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . $page['wiki']['urlName'] . '/' . urlencode($page['page']['urlName']), 'success' => true)); } else { logger('Error creating page'); json_return_and_die(array('message' => 'Error creating page.', 'success' => false)); } } // Fetch page list for a wiki if (argc() === 5 && argv(2) === 'get' && argv(3) === 'page' && argv(4) === 'list') { $resource_id = $_POST['resource_id']; // resource_id for wiki in db $channel = get_channel_by_nick(argv(1)); $observer_hash = get_observer_hash(); if (local_channel() !== intval($channel['channel_id'])) { $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash); if (!$perms['read']) { logger('Wiki read permission denied.' . EOL); json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false)); } } $page_list_html = widget_wiki_pages(array('resource_id' => $resource_id, 'refresh' => true, 'channel' => argv(1))); json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true)); } // Save a page if (argc() === 4 && argv(2) === 'save' && argv(3) === 'page') { $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; $pageHtmlName = escape_tags($_POST['name']); $content = $_POST['content']; //Get new content $commitMsg = $_POST['commitMsg']; if ($commitMsg === '') { $commitMsg = 'Updated ' . $pageHtmlName; } $nick = argv(1); $channel = get_channel_by_nick($nick); // Determine if observer has permission to save content if (local_channel() !== intval($channel['channel_id'])) { $observer_hash = get_observer_hash(); $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash); if (!$perms['write']) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); } } $saved = wiki_save_page(array('resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'content' => $content)); if ($saved['success']) { $ob = \App::get_observer(); $commit = wiki_git_commit(array('commit_msg' => $commitMsg, 'resource_id' => $resource_id, 'observer' => $ob, 'files' => array($pageUrlName . '.md'))); if ($commit['success']) { json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true)); } else { json_return_and_die(array('message' => 'Error making git commit', 'success' => false)); } } else { json_return_and_die(array('message' => 'Error saving page', 'success' => false)); } } // Update page history // /wiki/channel/history/page if (argc() === 4 && argv(2) === 'history' && argv(3) === 'page') { $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; $nick = argv(1); $channel = get_channel_by_nick($nick); // Determine if observer has permission to read content if (local_channel() !== intval($channel['channel_id'])) { $observer_hash = get_observer_hash(); $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash); if (!$perms['read']) { logger('Wiki read permission denied.' . EOL); json_return_and_die(array('historyHTML' => '', 'message' => 'Permission denied.', 'success' => false)); } } $historyHTML = widget_wiki_page_history(array('resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); json_return_and_die(array('historyHTML' => $historyHTML, 'message' => '', 'success' => true)); } // Delete a page if (argc() === 4 && argv(2) === 'delete' && argv(3) === 'page') { $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; if ($pageUrlName === 'Home') { json_return_and_die(array('message' => 'Cannot delete Home', 'success' => false)); } // Determine if observer has permission to delete pages $nick = argv(1); $channel = get_channel_by_nick($nick); if (local_channel() !== intval($channel['channel_id'])) { $observer_hash = get_observer_hash(); $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash); if (!$perms['write']) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); } } $deleted = wiki_delete_page(array('resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); if ($deleted['success']) { $ob = \App::get_observer(); $commit = wiki_git_commit(array('commit_msg' => 'Deleted ' . $pageUrlName, 'resource_id' => $resource_id, 'observer' => $ob, 'files' => null)); if ($commit['success']) { json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true)); } else { json_return_and_die(array('message' => 'Error making git commit', 'success' => false)); } } else { json_return_and_die(array('message' => 'Error deleting page', 'success' => false)); } } // Revert a page if (argc() === 4 && argv(2) === 'revert' && argv(3) === 'page') { $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; $commitHash = $_POST['commitHash']; // Determine if observer has permission to revert pages $nick = argv(1); $channel = get_channel_by_nick($nick); if (local_channel() !== intval($channel['channel_id'])) { $observer_hash = get_observer_hash(); $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash); if (!$perms['write']) { logger('Wiki write permission denied.' . EOL); json_return_and_die(array('success' => false)); } } $reverted = wiki_revert_page(array('commitHash' => $commitHash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); if ($reverted['success']) { json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true)); } else { json_return_and_die(array('content' => '', 'message' => 'Error reverting page', 'success' => false)); } } // Compare page revisions if (argc() === 4 && argv(2) === 'compare' && argv(3) === 'page') { $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; $compareCommit = $_POST['compareCommit']; $currentCommit = $_POST['currentCommit']; // Determine if observer has permission to revert pages $nick = argv(1); $channel = get_channel_by_nick($nick); if (local_channel() !== intval($channel['channel_id'])) { $observer_hash = get_observer_hash(); $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash); if (!$perms['read']) { logger('Wiki read permission denied.' . EOL); json_return_and_die(array('success' => false)); } } $compare = wiki_compare_page(array('currentCommit' => $currentCommit, 'compareCommit' => $compareCommit, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); if ($compare['success']) { $diffHTML = '<table class="text-center" width="100%"><tr><td class="lead" width="50%">Current Revision</td><td class="lead" width="50%">Selected Revision</td></tr></table>' . $compare['diff']; json_return_and_die(array('diff' => $diffHTML, 'message' => '', 'success' => true)); } else { json_return_and_die(array('diff' => '', 'message' => 'Error comparing page', 'success' => false)); } } // Rename a page if (argc() === 4 && argv(2) === 'rename' && argv(3) === 'page') { $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['oldName']; $pageNewName = $_POST['newName']; if ($pageUrlName === 'Home') { json_return_and_die(array('message' => 'Cannot rename Home', 'success' => false)); } if (urlencode(escape_tags($pageNewName)) === '') { json_return_and_die(array('message' => 'Error renaming page. Invalid name.', 'success' => false)); } // Determine if observer has permission to rename pages $nick = argv(1); $channel = get_channel_by_nick($nick); if (local_channel() !== intval($channel['channel_id'])) { $observer_hash = get_observer_hash(); $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash); if (!$perms['write']) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); } } $renamed = wiki_rename_page(array('resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'pageNewName' => $pageNewName)); if ($renamed['success']) { $ob = \App::get_observer(); $commit = wiki_git_commit(array('commit_msg' => 'Renamed ' . urldecode($pageUrlName) . ' to ' . $renamed['page']['htmlName'], 'resource_id' => $resource_id, 'observer' => $ob, 'files' => array($pageUrlName . '.md', $renamed['page']['fileName']), 'all' => true)); if ($commit['success']) { json_return_and_die(array('name' => $renamed['page'], 'message' => 'Wiki git repo commit made', 'success' => true)); } else { json_return_and_die(array('message' => 'Error making git commit', 'success' => false)); } } else { json_return_and_die(array('message' => 'Error renaming page', 'success' => false)); } } //notice('You must be authenticated.'); json_return_and_die(array('message' => 'You must be authenticated.', 'success' => false)); }