function init() { if (!local_channel()) { return; } if ($_SESSION['delegate']) { return; } \App::$profile_uid = local_channel(); // default is channel settings in the absence of other arguments if (argc() == 1) { // We are setting these values - don't use the argc(), argv() functions here \App::$argc = 2; \App::$argv[] = 'channel'; } }
/** * App constructor. */ public static function init() { // we'll reset this after we read our config file date_default_timezone_set('UTC'); self::$config = array('system' => array()); self::$page = array(); self::$pager = array(); self::$query_string = ''; startup(); set_include_path('include' . PATH_SEPARATOR . 'library' . PATH_SEPARATOR . 'library/langdet' . PATH_SEPARATOR . '.'); self::$scheme = 'http'; if (x($_SERVER, 'HTTPS') && $_SERVER['HTTPS']) { self::$scheme = 'https'; } elseif (x($_SERVER, 'SERVER_PORT') && intval($_SERVER['SERVER_PORT']) == 443) { self::$scheme = 'https'; } if (x($_SERVER, 'SERVER_NAME')) { self::$hostname = $_SERVER['SERVER_NAME']; if (x($_SERVER, 'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) { self::$hostname .= ':' . $_SERVER['SERVER_PORT']; } /** * Figure out if we are running at the top of a domain * or in a sub-directory and adjust accordingly */ $path = trim(dirname($_SERVER['SCRIPT_NAME']), '/\\'); if (isset($path) && strlen($path) && $path != self::$path) { self::$path = $path; } } set_include_path("include/self::{$hostname}" . PATH_SEPARATOR . get_include_path()); if (x($_SERVER, 'QUERY_STRING') && substr($_SERVER['QUERY_STRING'], 0, 2) === "q=") { self::$query_string = substr($_SERVER['QUERY_STRING'], 2); // removing trailing / - maybe a nginx problem if (substr(self::$query_string, 0, 1) == "/") { self::$query_string = substr(self::$query_string, 1); } } if (x($_GET, 'q')) { self::$cmd = trim($_GET['q'], '/\\'); } // unix style "homedir" if (substr(self::$cmd, 0, 1) === '~') { self::$cmd = 'channel/' . substr(self::$cmd, 1); } /* * Break the URL path into C style argc/argv style arguments for our * modules. Given "http://example.com/module/arg1/arg2", self::$argc * will be 3 (integer) and self::$argv will contain: * [0] => 'module' * [1] => 'arg1' * [2] => 'arg2' * * There will always be one argument. If provided a naked domain * URL, self::$argv[0] is set to "home". */ self::$argv = explode('/', self::$cmd); self::$argc = count(self::$argv); if (array_key_exists('0', self::$argv) && strlen(self::$argv[0])) { self::$module = str_replace(".", "_", self::$argv[0]); self::$module = str_replace("-", "_", self::$module); if (strpos(self::$module, '_') === 0) { self::$module = substr(self::$module, 1); } } else { self::$argc = 1; self::$argv = array('home'); self::$module = 'home'; } /* * See if there is any page number information, and initialise * pagination */ self::$pager['page'] = x($_GET, 'page') && intval($_GET['page']) > 0 ? intval($_GET['page']) : 1; self::$pager['itemspage'] = 60; self::$pager['start'] = self::$pager['page'] * self::$pager['itemspage'] - self::$pager['itemspage']; if (self::$pager['start'] < 0) { self::$pager['start'] = 0; } self::$pager['total'] = 0; /* * Detect mobile devices */ $mobile_detect = new Mobile_Detect(); self::$is_mobile = $mobile_detect->isMobile(); self::$is_tablet = $mobile_detect->isTablet(); self::head_set_icon('/images/hz-32.png'); /* * register template engines */ spl_autoload_register('ZotlabsAutoloader::loader'); self::$meta = new Zotlabs\Web\HttpMeta(); // create an instance of the smarty template engine so we can register it. $smarty = new Zotlabs\Render\SmartyTemplate(); $dc = get_declared_classes(); foreach ($dc as $k) { if (in_array('Zotlabs\\Render\\TemplateEngine', class_implements($k))) { self::register_template_engine($k); } } }
function get() { $sort_type = 0; $o = ''; if (!local_channel()) { notice(t('Permission denied.') . EOL); return login(); } $blocked = false; $hidden = false; $ignored = false; $archived = false; $unblocked = false; $pending = false; $unconnected = false; $all = false; if (!$_REQUEST['aj']) { $_SESSION['return_url'] = \App::$query_string; } $search_flags = ''; $head = ''; if (argc() == 2) { switch (argv(1)) { case 'blocked': $search_flags = " and abook_blocked = 1 "; $head = t('Blocked'); $blocked = true; break; case 'ignored': $search_flags = " and abook_ignored = 1 "; $head = t('Ignored'); $ignored = true; break; case 'hidden': $search_flags = " and abook_hidden = 1 "; $head = t('Hidden'); $hidden = true; break; case 'archived': $search_flags = " and abook_archived = 1 "; $head = t('Archived'); $archived = true; break; case 'pending': $search_flags = " and abook_pending = 1 "; $head = t('New'); $pending = true; nav_set_selected('intros'); break; case 'ifpending': $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ", intval(local_channel())); if ($r && $r[0]['total']) { $search_flags = " and abook_pending = 1 "; $head = t('New'); $pending = true; nav_set_selected('intros'); \App::$argv[1] = 'pending'; } else { $head = t('All'); $search_flags = ''; $all = true; \App::$argc = 1; unset(\App::$argv[1]); } nav_set_selected('intros'); break; // case 'unconnected': // $search_flags = " and abook_unconnected = 1 "; // $head = t('Unconnected'); // $unconnected = true; // break; // case 'unconnected': // $search_flags = " and abook_unconnected = 1 "; // $head = t('Unconnected'); // $unconnected = true; // break; case 'all': $head = t('All'); default: $search_flags = ''; $all = true; break; } $sql_extra = $search_flags; if (argv(1) === 'pending') { $sql_extra .= " and abook_ignored = 0 "; } } else { $sql_extra = " and abook_blocked = 0 "; $unblocked = true; } $search = x($_REQUEST, 'search') ? notags(trim($_REQUEST['search'])) : ''; $tabs = array('pending' => array('label' => t('New Connections'), 'url' => z_root() . '/connections/pending', 'sel' => $pending ? 'active' : '', 'title' => t('Show pending (new) connections')), 'all' => array('label' => t('All Connections'), 'url' => z_root() . '/connections/all', 'sel' => $all ? 'active' : '', 'title' => t('Show all connections')), 'blocked' => array('label' => t('Blocked'), 'url' => z_root() . '/connections/blocked', 'sel' => $blocked ? 'active' : '', 'title' => t('Only show blocked connections')), 'ignored' => array('label' => t('Ignored'), 'url' => z_root() . '/connections/ignored', 'sel' => $ignored ? 'active' : '', 'title' => t('Only show ignored connections')), 'archived' => array('label' => t('Archived'), 'url' => z_root() . '/connections/archived', 'sel' => $archived ? 'active' : '', 'title' => t('Only show archived connections')), 'hidden' => array('label' => t('Hidden'), 'url' => z_root() . '/connections/hidden', 'sel' => $hidden ? 'active' : '', 'title' => t('Only show hidden connections'))); //$tab_tpl = get_markup_template('common_tabs.tpl'); //$t = replace_macros($tab_tpl, array('$tabs'=>$tabs)); $searching = false; if ($search) { $search_hdr = $search; $search_txt = dbesc(protect_sprintf(preg_quote($search))); $searching = true; } $sql_extra .= $searching ? protect_sprintf(" AND xchan_name like '%{$search_txt}%' ") : ""; if ($_REQUEST['gid']) { $sql_extra .= " and xchan_hash in ( select xchan from group_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) "; } $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash \n\t\t\twhere abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 {$sql_extra} {$sql_extra2} ", intval(local_channel())); if ($r) { \App::set_pager_total($r[0]['total']); $total = $r[0]['total']; } $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash\n\t\t\tWHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 {$sql_extra} {$sql_extra2} ORDER BY xchan_name LIMIT %d OFFSET %d ", intval(local_channel()), intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); $contacts = array(); if (count($r)) { foreach ($r as $rr) { if ($rr['xchan_url']) { $status_str = ''; $status = array(intval($rr['abook_pending']) ? t('Pending approval') : '', intval($rr['abook_archived']) ? t('Archived') : '', intval($rr['abook_hidden']) ? t('Hidden') : '', intval($rr['abook_ignored']) ? t('Ignored') : '', intval($rr['abook_blocked']) ? t('Blocked') : ''); foreach ($status as $str) { if (!$str) { continue; } $status_str .= $str; $status_str .= ', '; } $status_str = rtrim($status_str, ', '); $contacts[] = array('img_hover' => sprintf(t('%1$s [%2$s]'), $rr['xchan_name'], $rr['xchan_url']), 'edit_hover' => t('Edit connection'), 'delete_hover' => t('Delete connection'), 'id' => $rr['abook_id'], 'thumb' => $rr['xchan_photo_m'], 'name' => $rr['xchan_name'], 'classes' => intval($rr['abook_archived']) ? 'archived' : '', 'link' => z_root() . '/connedit/' . $rr['abook_id'], 'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop', 'delete' => t('Delete'), 'url' => chanlink_url($rr['xchan_url']), 'webbie_label' => t('Channel address'), 'webbie' => $rr['xchan_addr'], 'network_label' => t('Network'), 'network' => network_to_name($rr['xchan_network']), 'public_forum' => intval($rr['xchan_pubforum']) ? true : false, 'status_label' => t('Status'), 'status' => $status_str, 'connected_label' => t('Connected'), 'connected' => datetime_convert('UTC', date_default_timezone_get(), $rr['abook_created'], 'c'), 'approve_hover' => t('Approve connection'), 'approve' => $rr['abook_pending'] ? t('Approve') : false, 'ignore_hover' => t('Ignore connection'), 'ignore' => !$rr['abook_ignored'] ? t('Ignore') : false, 'recent_label' => t('Recent activity'), 'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id'])); } } } if ($_REQUEST['aj']) { if ($contacts) { $o = replace_macros(get_markup_template('contactsajax.tpl'), array('$contacts' => $contacts, '$edit' => t('Edit'))); } else { $o = '<div id="content-complete"></div>'; } echo $o; killme(); } else { $o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>"; $o .= replace_macros(get_markup_template('connections.tpl'), array('$header' => t('Connections') . ($head ? ': ' . $head : ''), '$tabs' => $tabs, '$total' => $total, '$search' => $search_hdr, '$label' => t('Search'), '$desc' => t('Search your connections'), '$finding' => $searching ? t('Connections search') . ": '" . $search . "'" : "", '$submit' => t('Find'), '$edit' => t('Edit'), '$cmd' => \App::$cmd, '$contacts' => $contacts, '$paginate' => paginate($a))); } if (!$contacts) { $o .= '<div id="content-complete"></div>'; } return $o; }
function mail_post(&$a) { if (!local_channel()) { return; } $replyto = x($_REQUEST, 'replyto') ? notags(trim($_REQUEST['replyto'])) : ''; $subject = x($_REQUEST, 'subject') ? notags(trim($_REQUEST['subject'])) : ''; $body = x($_REQUEST, 'body') ? escape_tags(trim($_REQUEST['body'])) : ''; $recipient = x($_REQUEST, 'messageto') ? notags(trim($_REQUEST['messageto'])) : ''; $rstr = x($_REQUEST, 'messagerecip') ? notags(trim($_REQUEST['messagerecip'])) : ''; $preview = x($_REQUEST, 'preview') ? intval($_REQUEST['preview']) : 0; $expires = x($_REQUEST, 'expires') ? datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['expires']) : NULL_DATE; // If we have a raw string for a recipient which hasn't been auto-filled, // it means they probably aren't in our address book, hence we don't know // if we have permission to send them private messages. // finger them and find out before we try and send it. if (!$recipient) { $channel = App::get_channel(); $ret = zot_finger($rstr, $channel); if (!$ret['success']) { notice(t('Unable to lookup recipient.') . EOL); return; } $j = json_decode($ret['body'], true); logger('message_post: lookup: ' . $url . ' ' . print_r($j, true)); if (!($j['success'] && $j['guid'])) { notice(t('Unable to communicate with requested channel.')); return; } $x = import_xchan($j); if (!$x['success']) { notice(t('Cannot verify requested channel.')); return; } $recipient = $x['hash']; $their_perms = 0; $global_perms = get_perms(); if ($j['permissions']['data']) { $permissions = crypto_unencapsulate($j['permissions'], $channel['channel_prvkey']); if ($permissions) { $permissions = json_decode($permissions); } logger('decrypted permissions: ' . print_r($permissions, true), LOGGER_DATA); } else { $permissions = $j['permissions']; } foreach ($permissions as $k => $v) { if ($v) { $their_perms = $their_perms | intval($global_perms[$k][1]); } } if (!($their_perms & PERMS_W_MAIL)) { notice(t('Selected channel has private message restrictions. Send failed.')); // reported issue: let's still save the message and continue. We'll just tell them // that nothing useful is likely to happen. They might have spent hours on it. // return; } } // if(feature_enabled(local_channel(),'richtext')) { // $body = fix_mce_lf($body); // } require_once 'include/text.php'; linkify_tags($a, $body, local_channel()); if ($preview) { } if (!$recipient) { notice('No recipient found.'); App::$argc = 2; App::$argv[1] = 'new'; return; } // We have a local_channel, let send_message use the session channel and save a lookup $ret = send_message(0, $recipient, $body, $subject, $replyto, $expires); if ($ret['success']) { xchan_mail_query($ret['mail']); build_sync_packet(0, array('conv' => array($ret['conv']), 'mail' => array(encode_mail($ret['mail'], true)))); } else { notice($ret['message']); } goaway(z_root() . '/mail/combined'); }
function api_call() { $p = App::$cmd; $type = null; if (strrpos($p, '.')) { $type = substr($p, strrpos($p, '.') + 1); if (strpos($type, '/') === false) { $p = substr($p, 0, strrpos($p, '.')); // recalculate App argc,argv since we just extracted the type from it App::$argv = explode('/', $p); App::$argc = count(App::$argv); } } if (!$type || !in_array($type, ['json', 'xml', 'rss', 'as', 'atom'])) { $type = 'json'; } $info = \Zotlabs\Lib\Api_router::find($p); logger('info: ' . $p . ' type: ' . $type . ' ' . print_r($info, true)); if ($info) { if ($info['auth'] === true && api_user() === false) { api_login($a); } load_contact_links(api_user()); $channel = App::get_channel(); logger('API call for ' . $channel['channel_name'] . ': ' . App::$query_string); logger('API parameters: ' . print_r($_REQUEST, true)); $r = call_user_func($info['func'], $type); if ($r === false) { return; } switch ($type) { case "xml": $r = mb_convert_encoding($r, "UTF-8", mb_detect_encoding($r)); header("Content-Type: text/xml"); return '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $r; break; case "json": header("Content-Type: application/json"); if ($r) { foreach ($r as $rv) { $json = json_encode($rv); } } // Lookup JSONP to understand these lines. They provide cross-domain AJAX ability. if ($_GET['callback']) { $json = $_GET['callback'] . '(' . $json . ')'; } return $json; break; case "rss": header("Content-Type: application/rss+xml"); return '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $r; break; case "atom": header("Content-Type: application/atom+xml"); return '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $r; break; case "as": if ($r) { foreach ($r as $rv) { $json = json_encode($rv); } } return $json; break; } } header("HTTP/1.1 404 Not Found"); logger('API call not implemented: ' . App::$query_string . ' - ' . print_r($_REQUEST, true)); $r = '<status><error>not implemented</error></status>'; switch ($type) { case "xml": header("Content-Type: text/xml"); return '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $r; break; case "json": header("Content-Type: application/json"); return json_encode(array('error' => 'not implemented')); break; case "rss": header("Content-Type: application/rss+xml"); return '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $r; break; case "atom": header("Content-Type: application/atom+xml"); return '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $r; break; } }