function chat_post(&$a) { if ($_POST['room_name']) { $room = strip_tags(trim($_POST['room_name'])); } if (!$room || !local_channel()) { return; } $channel = $a->get_channel(); if ($_POST['action'] === 'drop') { logger('delete chatroom'); chatroom_destroy($channel, array('cr_name' => $room)); goaway(z_root() . '/chat/' . $channel['channel_address']); } $acl = new 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; } 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'); }
function init() { $starred = 0; if (!local_channel()) { killme(); } if (argc() > 1) { $message_id = intval(argv(1)); } if (!$message_id) { killme(); } $r = q("SELECT item_flags FROM item WHERE uid = %d AND id = %d LIMIT 1", intval(local_channel()), intval($message_id)); if (!count($r)) { killme(); } $item_starred = intval($r[0]['item_starred']) ? 0 : 1; $r = q("UPDATE item SET item_starred = %d WHERE uid = %d and id = %d", intval($item_starred), intval(local_channel()), intval($message_id)); $r = q("select * from item where id = %d", intval($message_id)); if ($r) { xchan_query($r); $sync_item = fetch_post_tags($r); build_sync_packet(local_channel(), ['item' => [encode_item($sync_item[0], true)]]); } header('Content-type: application/json'); echo json_encode(array('result' => $item_starred)); killme(); }
/** @file */ function notes_init(&$a) { if (!local_channel()) { return; } $ret = array('success' => true); if (array_key_exists('note_text', $_REQUEST)) { $body = escape_tags($_REQUEST['note_text']); // I've had my notes vanish into thin air twice in four years. // Provide a backup copy if there were contents previously // and there are none being saved now. if (!$body) { $old_text = get_pconfig(local_channel(), 'notes', 'text'); if ($old_text) { set_pconfig(local_channel(), 'notes', 'text.bak', $old_text); } } set_pconfig(local_channel(), 'notes', 'text', $body); } // push updates to channel clones if (argc() > 1 && argv(1) === 'sync') { require_once 'include/zot.php'; build_sync_packet(); } logger('notes saved.', LOGGER_DEBUG); json_return_and_die($ret); }
function post() { check_form_security_token_redirectOnErr('/settings/featured', 'settings_featured'); call_hooks('feature_settings_post', $_POST); build_sync_packet(); return; }
function chatroom_destroy($channel, $arr) { $ret = array('success' => false); if (intval($arr['cr_id'])) { $sql_extra = " and cr_id = " . intval($arr['cr_id']) . " "; } elseif (trim($arr['cr_name'])) { $sql_extra = " and cr_name = '" . protect_sprintf(dbesc(trim($arr['cr_name']))) . "' "; } else { $ret['message'] = t('Invalid room specifier.'); return $ret; } $r = q("select * from chatroom where cr_uid = %d {$sql_extra} limit 1", intval($channel['channel_id'])); if (!$r) { $ret['message'] = t('Invalid room specifier.'); return $ret; } build_sync_packet($channel['channel_id'], array('chatroom' => $r)); q("delete from chatroom where cr_id = %d", intval($r[0]['cr_id'])); if ($r[0]['cr_id']) { q("delete from chatpresence where cp_room = %d", intval($r[0]['cr_id'])); q("delete from chat where chat_room = %d", intval($r[0]['cr_id'])); } $ret['success'] = true; return $ret; }
function follow_init(&$a) { if (!local_channel()) { return; } $uid = local_channel(); $url = notags(trim($_REQUEST['url'])); $return_url = $_SESSION['return_url']; $confirm = intval($_REQUEST['confirm']); $result = new_contact($uid, $url, $a->get_channel(), true, $confirm); if ($result['success'] == false) { if ($result['message']) { notice($result['message']); } goaway($return_url); } info(t('Channel added.') . EOL); $clone = array(); foreach ($result['abook'] as $k => $v) { if (strpos($k, 'abook_') === 0) { $clone[$k] = $v; } } unset($clone['abook_id']); unset($clone['abook_account']); unset($clone['abook_channel']); build_sync_packet(0, array('abook' => array($clone))); // If we can view their stream, pull in some posts if ($result['abook']['abook_their_perms'] & PERMS_R_STREAM || $result['abook']['xchan_network'] === 'rss') { proc_run('php', 'include/onepoll.php', $result['abook']['abook_id']); } goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?f=&follow=1'); }
function superblock_addon_settings_post(&$a, &$b) { if (!local_channel()) { return; } if ($_POST['superblock-submit']) { set_pconfig(local_channel(), 'system', 'blocked', trim($_POST['superblock-words'])); info(t('SUPERBLOCK Settings saved.') . EOL); } build_sync_packet(); }
function pdledit_post(&$a) { if (!local_channel()) { return; } if (!$_REQUEST['module']) { return; } if (!trim($_REQUEST['content'])) { del_pconfig(local_channel(), 'system', 'mod_' . $_REQUEST['module'] . '.pdl'); goaway(z_root() . '/pdledit/' . $_REQUEST['module']); } set_pconfig(local_channel(), 'system', 'mod_' . $_REQUEST['module'] . '.pdl', escape_tags($_REQUEST['content'])); build_sync_packet(); info(t('Layout updated.') . EOL); goaway(z_root() . '/pdledit/' . $_REQUEST['module']); }
/** @file */ function notes_init(&$a) { if (!local_user()) { return; } $ret = array('success' => true); if ($_REQUEST['note_text'] || $_REQUEST['note_text'] == '') { $body = escape_tags($_REQUEST['note_text']); set_pconfig(local_user(), 'notes', 'text', $body); } // push updates to channel clones if (argc() > 1 && argv(1) === 'sync') { require_once 'include/zot.php'; build_sync_packet(); } logger('notes saved.', LOGGER_DEBUG); json_return_and_die($ret); }
function init() { if (!local_channel()) { return; } $uid = local_channel(); $url = notags(trim($_REQUEST['url'])); $return_url = $_SESSION['return_url']; $confirm = intval($_REQUEST['confirm']); $channel = \App::get_channel(); // Warning: Do not edit the following line. The first symbol is UTF-8 @ $url = str_replace('@', '@', $url); $result = new_contact($uid, $url, $channel, true, $confirm); if ($result['success'] == false) { if ($result['message']) { notice($result['message']); } goaway($return_url); } info(t('Channel added.') . EOL); $clone = array(); foreach ($result['abook'] as $k => $v) { if (strpos($k, 'abook_') === 0) { $clone[$k] = $v; } } unset($clone['abook_id']); unset($clone['abook_account']); unset($clone['abook_channel']); $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']); if ($abconfig) { $clone['abconfig'] = $abconfig; } build_sync_packet(0, array('abook' => array($clone)), true); $can_view_stream = intval(get_abconfig($channel['channel_id'], $clone['abook_xchan'], 'their_perms', 'view_stream')); // If we can view their stream, pull in some posts if ($can_view_stream || $result['abook']['xchan_network'] === 'rss') { \Zotlabs\Daemon\Master::Summon(array('Onepoll', $result['abook']['abook_id'])); } goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?f=&follow=1'); }
function post() { check_form_security_token_redirectOnErr('/settings/features', 'settings_features'); // Build list of features and check which are set // We will not create any settings for features that are above our techlevel $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; }
function post() { if (!local_channel()) { return; } if ($_SESSION['delegate']) { return; } check_form_security_token_redirectOnErr('/pconfig', 'pconfig'); $cat = trim(escape_tags($_POST['cat'])); $k = trim(escape_tags($_POST['k'])); $v = trim($_POST['v']); if (in_array(argv(2), $this->disallowed_pconfig())) { notice(t('This setting requires special processing and editing has been blocked.') . EOL); return; } if (strpos($k, 'password') !== false) { $v = z_obscure($v); } set_pconfig(local_channel(), $cat, $k, $v); build_sync_packet(); goaway(z_root() . '/pconfig/' . $cat . '/' . $k); }
function thing_content(&$a) { // @FIXME one problem with things is we can't share them unless we provide the channel in the url // so we can definitively lookup the owner. if (argc() == 2) { $r = q("select obj_channel from obj where obj_type = %d and obj_obj = '%s' limit 1", intval(TERM_OBJ_THING), dbesc(argv(1))); if ($r) { $sql_extra = permissions_sql($r[0]['obj_channel']); } $r = q("select * from obj where obj_type = %d and obj_obj = '%s' {$sql_extra} limit 1", intval(TERM_OBJ_THING), dbesc(argv(1))); if ($r) { return replace_macros(get_markup_template('show_thing.tpl'), array('$header' => t('Show Thing'), '$edit' => t('Edit'), '$delete' => t('Delete'), '$canedit' => local_channel() && local_channel() == $r[0]['obj_channel'] ? true : false, '$thing' => $r[0])); } else { notice(t('item not found.') . EOL); return; } } $channel = App::get_channel(); if (!(local_channel() && $channel)) { notice(t('Permission denied.') . EOL); return; } $acl = new Zotlabs\Access\AccessList($channel); $channel_acl = $acl->get(); $lockstate = $acl->is_private() ? 'lock' : 'unlock'; $thing_hash = ''; if (argc() == 3 && argv(1) === 'edit') { $thing_hash = argv(2); $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1", intval(TERM_OBJ_THING), dbesc($thing_hash)); if (!$r || $r[0]['obj_channel'] != local_channel()) { notice(t('Permission denied.') . EOL); return ''; } $o .= replace_macros(get_markup_template('thing_edit.tpl'), array('$thing_hdr' => t('Edit Thing'), '$multiprof' => feature_enabled(local_channel(), 'multi_profiles'), '$profile_lbl' => t('Select a profile'), '$profile_select' => contact_profile_assign($r[0]['obj_page']), '$verb_lbl' => $channel['channel_name'], '$verb_select' => obj_verb_selector($r[0]['obj_verb']), '$activity' => array('activity', t('Post an activity'), true, t('Only sends to viewers of the applicable profile')), '$thing_hash' => $thing_hash, '$thing_lbl' => t('Name of thing e.g. something'), '$thething' => $r[0]['obj_term'], '$url_lbl' => t('URL of thing (optional)'), '$theurl' => $r[0]['obj_url'], '$img_lbl' => t('URL for photo of thing (optional)'), '$imgurl' => $r[0]['obj_imgurl'], '$permissions' => t('Permissions'), '$aclselect' => populate_acl($channel_acl, false), '$lockstate' => $lockstate, '$submit' => t('Submit'))); return $o; } if (argc() == 3 && argv(1) === 'drop') { $thing_hash = argv(2); $r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1", intval(TERM_OBJ_THING), dbesc($thing_hash)); if (!$r || $r[0]['obj_channel'] != local_channel()) { notice(t('Permission denied.') . EOL); return ''; } $x = q("delete from obj where obj_obj = '%s' and obj_type = %d and obj_channel = %d", dbesc($thing_hash), intval(TERM_OBJ_THING), intval(local_channel())); $r[0]['obj_deleted'] = 1; build_sync_packet(0, array('obj' => $r)); return $o; } $o .= replace_macros(get_markup_template('thing_input.tpl'), array('$thing_hdr' => t('Add Thing to your Profile'), '$multiprof' => feature_enabled(local_channel(), 'multi_profiles'), '$profile_lbl' => t('Select a profile'), '$profile_select' => contact_profile_assign(''), '$verb_lbl' => $channel['channel_name'], '$activity' => array('activity', t('Post an activity'), array_key_exists('activity', $_REQUEST) ? $_REQUEST['activity'] : true, t('Only sends to viewers of the applicable profile')), '$verb_select' => obj_verb_selector(), '$thing_lbl' => t('Name of thing e.g. something'), '$url_lbl' => t('URL of thing (optional)'), '$img_lbl' => t('URL for photo of thing (optional)'), '$permissions' => t('Permissions'), '$aclselect' => populate_acl($channel_acl, false), '$lockstate' => $lockstate, '$submit' => t('Submit'))); return $o; }
function connections_clone(&$a) { if (!array_key_exists('abook', $a->data)) { return; } $clone = $a->data['abook']; unset($clone['abook_id']); unset($clone['abook_account']); unset($clone['abook_channel']); build_sync_packet(0, array('abook' => array($clone))); }
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 private_messages_drop($channel_id, $messageitem_id, $drop_conversation = false) { $x = q("select * from mail where id = %d and channel_id = %d limit 1", intval($messageitem_id), intval($channel_id)); if (!$x) { return false; } $conversation = null; if ($x[0]['conv_guid']) { $y = q("select * from conv where guid = '%s' and uid = %d limit 1", dbesc($x[0]['conv_guid']), intval($channel_id)); if ($y) { $conversation = $y[0]; $conversation['subject'] = base64url_decode(str_rot47($conversation['subject'])); } } if ($drop_conversation) { $m = array(); $m['conv'] = array($conversation); $m['conv'][0]['deleted'] = 1; $z = q("select * from mail where parent_mid = '%s' and channel_id = %d", dbesc($x[0]['parent_mid']), intval($channel_id)); if ($z) { q("delete from conv where guid = '%s' and uid = %d limit 1", dbesc($x[0]['conv_guid']), intval($channel_id)); $m['mail'] = array(); foreach ($z as $zz) { xchan_mail_query($zz); $zz['mail_deleted'] = 1; $m['mail'][] = encode_mail($zz, true); } q("DELETE FROM mail WHERE parent_mid = '%s' AND channel_id = %d ", dbesc($x[0]['parent_mid']), intval($channel_id)); } build_sync_packet($channel_id, $m); return true; } else { xchan_mail_query($x[0]); $x[0]['mail_deleted'] = true; $r = q("DELETE FROM mail WHERE id = %d AND channel_id = %d", intval($messageitem_id), intval($channel_id)); build_sync_packet($channel_id, array('mail' => array(encode_mail($x, true)))); return true; } return false; }
function group_add_member($uid, $name, $member, $gid = 0) { if (!$gid) { $gid = group_byname($uid, $name); } if (!$gid || !$uid || !$member) { return false; } $r = q("SELECT * FROM `group_member` WHERE `uid` = %d AND `gid` = %d AND `xchan` = '%s' LIMIT 1", intval($uid), intval($gid), dbesc($member)); if (count($r)) { return true; } // You might question this, but // we indicate success because the group member was in fact created // -- It was just created at another time if (!count($r)) { $r = q("INSERT INTO `group_member` (`uid`, `gid`, `xchan`)\n\t\t\tVALUES( %d, %d, '%s' ) ", intval($uid), intval($gid), dbesc($member)); } build_sync_packet($uid, null, true); return $r; }
function event_addtocal($item_id, $uid) { $c = q("select * from channel where channel_id = %d limit 1", intval($uid)); if (!$c) { return false; } $channel = $c[0]; $r = q("select * from item where id = %d and uid = %d limit 1", intval($item_id), intval($channel['channel_id'])); if (!$r || $r[0]['obj_type'] !== ACTIVITY_OBJ_EVENT) { return false; } $item = $r[0]; $ev = bbtoevent($r[0]['body']); if (x($ev, 'summary') && x($ev, 'start')) { $ev['event_xchan'] = $item['author_xchan']; $ev['uid'] = $channel['channel_id']; $ev['account'] = $channel['channel_account_id']; $ev['edited'] = $item['edited']; $ev['mid'] = $item['mid']; $ev['private'] = $item['item_private']; // is this an edit? if ($item['resource_type'] === 'event') { $ev['event_hash'] = $item['resource_id']; } $event = event_store_event($ev); if ($event) { $r = q("update item set resource_id = '%s', resource_type = 'event' where id = %d and uid = %d", dbesc($event['event_hash']), intval($item['id']), intval($channel['channel_id'])); $item['resource_id'] = $event['event_hash']; $item['resource_type'] = 'event'; $i = array($item); xchan_query($i); $sync_item = fetch_post_tags($i); $z = q("select * from event where event_hash = '%s' and uid = %d limit 1", dbesc($event['event_hash']), intval($channel['channel_id'])); if ($z) { build_sync_packet($channel['channel_id'], array('event_item' => array(encode_item($sync_item[0], true)), 'event' => $z)); } return true; } } return false; }
/** * A lot going on in this function, and some of it is old cruft and some is new cruft * and the entire thing probably needs to be refactored. It started out just storing * files, before we had DAV. It was made extensible to do extra stuff like edit an * existing file or optionally store a separate revision using $options to choose between different * storage models. Along the way we moved from * DB data storage to file system storage. * Then DAV came along and used different upload methods depending on whether the * file was stored as a DAV directory object or updated as a file object. One of these * is essentially an update and the other is basically an upload, but doesn't use the traditional PHP * upload workflow. * Then came hubzilla and we tried to merge photo functionality with the file storage. Most of * that integration occurs within this function. * This required overlap with the old photo_upload stuff and photo albums were * completely different concepts from directories which needed to be reconciled somehow. * The old revision stuff is kind of orphaned currently. There's new revision stuff for photos * which attaches (2) etc. onto the name, but doesn't integrate with the attach table revisioning. * That's where it sits currently. I repeat it needs to be refactored, and this note is here * for future explorers and those who may be doing that work to understand where it came * from and got to be the monstrosity of tangled unrelated code that it currently is. */ function attach_store($channel, $observer_hash, $options = '', $arr = null) { require_once 'include/photos.php'; call_hooks('photo_upload_begin', $arr); $ret = array('success' => false); $channel_id = $channel['channel_id']; $sql_options = ''; $source = $arr ? $arr['source'] : ''; $album = $arr ? $arr['album'] : ''; $newalbum = $arr ? $arr['newalbum'] : ''; $hash = $arr && $arr['hash'] ? $arr['hash'] : null; $upload_path = $arr && $arr['directory'] ? $arr['directory'] : ''; $visible = $arr && $arr['visible'] ? $arr['visible'] : ''; $observer = array(); $dosync = array_key_exists('nosync', $arr) && $arr['nosync'] ? 0 : 1; if ($observer_hash) { $x = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($observer_hash)); if ($x) { $observer = $x[0]; } } logger('arr: ' . print_r($arr, true), LOGGER_DATA); if (!perm_is_allowed($channel_id, $observer_hash, 'write_storage')) { $ret['message'] = t('Permission denied.'); return $ret; } $str_group_allow = perms2str($arr['group_allow']); $str_contact_allow = perms2str($arr['contact_allow']); $str_group_deny = perms2str($arr['group_deny']); $str_contact_deny = perms2str($arr['contact_deny']); // The 'update' option sets db values without uploading a new attachment // 'replace' replaces the existing uploaded data // 'revision' creates a new revision with new upload data // Default is to upload a new file // revise or update must provide $arr['hash'] of the thing to revise/update // By default remove $src when finished $remove_when_processed = true; if ($options === 'import') { $src = $arr['src']; $filename = $arr['filename']; $filesize = @filesize($src); $hash = $arr['resource_id']; if (array_key_exists('hash', $arr)) { $hash = $arr['hash']; } if (array_key_exists('type', $arr)) { $type = $arr['type']; } if ($arr['preserve_original']) { $remove_when_processed = false; } // if importing a directory, just do it now and go home - we're done. if (array_key_exists('is_dir', $arr) && intval($arr['is_dir'])) { $x = attach_mkdir($channel, $observer_hash, $arr); if ($x['message']) { logger('import_directory: ' . $x['message']); } return; } } elseif ($options !== 'update') { $f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => ''); call_hooks('photo_upload_file', $f); call_hooks('attach_upload_file', $f); if (x($f, 'src') && x($f, 'filesize')) { $src = $f['src']; $filename = $f['filename']; $filesize = $f['filesize']; $type = $f['type']; } else { if (!x($_FILES, 'userfile')) { $ret['message'] = t('No source file.'); return $ret; } $src = $_FILES['userfile']['tmp_name']; $filename = basename($_FILES['userfile']['name']); $filesize = intval($_FILES['userfile']['size']); } } // AndStatus sends jpegs with a non-standard mimetype if ($type === 'image/jpg') { $type = 'image/jpeg'; } $existing_size = 0; if ($options === 'replace') { $x = q("select id, hash, filesize from attach where id = %d and uid = %d limit 1", intval($arr['id']), intval($channel_id)); if (!$x) { $ret['message'] = t('Cannot locate file to replace'); return $ret; } $existing_id = $x[0]['id']; $existing_size = intval($x[0]['filesize']); $hash = $x[0]['hash']; } if ($options === 'revise' || $options === 'update') { $sql_options = " order by revision desc "; if ($options === 'update' && $arr && array_key_exists('revision', $arr)) { $sql_options = " and revision = " . intval($arr['revision']) . " "; } $x = q("select id, aid, uid, filename, filetype, filesize, hash, revision, folder, os_storage, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where hash = '%s' and uid = %d {$sql_options} limit 1", dbesc($arr['hash']), intval($channel_id)); if (!$x) { $ret['message'] = t('Cannot locate file to revise/update'); return $ret; } $hash = $x[0]['hash']; } $def_extension = ''; $is_photo = 0; $gis = @getimagesize($src); logger('getimagesize: ' . print_r($gis, true), LOGGER_DATA); if ($gis && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) { $is_photo = 1; if ($gis[2] === IMAGETYPE_GIF) { $def_extension = '.gif'; } if ($gis[2] === IMAGETYPE_JPEG) { $def_extension = '.jpg'; } if ($gis[2] === IMAGETYPE_PNG) { $def_extension = '.png'; } } $pathname = ''; if ($is_photo) { if ($newalbum) { $pathname = filepath_macro($newalbum); } elseif (array_key_exists('folder', $arr)) { $x = q("select filename from attach where hash = '%s' and uid = %d limit 1", dbesc($arr['folder']), intval($channel['channel_id'])); if ($x) { $pathname = $x[0]['filename']; } } else { $pathname = filepath_macro($album); } } if (!$pathname) { $pathname = filepath_macro($upload_path); } $darr = array('pathname' => $pathname); // if we need to create a directory, use the channel default permissions. $darr['allow_cid'] = $channel['allow_cid']; $darr['allow_gid'] = $channel['allow_gid']; $darr['deny_cid'] = $channel['deny_cid']; $darr['deny_gid'] = $channel['deny_gid']; $direct = null; if ($pathname) { $x = attach_mkdirp($channel, $observer_hash, $darr); $folder_hash = $x['success'] ? $x['data']['hash'] : ''; $direct = $x['success'] ? $x['data'] : null; if (!$str_contact_allow && !$str_group_allow && !$str_contact_deny && !$str_group_deny) { $str_contact_allow = $x['data']['allow_cid']; $str_group_allow = $x['data']['allow_gid']; $str_contact_deny = $x['data']['deny_cid']; $str_group_deny = $x['data']['deny_gid']; } } else { $folder_hash = $arr && array_key_exists('folder', $arr) ? $arr['folder'] : ''; } if (!$options || $options === 'import') { // A freshly uploaded file. Check for duplicate and resolve with the channel's overwrite settings. $r = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ", dbesc($filename), dbesc($folder_hash)); if ($r) { $overwrite = get_pconfig($channel_id, 'system', 'overwrite_dup_files'); if ($overwrite || $options === 'import') { $options = 'replace'; $existing_id = $x[0]['id']; $existing_size = intval($x[0]['filesize']); $hash = $x[0]['hash']; } else { if (strpos($filename, '.') !== false) { $basename = substr($filename, 0, strrpos($filename, '.')); $ext = substr($filename, strrpos($filename, '.')); } else { $basename = $filename; $ext = $def_extension; } $r = q("select filename from attach where ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", dbesc($basename . $ext), dbesc($basename . '(%)' . $ext), dbesc($folder_hash)); if ($r) { $x = 1; do { $found = false; foreach ($r as $rr) { if ($rr['filename'] === $basename . '(' . $x . ')' . $ext) { $found = true; break; } } if ($found) { $x++; } } while ($found); $filename = $basename . '(' . $x . ')' . $ext; } else { $filename = $basename . $ext; } } } } if (!$hash) { $hash = random_string(); } // Check storage limits if ($options !== 'update') { $maxfilesize = get_config('system', 'maxfilesize'); if ($maxfilesize && $filesize > $maxfilesize) { $ret['message'] = sprintf(t('File exceeds size limit of %d'), $maxfilesize); if ($remove_when_processed) { @unlink($src); } call_hooks('photo_upload_end', $ret); return $ret; } $limit = service_class_fetch($channel_id, 'attach_upload_limit'); if ($limit !== false) { $r = q("select sum(filesize) as total from attach where aid = %d ", intval($channel['channel_account_id'])); if ($r && $r[0]['total'] + $filesize > $limit - $existing_size) { $ret['message'] = upgrade_message(true) . sprintf(t("You have reached your limit of %1\$.0f Mbytes attachment storage."), $limit / 1024000); if ($remove_when_processed) { @unlink($src); } call_hooks('photo_upload_end', $ret); return $ret; } } $mimetype = isset($type) && $type ? $type : z_mime_content_type($filename); } $os_basepath = 'store/' . $channel['channel_address'] . '/'; $os_relpath = ''; if ($folder_hash) { $curr = find_folder_hash_by_attach_hash($channel_id, $folder_hash, true); if ($curr) { $os_relpath .= $curr . '/'; } $os_relpath .= $folder_hash . '/'; } $os_relpath .= $hash; if ($src) { @file_put_contents($os_basepath . $os_relpath, @file_get_contents($src)); } if (array_key_exists('created', $arr)) { $created = $arr['created']; } else { $created = datetime_convert(); } if (array_key_exists('edited', $arr)) { $edited = $arr['edited']; } else { $edited = $created; } if ($options === 'replace') { $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', filesize = %d, os_storage = %d, is_photo = %d, content = '%s', edited = '%s' where id = %d and uid = %d", dbesc($filename), dbesc($mimetype), dbesc($folder_hash), intval($filesize), intval(1), intval($is_photo), dbesc($os_basepath . $os_relpath), dbesc($created), intval($existing_id), intval($channel_id)); } elseif ($options === 'revise') { $r = q("insert into attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, content, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )\n\t\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($x[0]['aid']), intval($channel_id), dbesc($x[0]['hash']), dbesc($observer_hash), dbesc($filename), dbesc($mimetype), dbesc($folder_hash), intval($filesize), intval($x[0]['revision'] + 1), intval(1), intval($is_photo), dbesc($os_basepath . $os_relpath), dbesc($created), dbesc($created), dbesc($x[0]['allow_cid']), dbesc($x[0]['allow_gid']), dbesc($x[0]['deny_cid']), dbesc($x[0]['deny_gid'])); } elseif ($options === 'update') { $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', edited = '%s', os_storage = %d, is_photo = %d, \n\t\t\tallow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where id = %d and uid = %d", dbesc(array_key_exists('filename', $arr) ? $arr['filename'] : $x[0]['filename']), dbesc(array_key_exists('filetype', $arr) ? $arr['filetype'] : $x[0]['filetype']), dbesc($folder_hash ? $folder_hash : $x[0]['folder']), dbesc($created), dbesc(array_key_exists('os_storage', $arr) ? $arr['os_storage'] : $x[0]['os_storage']), dbesc(array_key_exists('is_photo', $arr) ? $arr['is_photo'] : $x[0]['is_photo']), dbesc(array_key_exists('allow_cid', $arr) ? $arr['allow_cid'] : $x[0]['allow_cid']), dbesc(array_key_exists('allow_gid', $arr) ? $arr['allow_gid'] : $x[0]['allow_gid']), dbesc(array_key_exists('deny_cid', $arr) ? $arr['deny_cid'] : $x[0]['deny_cid']), dbesc(array_key_exists('deny_gid', $arr) ? $arr['deny_gid'] : $x[0]['deny_gid']), intval($x[0]['id']), intval($x[0]['uid'])); } else { $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, content, created, edited, allow_cid, allow_gid,deny_cid, deny_gid )\n\t\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($channel['channel_account_id']), intval($channel_id), dbesc($hash), dbesc(get_observer_hash()), dbesc($filename), dbesc($mimetype), dbesc($folder_hash), intval($filesize), intval(0), intval(1), intval($is_photo), dbesc($os_basepath . $os_relpath), dbesc($created), dbesc($created), dbesc($arr && array_key_exists('allow_cid', $arr) ? $arr['allow_cid'] : $str_contact_allow), dbesc($arr && array_key_exists('allow_gid', $arr) ? $arr['allow_gid'] : $str_group_allow), dbesc($arr && array_key_exists('deny_cid', $arr) ? $arr['deny_cid'] : $str_contact_deny), dbesc($arr && array_key_exists('deny_gid', $arr) ? $arr['deny_gid'] : $str_group_deny)); } if ($is_photo) { $args = array('source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct, 'options' => $options); if ($arr['contact_allow']) { $args['contact_allow'] = $arr['contact_allow']; } if ($arr['group_allow']) { $args['group_allow'] = $arr['group_allow']; } if ($arr['contact_deny']) { $args['contact_deny'] = $arr['contact_deny']; } if ($arr['group_deny']) { $args['group_deny'] = $arr['group_deny']; } if (array_key_exists('allow_cid', $arr)) { $args['allow_cid'] = $arr['allow_cid']; } if (array_key_exists('allow_gid', $arr)) { $args['allow_gid'] = $arr['allow_gid']; } if (array_key_exists('deny_cid', $arr)) { $args['deny_cid'] = $arr['deny_cid']; } if (array_key_exists('deny_gid', $arr)) { $args['deny_gid'] = $arr['deny_gid']; } $args['created'] = $created; $args['edited'] = $edited; if ($arr['item']) { $args['item'] = $arr['item']; } if ($arr['body']) { $args['body'] = $arr['body']; } if ($arr['description']) { $args['description'] = $arr['description']; } $args['deliver'] = $dosync; $p = photo_upload($channel, $observer, $args); if ($p['success']) { $ret['body'] = $p['body']; } } if ($options !== 'update' && $remove_when_processed) { @unlink($src); } if (!$r) { $ret['message'] = t('File upload failed. Possible system limit or action terminated.'); call_hooks('photo_upload_end', $ret); return $ret; } // Caution: This re-uses $sql_options set further above $r = q("select * from attach where uid = %d and hash = '%s' {$sql_options} limit 1", intval($channel_id), dbesc($hash)); if (!$r) { $ret['message'] = t('Stored file could not be verified. Upload failed.'); call_hooks('photo_upload_end', $ret); return $ret; } $ret['success'] = true; $ret['data'] = $r[0]; if (!$is_photo) { // This would've been called already with a success result in photos_upload() if it was a photo. call_hooks('photo_upload_end', $ret); } if ($dosync) { $sync = attach_export_data($channel, $hash); if ($sync) { build_sync_packet($channel['channel_id'], array('file' => array($sync))); } } return $ret; }
/** * @brief Changes permissions of a file. * * @param int $channel_id * @param array $resource * @param string $allow_cid * @param string $allow_gid * @param string $deny_cid * @param string $deny_gid * @param boolean $recurse (optional) default false */ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse = false, $sync = false) { $channel = channelx_by_n($channel_id); if (!$channel) { return; } $r = q("select hash, flags, is_dir, is_photo from attach where hash = '%s' and uid = %d limit 1", dbesc($resource), intval($channel_id)); if (!$r) { return; } if (intval($r[0]['is_dir'])) { if ($recurse) { $r = q("select hash, flags, is_dir from attach where folder = '%s' and uid = %d", dbesc($resource), intval($channel_id)); if ($r) { foreach ($r as $rr) { attach_change_permissions($channel_id, $rr['hash'], $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse, $sync); } } } } $x = q("update attach set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where hash = '%s' and uid = %d", dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid), dbesc($resource), intval($channel_id)); if ($r[0]['is_photo']) { $x = q("update photo set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where resource_id = '%s' and uid = %d", dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid), dbesc($resource), intval($channel_id)); } if ($sync) { $data = attach_export_data($channel, $resource); if ($data) { build_sync_packet($channel['channel_id'], array('file' => array($data))); } } }
/** * @brief delete directory */ public function delete() { logger('delete file ' . basename($this->red_path), LOGGER_DEBUG); if (!$this->auth->owner_id || !perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage')) { throw new DAV\Exception\Forbidden('Permission denied.'); } if ($this->auth->owner_id !== $this->auth->channel_id) { if ($this->auth->observer !== $this->data['creator'] || intval($this->data['is_dir'])) { throw new DAV\Exception\Forbidden('Permission denied.'); } } attach_delete($this->auth->owner_id, $this->folder_hash); $ch = channelx_by_n($this->auth->owner_id); if ($ch) { $sync = attach_export_data($ch, $this->folder_hash, true); if ($sync) { build_sync_packet($ch['channel_id'], array('file' => array($sync))); } } }
function profiles_build_sync($channel_id) { $r = q("select * from profile where uid = %d", intval($channel_id)); if ($r) { build_sync_packet($channel_id, array('profile' => $r)); } }
function events_content(&$a) { if (argc() > 2 && argv(1) == 'ical') { $event_id = argv(2); require_once 'include/security.php'; $sql_extra = permissions_sql(local_channel()); $r = q("select * from event where event_hash = '%s' {$sql_extra} limit 1", dbesc($event_id)); if ($r) { header('Content-type: text/calendar'); header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"'); echo ical_wrapper($r); killme(); } else { notice(t('Event not found.') . EOL); return; } } if (!local_channel()) { notice(t('Permission denied.') . EOL); return; } nav_set_selected('all_events'); if (argc() > 2 && argv(1) === 'ignore' && intval(argv(2))) { $r = q("update event set ignore = 1 where id = %d and uid = %d", intval(argv(2)), intval(local_channel())); } if (argc() > 2 && argv(1) === 'unignore' && intval(argv(2))) { $r = q("update event set ignore = 0 where id = %d and uid = %d", intval(argv(2)), intval(local_channel())); } $first_day = get_pconfig(local_channel(), 'system', 'cal_first_day'); $first_day = $first_day ? $first_day : 0; $htpl = get_markup_template('event_head.tpl'); $a->page['htmlhead'] .= replace_macros($htpl, array('$baseurl' => $a->get_baseurl(), '$lang' => $a->language, '$first_day' => $first_day)); $o = ''; $channel = $a->get_channel(); $mode = 'view'; $y = 0; $m = 0; $ignored = x($_REQUEST, 'ignored') ? " and ignored = " . intval($_REQUEST['ignored']) . " " : ''; if (argc() > 1) { if (argc() > 2 && argv(1) === 'add') { $mode = 'add'; $item_id = intval(argv(2)); } if (argc() > 2 && argv(1) === 'drop') { $mode = 'drop'; $event_id = argv(2); } if (argc() > 2 && intval(argv(1)) && intval(argv(2))) { $mode = 'view'; $y = intval(argv(1)); $m = intval(argv(2)); } if (argc() <= 2) { $mode = 'view'; $event_id = argv(1); } } if ($mode === 'add') { event_addtocal($item_id, local_channel()); killme(); } if ($mode == 'view') { /* edit/create form */ if ($event_id) { $r = q("SELECT * FROM `event` WHERE event_hash = '%s' AND `uid` = %d LIMIT 1", dbesc($event_id), intval(local_channel())); if (count($r)) { $orig_event = $r[0]; } } $channel = $a->get_channel(); // Passed parameters overrides anything found in the DB if (!x($orig_event)) { $orig_event = array(); } // In case of an error the browser is redirected back here, with these parameters filled in with the previous values /* if(x($_REQUEST,'nofinish')) $orig_event['nofinish'] = $_REQUEST['nofinish']; if(x($_REQUEST,'adjust')) $orig_event['adjust'] = $_REQUEST['adjust']; if(x($_REQUEST,'summary')) $orig_event['summary'] = $_REQUEST['summary']; if(x($_REQUEST,'description')) $orig_event['description'] = $_REQUEST['description']; if(x($_REQUEST,'location')) $orig_event['location'] = $_REQUEST['location']; if(x($_REQUEST,'start')) $orig_event['start'] = $_REQUEST['start']; if(x($_REQUEST,'finish')) $orig_event['finish'] = $_REQUEST['finish']; if(x($_REQUEST,'type')) $orig_event['type'] = $_REQUEST['type']; */ $n_checked = x($orig_event) && $orig_event['nofinish'] ? ' checked="checked" ' : ''; $a_checked = x($orig_event) && $orig_event['adjust'] ? ' checked="checked" ' : ''; $t_orig = x($orig_event) ? $orig_event['summary'] : ''; $d_orig = x($orig_event) ? $orig_event['description'] : ''; $l_orig = x($orig_event) ? $orig_event['location'] : ''; $eid = x($orig_event) ? $orig_event['id'] : 0; $event_xchan = x($orig_event) ? $orig_event['event_xchan'] : $channel['channel_hash']; $mid = x($orig_event) ? $orig_event['mid'] : ''; if (!x($orig_event)) { $sh_checked = ''; } else { $sh_checked = ($orig_event['allow_cid'] === '<' . $channel['channel_hash'] . '>' || !$orig_event['allow_cid']) && !$orig_event['allow_gid'] && !$orig_event['deny_cid'] && !$orig_event['deny_gid'] ? '' : ' checked="checked" '; } if ($orig_event['event_xchan']) { $sh_checked .= ' disabled="disabled" '; } $sdt = x($orig_event) ? $orig_event['start'] : 'now'; $fdt = x($orig_event) ? $orig_event['finish'] : '+1 hour'; $tz = date_default_timezone_get(); if (x($orig_event)) { $tz = $orig_event['adjust'] ? date_default_timezone_get() : 'UTC'; } $syear = datetime_convert('UTC', $tz, $sdt, 'Y'); $smonth = datetime_convert('UTC', $tz, $sdt, 'm'); $sday = datetime_convert('UTC', $tz, $sdt, 'd'); $shour = datetime_convert('UTC', $tz, $sdt, 'H'); $sminute = datetime_convert('UTC', $tz, $sdt, 'i'); $stext = datetime_convert('UTC', $tz, $sdt); $stext = substr($stext, 0, 14) . "00:00"; $fyear = datetime_convert('UTC', $tz, $fdt, 'Y'); $fmonth = datetime_convert('UTC', $tz, $fdt, 'm'); $fday = datetime_convert('UTC', $tz, $fdt, 'd'); $fhour = datetime_convert('UTC', $tz, $fdt, 'H'); $fminute = datetime_convert('UTC', $tz, $fdt, 'i'); $ftext = datetime_convert('UTC', $tz, $fdt); $ftext = substr($ftext, 0, 14) . "00:00"; $type = x($orig_event) ? $orig_event['type'] : 'event'; $f = get_config('system', 'event_input_format'); if (!$f) { $f = 'ymd'; } $catsenabled = feature_enabled(local_channel(), 'categories'); $category = ''; if ($catsenabled && x($orig_event)) { $itm = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d limit 1", dbesc($orig_event['event_hash']), intval(local_channel())); $itm = fetch_post_tags($itm); if ($itm) { $cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY); foreach ($cats as $cat) { if (strlen($category)) { $category .= ', '; } $category .= $cat['term']; } } } require_once 'include/acl_selectors.php'; $acl = new AccessList($channel); $perm_defaults = $acl->get(); $tpl = get_markup_template('event_form.tpl'); $form = replace_macros($tpl, array('$post' => $a->get_baseurl() . '/events', '$eid' => $eid, '$type' => $type, '$xchan' => $event_xchan, '$mid' => $mid, '$event_hash' => $event_id, '$summary' => array('summary', $event_id ? t('Edit event titel') : t('Event titel'), $t_orig, t('Required'), '*'), '$catsenabled' => $catsenabled, '$placeholdercategory' => t('Categories (comma-separated list)'), '$c_text' => $event_id ? t('Edit Category') : t('Category'), '$category' => $category, '$required' => '<span class="required" title="' . t('Required') . '">*</span>', '$s_dsel' => datetimesel($f, new DateTime(), DateTime::createFromFormat('Y', $syear + 5), DateTime::createFromFormat('Y-m-d H:i', "{$syear}-{$smonth}-{$sday} {$shour}:{$sminute}"), $event_id ? t('Edit start date and time') : t('Start date and time'), 'start_text', true, true, '', '', true, $first_day), '$n_text' => t('Finish date and time are not known or not relevant'), '$n_checked' => $n_checked, '$f_dsel' => datetimesel($f, new DateTime(), DateTime::createFromFormat('Y', $fyear + 5), DateTime::createFromFormat('Y-m-d H:i', "{$fyear}-{$fmonth}-{$fday} {$fhour}:{$fminute}"), $event_id ? t('Edit finish date and time') : t('Finish date and time'), 'finish_text', true, true, 'start_text', '', false, $first_day), '$nofinish' => array('nofinish', t('Finish date and time are not known or not relevant'), $n_checked, '', array(t('No'), t('Yes')), 'onclick="enableDisableFinishDate();"'), '$adjust' => array('adjust', t('Adjust for viewer timezone'), $a_checked, t('Important for events that happen in a particular place. Not practical for global holidays.'), array(t('No'), t('Yes'))), '$a_text' => t('Adjust for viewer timezone'), '$d_text' => $event_id ? t('Edit Description') : t('Description'), '$d_orig' => $d_orig, '$l_text' => $event_id ? t('Edit Location') : t('Location'), '$l_orig' => $l_orig, '$t_orig' => $t_orig, '$sh_text' => t('Share this event'), '$sh_checked' => $sh_checked, '$share' => array('share', t('Share this event'), $sh_checked, '', array(t('No'), t('Yes'))), '$preview' => t('Preview'), '$permissions' => t('Permission settings'), '$acl' => $orig_event['event_xchan'] ? '' : populate_acl(x($orig_event) ? $orig_event : $perm_defaults, false), '$submit' => t('Submit'), '$advanced' => t('Advanced Options'))); /* end edit/create form */ $thisyear = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y'); $thismonth = datetime_convert('UTC', date_default_timezone_get(), 'now', 'm'); if (!$y) { $y = intval($thisyear); } if (!$m) { $m = intval($thismonth); } $export = false; if (argc() === 4 && argv(3) === 'export') { $export = true; } // Put some limits on dates. The PHP date functions don't seem to do so well before 1900. // An upper limit was chosen to keep search engines from exploring links millions of years in the future. if ($y < 1901) { $y = 1900; } if ($y > 2099) { $y = 2100; } $nextyear = $y; $nextmonth = $m + 1; if ($nextmonth > 12) { $nextmonth = 1; $nextyear++; } $prevyear = $y; if ($m > 1) { $prevmonth = $m - 1; } else { $prevmonth = 12; $prevyear--; } $dim = get_dim($y, $m); $start = sprintf('%d-%d-%d %d:%d:%d', $y, $m, 1, 0, 0, 0); $finish = sprintf('%d-%d-%d %d:%d:%d', $y, $m, $dim, 23, 59, 59); if (argv(1) === 'json') { if (x($_GET, 'start')) { $start = $_GET['start']; } if (x($_GET, 'end')) { $finish = $_GET['end']; } } $start = datetime_convert('UTC', 'UTC', $start); $finish = datetime_convert('UTC', 'UTC', $finish); $adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start); $adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish); if (x($_GET, 'id')) { $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan\n from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d limit 1", intval(local_channel()), intval($_GET['id'])); } elseif ($export) { $r = q("SELECT * from event where uid = %d\n\t\t\t\tAND (( `adjust` = 0 AND ( `finish` >= '%s' or nofinish = 1 ) AND `start` <= '%s' ) \n\t\t\t\tOR ( `adjust` = 1 AND ( `finish` >= '%s' or nofinish = 1 ) AND `start` <= '%s' )) ", intval(local_channel()), dbesc($start), dbesc($finish), dbesc($adjust_start), dbesc($adjust_finish)); } else { // fixed an issue with "nofinish" events not showing up in the calendar. // There's still an issue if the finish date crosses the end of month. // Noting this for now - it will need to be fixed here and in Friendica. // Ultimately the finish date shouldn't be involved in the query. $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan\n from event left join item on event_hash = resource_id \n\t\t\t\twhere resource_type = 'event' and event.uid = %d {$ignored} \n\t\t\t\tAND (( adjust = 0 AND ( finish >= '%s' or nofinish = 1 ) AND start <= '%s' ) \n\t\t\t\tOR ( adjust = 1 AND ( finish >= '%s' or nofinish = 1 ) AND start <= '%s' )) ", intval(local_channel()), dbesc($start), dbesc($finish), dbesc($adjust_start), dbesc($adjust_finish)); } $links = array(); if ($r && !$export) { xchan_query($r); $r = fetch_post_tags($r, true); $r = sort_by_date($r); } if ($r) { foreach ($r as $rr) { $j = $rr['adjust'] ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'j') : datetime_convert('UTC', 'UTC', $rr['start'], 'j'); if (!x($links, $j)) { $links[$j] = $a->get_baseurl() . '/' . $a->cmd . '#link-' . $j; } } } $events = array(); $last_date = ''; $fmt = t('l, F j'); if ($r) { foreach ($r as $rr) { $j = $rr['adjust'] ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'j') : datetime_convert('UTC', 'UTC', $rr['start'], 'j'); $d = $rr['adjust'] ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], $fmt) : datetime_convert('UTC', 'UTC', $rr['start'], $fmt); $d = day_translate($d); $start = $rr['adjust'] ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'c') : datetime_convert('UTC', 'UTC', $rr['start'], 'c'); if ($rr['nofinish']) { $end = null; } else { $end = $rr['adjust'] ? datetime_convert('UTC', date_default_timezone_get(), $rr['finish'], 'c') : datetime_convert('UTC', 'UTC', $rr['finish'], 'c'); } $is_first = $d !== $last_date; $last_date = $d; $edit = local_channel() && $rr['author_xchan'] == get_observer_hash() ? array($a->get_baseurl() . '/events/' . $rr['event_hash'] . '?expandform=1', t('Edit event'), '', '') : false; $drop = array($a->get_baseurl() . '/events/drop/' . $rr['event_hash'], t('Delete event'), '', ''); $title = strip_tags(html_entity_decode(bbcode($rr['summary']), ENT_QUOTES, 'UTF-8')); if (!$title) { list($title, $_trash) = explode("<br", bbcode($rr['desc']), 2); $title = strip_tags(html_entity_decode($title, ENT_QUOTES, 'UTF-8')); } $html = format_event_html($rr); $rr['desc'] = bbcode($rr['desc']); $rr['location'] = bbcode($rr['location']); $events[] = array('id' => $rr['id'], 'hash' => $rr['event_hash'], 'start' => $start, 'end' => $end, 'drop' => $drop, 'allDay' => false, 'title' => $title, 'j' => $j, 'd' => $d, 'edit' => $edit, 'is_first' => $is_first, 'item' => $rr, 'html' => $html, 'plink' => array($rr['plink'], t('Link to Source'), '', '')); } } if ($export) { header('Content-type: text/calendar'); header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"'); echo ical_wrapper($r); killme(); } if ($a->argv[1] === 'json') { echo json_encode($events); killme(); } // links: array('href', 'text', 'extra css classes', 'title') if (x($_GET, 'id')) { $tpl = get_markup_template("event.tpl"); } else { $tpl = get_markup_template("events-js.tpl"); } $o = replace_macros($tpl, array('$baseurl' => $a->get_baseurl(), '$new_event' => array($a->get_baseurl() . '/events', $event_id ? t('Edit Event') : t('Create Event'), '', ''), '$previus' => array($a->get_baseurl() . "/events/{$prevyear}/{$prevmonth}", t('Previous'), '', ''), '$next' => array($a->get_baseurl() . "/events/{$nextyear}/{$nextmonth}", t('Next'), '', ''), '$export' => array($a->get_baseurl() . "/events/{$y}/{$m}/export", t('Export'), '', ''), '$calendar' => cal($y, $m, $links, ' eventcal'), '$events' => $events, '$upload' => t('Import'), '$submit' => t('Submit'), '$prev' => t('Previous'), '$next' => t('Next'), '$today' => t('Today'), '$form' => $form, '$expandform' => x($_GET, 'expandform') ? true : false)); if (x($_GET, 'id')) { echo $o; killme(); } return $o; } if ($mode === 'drop' && $event_id) { $r = q("SELECT * FROM `event` WHERE event_hash = '%s' AND `uid` = %d LIMIT 1", dbesc($event_id), intval(local_channel())); $sync_event = $r[0]; if ($r) { $r = q("delete from event where event_hash = '%s' and uid = %d limit 1", dbesc($event_id), intval(local_channel())); if ($r) { $r = q("update item set resource_type = '', resource_id = '' where resource_type = 'event' and resource_id = '%s' and uid = %d", dbesc($event_id), intval(local_channel())); $sync_event['event_deleted'] = 1; build_sync_packet(0, array('event' => array($sync_event))); info(t('Event removed') . EOL); } else { notice(t('Failed to remove event') . EOL); } goaway(z_root() . '/events'); } } }
function post() { if (!local_channel()) { notice(t('Permission denied.') . EOL); return; } require_once 'include/activities.php'; $namechanged = false; // import from json export file. // Only import fields that are allowed on this hub if (x($_FILES, 'userfile')) { $src = $_FILES['userfile']['tmp_name']; $filesize = intval($_FILES['userfile']['size']); if ($filesize) { $j = @json_decode(@file_get_contents($src), true); @unlink($src); if ($j) { $fields = get_profile_fields_advanced(); if ($fields) { foreach ($j as $jj => $v) { foreach ($fields as $f => $n) { if ($jj == $f) { $_POST[$f] = $v; break; } } } } } } } call_hooks('profile_post', $_POST); if (argc() > 1 && argv(1) !== "new" && intval(argv(1))) { $orig = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval(\App::$argv[1]), intval(local_channel())); if (!count($orig)) { notice(t('Profile not found.') . EOL); return; } check_form_security_token_redirectOnErr('/profiles', 'profile_edit'); $is_default = $orig[0]['is_default'] ? 1 : 0; $profile_name = notags(trim($_POST['profile_name'])); if (!strlen($profile_name)) { notice(t('Profile Name is required.') . EOL); return; } $dob = $_POST['dob'] ? escape_tags(trim($_POST['dob'])) : '0000-00-00'; // FIXME: Needs to be validated? $y = substr($dob, 0, 4); if (!ctype_digit($y) || $y < 1900) { $ignore_year = true; } else { $ignore_year = false; } if ($dob != '0000-00-00') { if (strpos($dob, '0000-') === 0) { $ignore_year = true; $dob = substr($dob, 5); } $dob = datetime_convert('UTC', 'UTC', $ignore_year ? '1900-' . $dob : $dob, $ignore_year ? 'm-d' : 'Y-m-d'); if ($ignore_year) { $dob = '0000-' . $dob; } } $name = escape_tags(trim($_POST['name'])); if ($orig[0]['fullname'] != $name) { $namechanged = true; $v = validate_channelname($name); if ($v) { notice($v); $namechanged = false; $name = $orig[0]['fullname']; } } $pdesc = escape_tags(trim($_POST['pdesc'])); $gender = escape_tags(trim($_POST['gender'])); $address = escape_tags(trim($_POST['address'])); $locality = escape_tags(trim($_POST['locality'])); $region = escape_tags(trim($_POST['region'])); $postal_code = escape_tags(trim($_POST['postal_code'])); $country_name = escape_tags(trim($_POST['country_name'])); $keywords = escape_tags(trim($_POST['keywords'])); $marital = escape_tags(trim($_POST['marital'])); $howlong = escape_tags(trim($_POST['howlong'])); $sexual = escape_tags(trim($_POST['sexual'])); $homepage = escape_tags(trim($_POST['homepage'])); $hometown = escape_tags(trim($_POST['hometown'])); $politic = escape_tags(trim($_POST['politic'])); $religion = escape_tags(trim($_POST['religion'])); $likes = fix_mce_lf(escape_tags(trim($_POST['likes']))); $dislikes = fix_mce_lf(escape_tags(trim($_POST['dislikes']))); $about = fix_mce_lf(escape_tags(trim($_POST['about']))); $interest = fix_mce_lf(escape_tags(trim($_POST['interest']))); $contact = fix_mce_lf(escape_tags(trim($_POST['contact']))); $channels = fix_mce_lf(escape_tags(trim($_POST['channels']))); $music = fix_mce_lf(escape_tags(trim($_POST['music']))); $book = fix_mce_lf(escape_tags(trim($_POST['book']))); $tv = fix_mce_lf(escape_tags(trim($_POST['tv']))); $film = fix_mce_lf(escape_tags(trim($_POST['film']))); $romance = fix_mce_lf(escape_tags(trim($_POST['romance']))); $work = fix_mce_lf(escape_tags(trim($_POST['work']))); $education = fix_mce_lf(escape_tags(trim($_POST['education']))); $hide_friends = intval($_POST['hide_friends']) ? 1 : 0; require_once 'include/text.php'; linkify_tags($a, $likes, local_channel()); linkify_tags($a, $dislikes, local_channel()); linkify_tags($a, $about, local_channel()); linkify_tags($a, $interest, local_channel()); linkify_tags($a, $interest, local_channel()); linkify_tags($a, $contact, local_channel()); linkify_tags($a, $channels, local_channel()); linkify_tags($a, $music, local_channel()); linkify_tags($a, $book, local_channel()); linkify_tags($a, $tv, local_channel()); linkify_tags($a, $film, local_channel()); linkify_tags($a, $romance, local_channel()); linkify_tags($a, $work, local_channel()); linkify_tags($a, $education, local_channel()); $with = x($_POST, 'with') ? escape_tags(trim($_POST['with'])) : ''; if (!strlen($howlong)) { $howlong = NULL_DATE; } else { $howlong = datetime_convert(date_default_timezone_get(), 'UTC', $howlong); } // linkify the relationship target if applicable $withchanged = false; if (strlen($with)) { if ($with != strip_tags($orig[0]['partner'])) { $withchanged = true; $prf = ''; $lookup = $with; if (strpos($lookup, '@') === 0) { $lookup = substr($lookup, 1); } $lookup = str_replace('_', ' ', $lookup); $newname = $lookup; $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1", dbesc($newname), intval(local_channel())); if (!$r) { $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE xchan_addr = '%s' AND abook_channel = %d LIMIT 1", dbesc($lookup . '@%'), intval(local_channel())); } if ($r) { $prf = $r[0]['xchan_url']; $newname = $r[0]['xchan_name']; } if ($prf) { $with = str_replace($lookup, '<a href="' . $prf . '">' . $newname . '</a>', $with); if (strpos($with, '@') === 0) { $with = substr($with, 1); } } } else { $with = $orig[0]['partner']; } } $profile_fields_basic = get_profile_fields_basic(); $profile_fields_advanced = get_profile_fields_advanced(); $advanced = feature_enabled(local_channel(), 'advanced_profiles') ? true : false; if ($advanced) { $fields = $profile_fields_advanced; } else { $fields = $profile_fields_basic; } $z = q("select * from profdef where true"); if ($z) { foreach ($z as $zz) { if (array_key_exists($zz['field_name'], $fields)) { $w = q("select * from profext where channel_id = %d and hash = '%s' and k = '%s' limit 1", intval(local_channel()), dbesc($orig[0]['profile_guid']), dbesc($zz['field_name'])); if ($w) { q("update profext set v = '%s' where id = %d", dbesc(escape_tags(trim($_POST[$zz['field_name']]))), intval($w[0]['id'])); } else { q("insert into profext ( channel_id, hash, k, v ) values ( %d, '%s', '%s', '%s') ", intval(local_channel()), dbesc($orig[0]['profile_guid']), dbesc($zz['field_name']), dbesc(escape_tags(trim($_POST[$zz['field_name']])))); } } } } $changes = array(); $value = ''; if ($is_default) { if ($marital != $orig[0]['marital']) { $changes[] = '[color=#ff0000]♥[/color] ' . t('Marital Status'); $value = $marital; } if ($withchanged) { $changes[] = '[color=#ff0000]♥[/color] ' . t('Romantic Partner'); $value = strip_tags($with); } if ($likes != $orig[0]['likes']) { $changes[] = t('Likes'); $value = $likes; } if ($dislikes != $orig[0]['dislikes']) { $changes[] = t('Dislikes'); $value = $dislikes; } if ($work != $orig[0]['employment']) { $changes[] = t('Work/Employment'); } if ($religion != $orig[0]['religion']) { $changes[] = t('Religion'); $value = $religion; } if ($politic != $orig[0]['politic']) { $changes[] = t('Political Views'); $value = $politic; } if ($gender != $orig[0]['gender']) { $changes[] = t('Gender'); $value = $gender; } if ($sexual != $orig[0]['sexual']) { $changes[] = t('Sexual Preference'); $value = $sexual; } if ($homepage != $orig[0]['homepage']) { $changes[] = t('Homepage'); $value = $homepage; } if ($interest != $orig[0]['interest']) { $changes[] = t('Interests'); $value = $interest; } if ($address != $orig[0]['address']) { $changes[] = t('Address'); // New address not sent in notifications, potential privacy issues // in case this leaks to unintended recipients. Yes, it's in the public // profile but that doesn't mean we have to broadcast it to everybody. } if ($locality != $orig[0]['locality'] || $region != $orig[0]['region'] || $country_name != $orig[0]['country_name']) { $changes[] = t('Location'); $comma1 = $locality && ($region || $country_name) ? ', ' : ' '; $comma2 = $region && $country_name ? ', ' : ''; $value = $locality . $comma1 . $region . $comma2 . $country_name; } profile_activity($changes, $value); } $r = q("UPDATE `profile` \n\t\t\t\tSET `profile_name` = '%s',\n\t\t\t\t`fullname` = '%s',\n\t\t\t\t`pdesc` = '%s',\n\t\t\t\t`gender` = '%s',\n\t\t\t\t`dob` = '%s',\n\t\t\t\t`address` = '%s',\n\t\t\t\t`locality` = '%s',\n\t\t\t\t`region` = '%s',\n\t\t\t\t`postal_code` = '%s',\n\t\t\t\t`country_name` = '%s',\n\t\t\t\t`marital` = '%s',\n\t\t\t\t`partner` = '%s',\n\t\t\t\t`howlong` = '%s',\n\t\t\t\t`sexual` = '%s',\n\t\t\t\t`homepage` = '%s',\n\t\t\t\t`hometown` = '%s',\n\t\t\t\t`politic` = '%s',\n\t\t\t\t`religion` = '%s',\n\t\t\t\t`keywords` = '%s',\n\t\t\t\t`likes` = '%s',\n\t\t\t\t`dislikes` = '%s',\n\t\t\t\t`about` = '%s',\n\t\t\t\t`interest` = '%s',\n\t\t\t\t`contact` = '%s',\n\t\t\t\t`channels` = '%s',\n\t\t\t\t`music` = '%s',\n\t\t\t\t`book` = '%s',\n\t\t\t\t`tv` = '%s',\n\t\t\t\t`film` = '%s',\n\t\t\t\t`romance` = '%s',\n\t\t\t\t`employment` = '%s',\n\t\t\t\t`education` = '%s',\n\t\t\t\t`hide_friends` = %d\n\t\t\t\tWHERE `id` = %d AND `uid` = %d", dbesc($profile_name), dbesc($name), dbesc($pdesc), dbesc($gender), dbesc($dob), dbesc($address), dbesc($locality), dbesc($region), dbesc($postal_code), dbesc($country_name), dbesc($marital), dbesc($with), dbesc($howlong), dbesc($sexual), dbesc($homepage), dbesc($hometown), dbesc($politic), dbesc($religion), dbesc($keywords), dbesc($likes), dbesc($dislikes), dbesc($about), dbesc($interest), dbesc($contact), dbesc($channels), dbesc($music), dbesc($book), dbesc($tv), dbesc($film), dbesc($romance), dbesc($work), dbesc($education), intval($hide_friends), intval(argv(1)), intval(local_channel())); if ($r) { info(t('Profile updated.') . EOL); } $r = q("select * from profile where id = %d and uid = %d limit 1", intval(argv(1)), intval(local_channel())); if ($r) { require_once 'include/zot.php'; build_sync_packet(local_channel(), array('profile' => $r)); } $channel = \App::get_channel(); if ($namechanged && $is_default) { $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'", dbesc($name), dbesc(datetime_convert()), dbesc($channel['xchan_hash'])); $r = q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'", dbesc($name), dbesc($channel['xchan_hash'])); } if ($is_default) { // reload the info for the sidebar widget - why does this not work? profile_load($channel['channel_address']); \Zotlabs\Daemon\Master::Summon(array('Directory', local_channel())); } } }
/** * @brief Refreshes after permission changed or friending, etc. * * zot_refresh is typically invoked when somebody has changed permissions of a channel and they are notified * to fetch new permissions via a finger/discovery operation. This may result in a new connection * (abook entry) being added to a local channel and it may result in auto-permissions being granted. * * Friending in zot is accomplished by sending a refresh packet to a specific channel which indicates a * permission change has been made by the sender which affects the target channel. The hub controlling * the target channel does targetted discovery (a zot-finger request requesting permissions for the local * channel). These are decoded here, and if necessary and abook structure (addressbook) is created to store * the permissions assigned to this channel. * * Initially these abook structures are created with a 'pending' flag, so that no reverse permissions are * implied until this is approved by the owner channel. A channel can also auto-populate permissions in * return and send back a refresh packet of its own. This is used by forum and group communication channels * so that friending and membership in the channel's "club" is automatic. * * @param array $them => xchan structure of sender * @param array $channel => local channel structure of target recipient, required for "friending" operations * @param array $force default false * * @returns boolean true if successful, else false */ function zot_refresh($them, $channel = null, $force = false) { if (array_key_exists('xchan_network', $them) && $them['xchan_network'] !== 'zot') { logger('zot_refresh: not got zot. ' . $them['xchan_name']); return true; } logger('zot_refresh: them: ' . print_r($them, true), LOGGER_DATA); if ($channel) { logger('zot_refresh: channel: ' . print_r($channel, true), LOGGER_DATA); } $url = null; if ($them['hubloc_url']) { $url = $them['hubloc_url']; } else { $r = null; // if they re-installed the server we could end up with the wrong record - pointing to the old install. // We'll order by reverse id to try and pick off the newest one first and hopefully end up with the // correct hubloc. If this doesn't work we may have to re-write this section to try them all. if (array_key_exists('xchan_addr', $them) && $them['xchan_addr']) { $r = q("select hubloc_url, hubloc_primary from hubloc where hubloc_addr = '%s' order by hubloc_id desc", dbesc($them['xchan_addr'])); } if (!$r) { $r = q("select hubloc_url, hubloc_primary from hubloc where hubloc_hash = '%s' order by hubloc_id desc", dbesc($them['xchan_hash'])); } if ($r) { foreach ($r as $rr) { if (intval($rr['hubloc_primary'])) { $url = $rr['hubloc_url']; break; } } if (!$url) { $url = $r[0]['hubloc_url']; } } } if (!$url) { logger('zot_refresh: no url'); return false; } $postvars = array(); if ($channel) { $postvars['target'] = $channel['channel_guid']; $postvars['target_sig'] = $channel['channel_guid_sig']; $postvars['key'] = $channel['channel_pubkey']; } if (array_key_exists('xchan_addr', $them) && $them['xchan_addr']) { $postvars['address'] = $them['xchan_addr']; } if (array_key_exists('xchan_hash', $them) && $them['xchan_hash']) { $postvars['guid_hash'] = $them['xchan_hash']; } if (array_key_exists('xchan_guid', $them) && $them['xchan_guid'] && array_key_exists('xchan_guid_sig', $them) && $them['xchan_guid_sig']) { $postvars['guid'] = $them['xchan_guid']; $postvars['guid_sig'] = $them['xchan_guid_sig']; } $rhs = '/.well-known/zot-info'; $result = z_post_url($url . $rhs, $postvars); logger('zot_refresh: zot-info: ' . print_r($result, true), LOGGER_DATA); if ($result['success']) { $j = json_decode($result['body'], true); if (!($j && $j['success'])) { logger('zot_refresh: result not decodable'); return false; } $x = import_xchan($j, $force ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED); if (!$x['success']) { return false; } $their_perms = 0; if ($channel) { $global_perms = get_perms(); if ($j['permissions']['data']) { $permissions = crypto_unencapsulate(array('data' => $j['permissions']['data'], 'key' => $j['permissions']['key'], 'iv' => $j['permissions']['iv']), $channel['channel_prvkey']); if ($permissions) { $permissions = json_decode($permissions, true); } logger('decrypted permissions: ' . print_r($permissions, true), LOGGER_DATA); } else { $permissions = $j['permissions']; } $connected_set = false; if ($permissions && is_array($permissions)) { foreach ($permissions as $k => $v) { // The connected permission means you are in their address book if ($k === 'connected') { $connected_set = intval($v); continue; } if ($v && array_key_exists($k, $global_perms)) { $their_perms = $their_perms | intval($global_perms[$k][1]); } } } if (array_key_exists('profile', $j) && array_key_exists('next_birthday', $j['profile'])) { $next_birthday = datetime_convert('UTC', 'UTC', $j['profile']['next_birthday']); } else { $next_birthday = NULL_DATE; } $r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", dbesc($x['hash']), intval($channel['channel_id'])); if ($r) { // connection exists // if the dob is the same as what we have stored (disregarding the year), keep the one // we have as we may have updated the year after sending a notification; and resetting // to the one we just received would cause us to create duplicated events. if (substr($r[0]['abook_dob'], 5) == substr($next_birthday, 5)) { $next_birthday = $r[0]['abook_dob']; } $current_abook_connected = intval($r[0]['abook_unconnected']) ? 0 : 1; $y = q("update abook set abook_their_perms = %d, abook_dob = '%s'\n\t\t\t\t\twhere abook_xchan = '%s' and abook_channel = %d\n\t\t\t\t\tand abook_self = 0 ", intval($their_perms), dbescdate($next_birthday), dbesc($x['hash']), intval($channel['channel_id'])); // if(($connected_set === 0 || $connected_set === 1) && ($connected_set !== $current_abook_unconnected)) { // if they are in your address book but you aren't in theirs, and/or this does not // match your current connected state setting, toggle it. /** @FIXME uncoverted to postgres */ /** @FIXME when this was enabled, all contacts became unconnected. Currently disabled intentionally */ // $y1 = q("update abook set abook_unconnected = 1 // where abook_xchan = '%s' and abook_channel = %d // and abook_self = 0 limit 1", // dbesc($x['hash']), // intval($channel['channel_id']) // ); // } if (!$y) { logger('abook update failed'); } else { // if we were just granted read stream permission and didn't have it before, try to pull in some posts if (!($r[0]['abook_their_perms'] & PERMS_R_STREAM) && $their_perms & PERMS_R_STREAM) { proc_run('php', 'include/onepoll.php', $r[0]['abook_id']); } } } else { // new connection $role = get_pconfig($channel['channel_id'], 'system', 'permissions_role'); if ($role) { $xx = get_role_perms($role); if ($xx['perms_auto']) { $default_perms = $xx['perms_accept']; } } if (!$default_perms) { $default_perms = intval(get_pconfig($channel['channel_id'], 'system', 'autoperms')); } // Keep original perms to check if we need to notify them $previous_perms = get_all_perms($channel['channel_id'], $x['hash']); $closeness = get_pconfig($channel['channel_id'], 'system', 'new_abook_closeness'); if ($closeness === false) { $closeness = 80; } $y = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_their_perms, abook_my_perms, abook_created, abook_updated, abook_dob, abook_pending ) values ( %d, %d, %d, '%s', %d, %d, '%s', '%s', '%s', %d )", intval($channel['channel_account_id']), intval($channel['channel_id']), intval($closeness), dbesc($x['hash']), intval($their_perms), intval($default_perms), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($next_birthday), intval($default_perms ? 0 : 1)); if ($y) { logger("New introduction received for {$channel['channel_name']}"); $new_perms = get_all_perms($channel['channel_id'], $x['hash']); // Send a clone sync packet and a permissions update if permissions have changed $new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 order by abook_created desc limit 1", dbesc($x['hash']), intval($channel['channel_id'])); if ($new_connection) { if ($new_perms != $previous_perms) { proc_run('php', 'include/notifier.php', 'permission_create', $new_connection[0]['abook_id']); } require_once 'include/enotify.php'; notification(array('type' => NOTIFY_INTRO, 'from_xchan' => $x['hash'], 'to_xchan' => $channel['channel_hash'], 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'])); if ($their_perms & PERMS_R_STREAM) { if ($channel['channel_w_stream'] & PERMS_PENDING || !intval($new_connection[0]['abook_pending'])) { proc_run('php', 'include/onepoll.php', $new_connection[0]['abook_id']); } } unset($new_connection[0]['abook_id']); unset($new_connection[0]['abook_account']); unset($new_connection[0]['abook_channel']); build_sync_packet($channel['channel_id'], array('abook' => $new_connection)); } } } } return true; } return false; }
function settings_post(&$a) { if (!local_channel()) { return; } if ($_SESSION['delegate']) { return; } $channel = $a->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($a->get_baseurl(true) . "/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\tclient_id='%s',\n\t\t\t\t\t\t\tpw='%s',\n\t\t\t\t\t\t\tname='%s',\n\t\t\t\t\t\t\tredirect_uri='%s',\n\t\t\t\t\t\t\ticon='%s',\n\t\t\t\t\t\t\tuid=%d\n\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, name, redirect_uri, icon, uid)\n\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($a->get_baseurl(true) . "/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) === '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'])) : $a->channel['channel_theme']; $mobile_theme = x($_POST, 'mobile_theme') ? notags(trim($_POST['mobile_theme'])) : ''; $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', '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 == $a->channel['channel_theme']) { // call theme_post only if theme has not been changed if (($themeconfigfile = 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($a->get_baseurl(true) . '/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(); if (x($_POST, 'npassword') || x($_POST, 'confirm')) { $newpass = $_POST['npassword']; $confirm = $_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\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); } $errs = array(); } $email = x($_POST, 'email') ? trim(notags($_POST['email'])) : ''; $account = $a->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 = $a->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); } } goaway($a->get_baseurl(true) . '/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 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\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 name = '%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 name = '%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\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 = $a->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 = $a->get_channel(); $err = ''; $name_change = false; if ($username != $channel['channel_name']) { $name_change = true; require_once 'include/identity.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 name = '%s' where uid = %d and is_default = 1", dbesc($username), intval($channel['channel_id'])); } proc_run('php', 'include/directory.php', local_channel()); build_sync_packet(); //$_SESSION['theme'] = $theme; if ($email_changed && $a->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($a->get_baseurl(true) . '/settings'); return; // NOTREACHED }
function gnusoc_follow_from_feed(&$a, &$b) { $item = $b['item']; $importer = $b['channel']; $xchan = $b['xchan']; $author = $b['author']; $b['caught'] = true; logger('follow activity received'); if ($author && !$xchan) { $r = q("select * from xchan where xchan_guid = '%s' limit 1", dbesc($author['author_link'])); if (!$r) { if (discover_by_webbie($author['author_link'])) { $r = q("select * from xchan where xchan_guid = '%s' limit 1", dbesc($author['author_link'])); if (!$r) { logger('discovery failed'); return; } } $xchan = $r[0]; } $x = \Zotlabs\Access\PermissionRoles::role_perms('social'); $their_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']); $r = q("select * from abook where abook_channel = %d and abook_xchan = '%s' limit 1", intval($importer['channel_id']), dbesc($xchan['xchan_hash'])); if ($r) { $contact = $r[0]; $abook_instance = $contact['abook_instance']; if ($abook_instance) { $abook_instance .= ','; } $abook_instance .= z_root(); $r = q("update abook set abook_instance = '%s' where abook_id = %d and abook_channel = %d", dbesc($abook_instance), intval($contact['abook_id']), intval($importer['channel_id'])); foreach ($their_perms as $k => $v) { set_abconfig($importer['channel_id'], $contact['abook_xchan'], 'their_perms', $k, $v); } } else { $role = get_pconfig($importer['channel_id'], 'system', 'permissions_role'); if ($role) { $x = \Zotlabs\Access\PermissionRoles::role_perms($role); if ($x['perms_auto']) { $my_perms = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']); } } if (!$my_perms) { $my_perms = \Zotlabs\Access\Permissions::FilledAutoperms($importer['channel_id']); } $closeness = get_pconfig($importer['channel_id'], 'system', 'new_abook_closeness'); if ($closeness === false) { $closeness = 80; } $r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_connected, abook_dob, abook_pending, abook_instance ) values ( %d, %d, '%s', %d, '%s', '%s', '%s', '%s', %d, '%s' )", intval($importer['channel_account_id']), intval($importer['channel_id']), dbesc($xchan['xchan_hash']), intval($closeness), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(NULL_DATE), intval($my_perms ? 0 : 1), dbesc(z_root())); if ($r) { if ($my_perms) { foreach ($my_perms as $k => $v) { set_abconfig($importer['channel_id'], $xchan['xchan_hash'], 'my_perms', $k, $v); } } if ($their_perms) { foreach ($their_perms as $k => $v) { set_abconfig($importer['channel_id'], $xchan['xchan_hash'], 'their_perms', $k, $v); } } logger("New GNU-Social follower received for {$importer['channel_name']}"); $new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash left join hubloc on hubloc_hash = xchan_hash where abook_channel = %d and abook_xchan = '%s' order by abook_created desc limit 1", intval($importer['channel_id']), dbesc($xchan['xchan_hash'])); if ($new_connection) { \Zotlabs\Lib\Enotify::submit(array('type' => NOTIFY_INTRO, 'from_xchan' => $xchan['xchan_hash'], 'to_xchan' => $importer['channel_hash'], 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'])); if ($default_perms) { // Send back a sharing notification to them $deliver = gnusoc_remote_follow($importer, $new_connection[0]); if ($deliver) { Zotlabs\Daemon\Master::Summon(array('Deliver', $deliver)); } } $clone = array(); foreach ($new_connection[0] as $k => $v) { if (strpos($k, 'abook_') === 0) { $clone[$k] = $v; } } unset($clone['abook_id']); unset($clone['abook_account']); unset($clone['abook_channel']); $abconfig = load_abconfig($importer['channel_id'], $clone['abook_xchan']); if ($abconfig) { $clone['abconfig'] = $abconfig; } build_sync_packet($importer['channel_id'], array('abook' => array($clone))); } } } return; } }
public static function run($argc, $argv) { $maxsysload = intval(get_config('system', 'maxloadavg')); if ($maxsysload < 1) { $maxsysload = 50; } if (function_exists('sys_getloadavg')) { $load = sys_getloadavg(); if (intval($load[0]) > $maxsysload) { logger('system: load ' . $load . ' too high. Cron deferred to next scheduled run.'); return; } } // Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it. $lockfile = 'store/[data]/cron'; if (file_exists($lockfile) && filemtime($lockfile) > time() - 3600 && !get_config('system', 'override_cron_lockfile')) { logger("cron: Already running"); return; } // Create a lockfile. Needs two vars, but $x doesn't need to contain anything. file_put_contents($lockfile, $x); logger('cron: start'); // run queue delivery process in the background Master::Summon(array('Queue')); Master::Summon(array('Poller')); // maintenance for mod sharedwithme - check for updated items and remove them require_once 'include/sharedwithme.php'; apply_updates(); // expire any expired mail q("delete from mail where expires > '%s' and expires < %s ", dbesc(NULL_DATE), db_utcnow()); // expire any expired items $r = q("select id from item where expires > '2001-01-01 00:00:00' and expires < %s \n\t\t\tand item_deleted = 0 ", db_utcnow()); if ($r) { require_once 'include/items.php'; foreach ($r as $rr) { drop_item($rr['id'], false); } } // delete expired access tokens $r = q("select atoken_id from atoken where atoken_expires > '%s' and atoken_expires < %s", dbesc(NULL_DATE), db_utcnow()); if ($r) { require_once 'include/security.php'; foreach ($r as $rr) { atoken_delete($rr['atoken_id']); } } // Ensure that every channel pings a directory server once a month. This way we can discover // channels and sites that quietly vanished and prevent the directory from accumulating stale // or dead entries. $r = q("select channel_id from channel where channel_dirdate < %s - INTERVAL %s", db_utcnow(), db_quoteinterval('30 DAY')); if ($r) { foreach ($r as $rr) { Master::Summon(array('Directory', $rr['channel_id'], 'force')); if ($interval) { @time_sleep_until(microtime(true) + (double) $interval); } } } // publish any applicable items that were set to be published in the future // (time travel posts). Restrict to items that have come of age in the last // couple of days to limit the query to something reasonable. $r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ", db_utcnow(), dbesc(datetime_convert('UTC', 'UTC', 'now - 2 days'))); if ($r) { foreach ($r as $rr) { $x = q("update item set item_delayed = 0 where id = %d", intval($rr['id'])); if ($x) { $z = q("select * from item where id = %d", intval($message_id)); if ($z) { xchan_query($z); $sync_item = fetch_post_tags($z); build_sync_packet($sync_item[0]['uid'], ['item' => [encode_item($sync_item[0], true)]]); } Master::Summon(array('Notifier', 'wall-new', $rr['id'])); } } } $abandon_days = intval(get_config('system', 'account_abandon_days')); if ($abandon_days < 1) { $abandon_days = 0; } // once daily run birthday_updates and then expire in background // FIXME: add birthday updates, both locally and for xprof for use // by directory servers $d1 = intval(get_config('system', 'last_expire_day')); $d2 = intval(datetime_convert('UTC', 'UTC', 'now', 'd')); // Allow somebody to staggger daily activities if they have more than one site on their server, // or if it happens at an inconvenient (busy) hour. $h1 = intval(get_config('system', 'cron_hour')); $h2 = intval(datetime_convert('UTC', 'UTC', 'now', 'G')); if ($d2 != $d1 && $h1 == $h2) { Master::Summon(array('Cron_daily')); } // update any photos which didn't get imported properly // This should be rare $r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = '' \n\t\t\tand xchan_photo_date < %s - INTERVAL %s", db_utcnow(), db_quoteinterval('1 DAY')); if ($r) { require_once 'include/photo/photo_driver.php'; foreach ($r as $rr) { $photos = import_xchan_photo($rr['xchan_photo_l'], $rr['xchan_hash']); $x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'\n\t\t\t\t\twhere xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), dbesc($photos[3]), dbesc($rr['xchan_hash'])); } } // pull in some public posts if (!get_config('system', 'disable_discover_tab')) { Master::Summon(array('Externals')); } $generation = 0; $restart = false; if ($argc > 1 && $argv[1] == 'restart') { $restart = true; $generation = intval($argv[2]); if (!$generation) { killme(); } } reload_plugins(); $d = datetime_convert(); // TODO check to see if there are any cronhooks before wasting a process if (!$restart) { Master::Summon(array('Cronhooks')); } set_config('system', 'lastcron', datetime_convert()); //All done - clear the lockfile @unlink($lockfile); return; }
function sync_an_item($channel_id, $item_id) { $r = q("select * from item where id = %d", intval($item_id)); if ($r) { xchan_query($r); $sync_item = fetch_post_tags($r); $rid = q("select * from item_id where iid = %d", intval($item_id)); build_sync_packet($channel_d, array('item' => array(encode_item($sync_item[0], true)), 'item_id' => $rid)); } }
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('UTC', '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($a->get_baseurl() . "/" . $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($a->get_baseurl() . "/" . $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 = $a->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($a->get_baseurl() . "/" . $return_path); } killme(); } } else { if (!perm_is_allowed($profile_uid, $observer['xchan_hash'], 'post_wall')) { notice(t('Permission denied.') . EOL); if (x($_REQUEST, 'return')) { goaway($a->get_baseurl() . "/" . $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']; } } 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]; } if (!$channel) { if ($uid && $uid == $profile_uid) { $channel = $a->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($a->get_baseurl() . "/" . $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($a->get_baseurl() . "/" . $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 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 && (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); } $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($a->get_baseurl() . "/" . $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 === 'application/x-php') { $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($a->get_baseurl() . "/" . $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'; if ($uid && $uid == $profile_uid && feature_enabled($uid, 'markdown')) { require_once 'include/bb2diaspora.php'; $body = escape_tags($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(); 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' => $a->get_baseurl() . '/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], $attach_link, $body); } } } // 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))); } } $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_thead_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; // 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; } call_hooks('post_local', $datarray); if (x($datarray, 'cancel')) { logger('mod_item: post cancelled by plugin.'); if ($return_path) { goaway($a->get_baseurl() . "/" . $return_path); } $json = array('cancel' => 1); if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) { $json['reload'] = $a->get_baseurl() . '/' . $_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($a->get_baseurl() . "/" . $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' => $a->get_baseurl() . '/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']) { notification(array('type' => NOTIFY_WALL, 'from_xchan' => $datarray['author_xchan'], 'to_xchan' => $datarray['owner_xchan'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/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($a->get_baseurl() . "/" . $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'] = $a->get_baseurl() . '/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($a->get_baseurl() . "/" . $return_path); } $json = array('success' => 1); if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) { $json['reload'] = $a->get_baseurl() . '/' . $_REQUEST['jsreload']; } logger('post_json: ' . print_r($json, true), LOGGER_DEBUG); echo json_encode($json); killme(); // NOTREACHED }