diff options
Diffstat (limited to 'mod')
61 files changed, 2323 insertions, 1388 deletions
diff --git a/mod/acl.php b/mod/acl.php index 4b63cd239..ba2159dbc 100644 --- a/mod/acl.php +++ b/mod/acl.php @@ -98,6 +98,7 @@ function acl_init(&$a){ intval(local_channel()), intval(ABOOK_FLAG_BLOCKED|ABOOK_FLAG_PENDING|ABOOK_FLAG_ARCHIVED) ); + } else { // Visitors $r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags @@ -146,11 +147,13 @@ function acl_init(&$a){ } } if(intval(get_config('system','taganyone')) || intval(get_pconfig(local_channel(),'system','taganyone'))) { - if((! $r) && $type == 'c') { - $r = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags + if((count($r) < 100) && $type == 'c') { + $r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags FROM xchan WHERE xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ); + if($r2) + $r = array_merge($r,$r2); } } } diff --git a/mod/admin.php b/mod/admin.php index 7e8199e68..7d0497a7b 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1,23 +1,25 @@ <?php - - /** - * Red admin - */ +/** + * @file mod/admin.php + * @brief RedMatrix's admin controller. + * + * Controller for the /admin/ area. + */ /** - * @param App $a + * @param App &$a */ function admin_post(&$a){ logger('admin_post', LOGGER_DEBUG); - if(!is_site_admin()) { + if(! is_site_admin()) { return; } // urls - if (argc() > 1){ - switch (argv(1)){ + if (argc() > 1) { + switch (argv(1)) { case 'site': admin_page_site_post($a); break; @@ -27,7 +29,6 @@ function admin_post(&$a){ case 'channels': admin_page_channels_post($a); break; - case 'plugins': if (argc() > 2 && is_file("addon/" . argv(2) . "/" . argv(2) . ".php")){ @@ -38,7 +39,6 @@ function admin_post(&$a){ } } goaway($a->get_baseurl(true) . '/admin/plugins/' . argv(2) ); - return; // NOTREACHED break; case 'themes': $theme = argv(2); @@ -51,10 +51,8 @@ function admin_post(&$a){ } info(t('Theme settings updated.')); if(is_ajax()) return; - - goaway($a->get_baseurl(true) . '/admin/themes/' . $theme ); - return; + goaway($a->get_baseurl(true) . '/admin/themes/' . $theme ); break; case 'logs': admin_page_logs_post($a); @@ -65,56 +63,57 @@ function admin_post(&$a){ case 'dbsync': admin_page_dbsync_post($a); break; - case 'profs': admin_page_profs_post($a); break; - } } goaway($a->get_baseurl(true) . '/admin' ); - return; // NOTREACHED } /** - * @param App $a + * @param App &$a * @return string */ function admin_content(&$a) { logger('admin_content', LOGGER_DEBUG); - if(!is_site_admin()) { + + if(! is_site_admin()) { return login(false); } - /** + /* * Side bar links */ // array( url, name, extra css classes ) - $aside = Array( - 'site' => Array($a->get_baseurl(true)."/admin/site/", t("Site") , "site"), - 'users' => Array($a->get_baseurl(true)."/admin/users/", t("Accounts") , "users"), - 'channels' => Array($a->get_baseurl(true)."/admin/channels/", t("Channels") , "channels"), - 'plugins' => Array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"), - 'themes' => Array($a->get_baseurl(true)."/admin/themes/", t("Themes") , "themes"), -// 'hubloc' => Array($a->get_baseurl(true)."/admin/hubloc/", t("Server") , "server"), - 'profs' => array(z_root() . '/admin/profs', t('Profile Config'), 'profs'), - 'dbsync' => Array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync") + + $aside = array( + 'site' => array($a->get_baseurl(true)."/admin/site/", t("Site") , "site"), + 'users' => array($a->get_baseurl(true)."/admin/users/", t("Accounts") , "users"), + 'channels' => array($a->get_baseurl(true)."/admin/channels/", t("Channels") , "channels"), + 'plugins' => array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"), + 'themes' => array($a->get_baseurl(true)."/admin/themes/", t("Themes") , "themes"), + 'queue' => array(z_root() . '/admin/queue', t('Inspect queue'), 'queue'), +// 'hubloc' => array($a->get_baseurl(true)."/admin/hubloc/", t("Server") , "server"), + 'profs' => array(z_root() . '/admin/profs', t('Profile Config'), 'profs'), + 'dbsync' => array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync") + ); - + /* get plugins admin page */ - - $r = q("SELECT * FROM `addon` WHERE `plugin_admin`=1"); - $aside['plugins_admin']=Array(); + + $r = q("SELECT * FROM addon WHERE plugin_admin = 1"); + $aside['plugins_admin'] = array(); foreach ($r as $h){ - $plugin =$h['name']; - $aside['plugins_admin'][] = Array($a->get_baseurl(true)."/admin/plugins/".$plugin, $plugin, "plugin"); + $plugin = $h['name']; + $aside['plugins_admin'][] = array($a->get_baseurl(true) . '/admin/plugins/' . $plugin, $plugin, 'plugin'); // temp plugins with admin $a->plugins_admin[] = $plugin; } - + $aside['logs'] = Array($a->get_baseurl(true)."/admin/logs/", t("Logs"), "logs"); $t = get_markup_template("admin_aside.tpl"); @@ -128,12 +127,11 @@ function admin_content(&$a) { )); - - /** + /* * Page content */ $o = ''; - + // urls if (argc() > 1){ switch (argv(1)) { @@ -164,13 +162,16 @@ function admin_content(&$a) { case 'profs': $o = admin_page_profs($a); break; + case 'queue': + $o = admin_page_queue($a); + break; default: - notice( t("Item not found.") ); + notice( t('Item not found.') ); } } else { $o = admin_page_summary($a); } - + if(is_ajax()) { echo $o; killme(); @@ -178,59 +179,91 @@ function admin_content(&$a) { } else { return $o; } -} +} /** - * Admin Summary Page - * @param App $a - * @return string + * @brief Returns content for Admin Summary Page. + * + * @param App &$a + * @return string HTML from parsed admin_summary.tpl */ function admin_page_summary(&$a) { - // list total user accounts, expirations etc. + $accounts = array(); + $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires != '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account", + db_utcnow(), + db_utcnow(), + dbesc(NULL_DATE), + intval(ACCOUNT_BLOCKED) + ); + if ($r) { + $accounts['total'] = array('label' => t('# Accounts'), 'val' => $r[0]['total']); + $accounts['blocked'] = array('label' => t('# blocked accounts'), 'val' => $r[0]['blocked']); + $accounts['expired'] = array('label' => t('# expired accounts'), 'val' => $r[0]['expired']); + $accounts['expiring'] = array('label' => t('# expiring accounts'), 'val' => $r[0]['expiring']); + } - - $r = q("SELECT COUNT(account_id) as total FROM `account`"); - $users = $r[0]['total']; - - $r = q("SELECT COUNT(id) as `count` FROM `register`"); + // pending registrations + $r = q("SELECT COUNT(id) AS `count` FROM register"); $pending = $r[0]['count']; - $r = q("select count(*) as total from outq"); - $queue = (($r) ? $r[0]['total'] : 0); + // available channels, primary and clones + $channels = array(); + $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE NOT (channel_pageflags & %d)>0", + intval(PAGE_REMOVED) + ); + if ($r) { + $channels['total'] = array('label' => t('# Channels'), 'val' => $r[0]['total']); + $channels['main'] = array('label' => t('# primary'), 'val' => $r[0]['main']); + $channels['clones'] = array('label' => t('# clones'), 'val' => $r[0]['clones']); + } // We can do better, but this is a quick queue status - + $r = q("SELECT COUNT(outq_delivered) AS total FROM outq WHERE outq_delivered = 0"); + $queue = (($r) ? $r[0]['total'] : 0); $queues = array( 'label' => t('Message queues'), 'queue' => $queue ); + // If no plugins active return 0, otherwise list of plugin names + $plugins = (count($a->plugins) == 0) ? count($a->plugins) : $a->plugins; + + // Could be extended to provide also other alerts to the admin + $alertmsg = ''; + // annoy admin about upcoming unsupported PHP version + if (version_compare(PHP_VERSION, '5.4', '<')) { + $alertmsg = 'Your PHP version ' . PHP_VERSION . ' will not be supported with the next major release of RedMatrix. You are strongly urged to upgrade to a current version.' + . '<br>PHP 5.3 has reached its <a href="http://php.net/eol.php" class="alert-link">End of Life (EOL)</a> in August 2014.' + . ' A list about current PHP versions can be found <a href="http://php.net/supported-versions.php" class="alert-link">here</a>.'; + } - $t = get_markup_template("admin_summary.tpl"); + $t = get_markup_template('admin_summary.tpl'); return replace_macros($t, array( '$title' => t('Administration'), '$page' => t('Summary'), + '$adminalertmsg' => $alertmsg, '$queues' => $queues, - '$users' => Array( t('Registered users'), $users), - '$accounts' => $accounts, - '$pending' => Array( t('Pending registrations'), $pending), - '$version' => Array( t('Version'), RED_VERSION), - '$build' => get_config('system','db_version'), - '$plugins' => Array( t('Active plugins'), $a->plugins ) + '$accounts' => array( t('Registered accounts'), $accounts), + '$pending' => array( t('Pending registrations'), $pending), + '$channels' => array( t('Registered channels'), $channels), + '$plugins' => array( t('Active plugins'), $plugins ), + '$version' => array( t('Version'), RED_VERSION), + '$build' => get_config('system', 'db_version') )); } /** - * Admin Site Page - * @param App $a + * @brief POST handler for Admin Site Page. + * + * @param App &$a */ function admin_page_site_post(&$a){ - if (!x($_POST,"page_site")){ + if (!x($_POST, 'page_site')){ return; } - check_form_security_token_redirectOnErr('/admin/site', 'admin_site'); + check_form_security_token_redirectOnErr('/admin/site', 'admin_site'); $sitename = ((x($_POST,'sitename')) ? notags(trim($_POST['sitename'])) : ''); $banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false); @@ -240,69 +273,68 @@ function admin_page_site_post(&$a){ $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : ''); // $site_channel = ((x($_POST,'site_channel')) ? notags(trim($_POST['site_channel'])) : ''); $maximagesize = ((x($_POST,'maximagesize')) ? intval(trim($_POST['maximagesize'])) : 0); - - + $register_policy = ((x($_POST,'register_policy')) ? intval(trim($_POST['register_policy'])) : 0); $access_policy = ((x($_POST,'access_policy')) ? intval(trim($_POST['access_policy'])) : 0); $abandon_days = ((x($_POST,'abandon_days')) ? intval(trim($_POST['abandon_days'])) : 0); - $register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : ''); - - $allowed_sites = ((x($_POST,'allowed_sites')) ? notags(trim($_POST['allowed_sites'])) : ''); - $allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : ''); - $not_allowed_email = ((x($_POST,'not_allowed_email')) ? notags(trim($_POST['not_allowed_email'])) : ''); - $block_public = ((x($_POST,'block_public')) ? True : False); - $force_publish = ((x($_POST,'publish_all')) ? True : False); - $disable_discover_tab = ((x($_POST,'disable_discover_tab')) ? True : False); - $no_login_on_homepage = ((x($_POST,'no_login_on_homepage')) ? True : False); - $global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : ''); - $no_community_page = !((x($_POST,'no_community_page')) ? True : False); - - $verifyssl = ((x($_POST,'verifyssl')) ? True : False); - $proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : ''); - $proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : ''); - $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60); - $delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0); - $poll_interval = ((x($_POST,'poll_interval'))? intval(trim($_POST['poll_interval'])) : 0); - $maxloadavg = ((x($_POST,'maxloadavg'))? intval(trim($_POST['maxloadavg'])) : 50); - $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0); - $diaspora_enabled = ((x($_POST,'diaspora_enabled')) ? intval($_POST['diaspora_enabled']) : 0); - $verify_email = ((x($_POST,'verify_email')) ? 1 : 0); - - set_config('system','feed_contacts',$feed_contacts); - set_config('system','diaspora_enabled',$diaspora_enabled); - set_config('system','delivery_interval',$delivery_interval); - set_config('system','poll_interval',$poll_interval); - set_config('system','maxloadavg',$maxloadavg); - set_config('system','sitename',$sitename); - set_config('system','no_login_on_homepage',$no_login_on_homepage); - set_config('system','verify_email',$verify_email); - - if ($banner=="") { - del_config('system','banner'); - } - else { - set_config('system','banner', $banner); + $register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : ''); + + $allowed_sites = ((x($_POST,'allowed_sites')) ? notags(trim($_POST['allowed_sites'])) : ''); + $allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : ''); + $not_allowed_email = ((x($_POST,'not_allowed_email')) ? notags(trim($_POST['not_allowed_email'])) : ''); + $block_public = ((x($_POST,'block_public')) ? True : False); + $force_publish = ((x($_POST,'publish_all')) ? True : False); + $disable_discover_tab = ((x($_POST,'disable_discover_tab')) ? True : False); + $no_login_on_homepage = ((x($_POST,'no_login_on_homepage')) ? True : False); + $global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : ''); + $no_community_page = !((x($_POST,'no_community_page')) ? True : False); + $default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0); + + $verifyssl = ((x($_POST,'verifyssl')) ? True : False); + $proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : ''); + $proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : ''); + $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60); + $delivery_interval = ((x($_POST,'delivery_interval'))? intval(trim($_POST['delivery_interval'])) : 0); + $poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0); + $maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50); + $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0); + $diaspora_enabled = ((x($_POST,'diaspora_enabled')) ? intval($_POST['diaspora_enabled']) : 0); + $verify_email = ((x($_POST,'verify_email')) ? 1 : 0); + + set_config('system', 'feed_contacts', $feed_contacts); + set_config('system', 'diaspora_enabled', $diaspora_enabled); + set_config('system', 'delivery_interval', $delivery_interval); + set_config('system', 'poll_interval', $poll_interval); + set_config('system', 'maxloadavg', $maxloadavg); + set_config('system', 'sitename', $sitename); + set_config('system', 'no_login_on_homepage', $no_login_on_homepage); + set_config('system', 'verify_email', $verify_email); + set_config('system', 'default_expire_days', $default_expire_days); + + if ($banner == '') { + del_config('system', 'banner'); + } else { + set_config('system', 'banner', $banner); } - if ($admininfo==''){ - del_config('system','admininfo'); - } - else { + if ($admininfo == ''){ + del_config('system', 'admininfo'); + } else { require_once('include/text.php'); linkify_tags($a, $admininfo, local_channel()); - set_config('system','admininfo', $admininfo); + set_config('system', 'admininfo', $admininfo); } - set_config('system','language', $language); - set_config('system','theme', $theme); + set_config('system', 'language', $language); + set_config('system', 'theme', $theme); if ( $theme_mobile === '---' ) { - del_config('system','mobile_theme'); + del_config('system', 'mobile_theme'); } else { - set_config('system','mobile_theme', $theme_mobile); - } + set_config('system', 'mobile_theme', $theme_mobile); + } // set_config('system','site_channel', $site_channel); set_config('system','maximagesize', $maximagesize); - + set_config('system','register_policy', $register_policy); set_config('system','access_policy', $access_policy); set_config('system','account_abandon_days', $abandon_days); @@ -313,11 +345,10 @@ function admin_page_site_post(&$a){ set_config('system','block_public', $block_public); set_config('system','publish_all', $force_publish); set_config('system','disable_discover_tab', $disable_discover_tab); - if($global_directory=="") { - del_config('system','directory_submit_url'); - } - else { - set_config('system','directory_submit_url', $global_directory); + if ($global_directory == '') { + del_config('system', 'directory_submit_url'); + } else { + set_config('system', 'directory_submit_url', $global_directory); } set_config('system','no_community_page', $no_community_page); @@ -329,20 +360,20 @@ function admin_page_site_post(&$a){ info( t('Site settings updated.') . EOL); goaway($a->get_baseurl(true) . '/admin/site' ); - return; // NOTREACHED - } /** + * @brief Admin page site. + * * @param App $a * @return string */ function admin_page_site(&$a) { - + /* Installed langs */ $lang_choices = array(); $langs = glob('view/*/strings.php'); - + if(is_array($langs) && count($langs)) { if(! in_array('view/en/strings.php',$langs)) $langs[] = 'view/en/'; @@ -354,17 +385,17 @@ function admin_page_site(&$a) { } /* Installed themes */ - $theme_choices_mobile["---"] = t("Default"); - $theme_choices = array(); - $files = glob('view/theme/*'); - if($files) { - foreach($files as $file) { - $vars = ''; - $f = basename($file); - if (file_exists($file . '/library')) - continue; - if (file_exists($file . '/mobile')) - $vars = t('mobile'); + $theme_choices_mobile["---"] = t("Default"); + $theme_choices = array(); + $files = glob('view/theme/*'); + if($files) { + foreach($files as $file) { + $vars = ''; + $f = basename($file); + if (file_exists($file . '/library')) + continue; + if (file_exists($file . '/mobile')) + $vars = t('mobile'); if (file_exists($file . '/experimental')) $vars .= t('experimental'); if (file_exists($file . '/unsupported')) @@ -372,29 +403,30 @@ function admin_page_site(&$a) { if ($vars) { $theme_choices[$f] = $f . ' (' . $vars . ')'; $theme_choices_mobile[$f] = $f . ' (' . $vars . ')'; - } + } else { - $theme_choices[$f] = $f; - $theme_choices_mobile[$f] = $f; - } - } - } + $theme_choices[$f] = $f; + $theme_choices_mobile[$f] = $f; + } + } + } /* Banner */ - $banner = get_config('system','banner'); + $banner = get_config('system', 'banner'); if($banner == false) $banner = 'red'; + $banner = htmlspecialchars($banner); - + /* Admin Info */ - $admininfo = get_config('system','admininfo'); + $admininfo = get_config('system', 'admininfo'); /* Register policy */ $register_choices = Array( REGISTER_CLOSED => t("No"), REGISTER_APPROVE => t("Yes - with approval"), REGISTER_OPEN => t("Yes") - ); + ); /* Acess policy */ $access_choices = Array( @@ -403,7 +435,7 @@ function admin_page_site(&$a) { ACCESS_FREE => t("My site has free access only"), ACCESS_TIERED => t("My site offers free accounts with optional paid upgrades") ); - + // $ssl_choices = array( // SSL_POLICY_NONE => t("No SSL policy, links will track page SSL state"), // SSL_POLICY_FULL => t("Force all links to use SSL") @@ -418,9 +450,9 @@ function admin_page_site(&$a) { '$upload' => t('File upload'), '$corporate' => t('Policies'), '$advanced' => t('Advanced'), - + '$baseurl' => $a->get_baseurl(true), - // name, label, value, help string, extra data... + // name, label, value, help string, extra data... '$sitename' => array('sitename', t("Site name"), htmlspecialchars(get_config('system','sitename'), ENT_QUOTES, 'UTF-8'),''), '$banner' => array('banner', t("Banner/Logo"), $banner, ""), '$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")), @@ -443,18 +475,18 @@ function admin_page_site(&$a) { '$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")), '$disable_discover_tab' => array('disable_discover_tab', t("Disable discovery tab"), get_config('system','disable_discover_tab'), t("Remove the tab in the network view with public content pulled from sources chosen for this site.")), '$no_login_on_homepage' => array('no_login_on_homepage', t("No login on Homepage"), get_config('system','no_login_on_homepage'), t("Check to hide the login form from your sites homepage when visitors arrive who are not logged in (e.g. when you put the content of the homepage in via the site channel).")), - + '$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""), '$proxy' => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""), '$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")), '$delivery_interval' => array('delivery_interval', t("Delivery interval"), (x(get_config('system','delivery_interval'))?get_config('system','delivery_interval'):2), t("Delay background delivery processes by this many seconds to reduce system load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 for large dedicated servers.")), '$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")), '$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")), - '$form_security_token' => get_form_security_token("admin_site"), - + '$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (matrix/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')), + '$form_security_token' => get_form_security_token("admin_site"), )); - } + function admin_page_hubloc_post(&$a){ check_form_security_token_redirectOnErr('/admin/hubloc', 'admin_hubloc'); require_once('include/zot.php'); @@ -467,10 +499,10 @@ function admin_page_hubloc_post(&$a){ intval($hublocid) ); $hublocurl = $arrhublocurl[0]['hubloc_url'] . '/post'; - + //perform ping $m = zot_build_packet($a->get_channel(),'ping'); - $r = zot_zot($hublocurl,$m); + $r = zot_zot($hublocurl,$m); //handle results and set the hubloc flags in db to make results visible $r2 = $r['body']; $r3 = $r2['success']; @@ -480,53 +512,44 @@ function admin_page_hubloc_post(&$a){ } else { //set HUBLOC_OFFLINE to 1 logger(' success = false ', LOGGER_DEBUG); - } - + //unfotunatly zping wont work, I guess return format is not correct - //require_once('mod/zping.php'); - //$r = zping_content($hublocurl); - //logger('zping answer: ' . $r, LOGGER_DEBUG); - + //require_once('mod/zping.php'); + //$r = zping_content($hublocurl); + //logger('zping answer: ' . $r, LOGGER_DEBUG); //in case of repair store new pub key for tested hubloc (all channel with this hubloc) in db //after repair set hubloc flags to 0 - } - goaway($a->get_baseurl(true) . '/admin/hubloc' ); - return; } function admin_page_hubloc(&$a) { - $o = ''; $hubloc = q("SELECT hubloc_id, hubloc_addr, hubloc_host, hubloc_status FROM hubloc"); - if(! $hubloc){ notice( t('No server found') . EOL); goaway($a->get_baseurl(true) . '/admin/hubloc'); } - $t = get_markup_template("admin_hubloc.tpl"); - return replace_macros($t, array( + $t = get_markup_template('admin_hubloc.tpl'); + return replace_macros($t, array( '$hubloc' => $hubloc, '$th_hubloc' => array(t('ID'), t('for channel'), t('on server'), t('Status')), - '$title' => t('Administration'), - '$page' => t('Server'), - '$queues' => $queues, - //'$accounts' => $accounts, /*$accounts is empty here*/ - '$pending' => Array( t('Pending registrations'), $pending), - '$plugins' => Array( t('Active plugins'), $a->plugins ), - '$form_security_token' => get_form_security_token("admin_hubloc") - )); - return $o; + '$title' => t('Administration'), + '$page' => t('Server'), + '$queues' => $queues, + //'$accounts' => $accounts, /*$accounts is empty here*/ + '$pending' => array( t('Pending registrations'), $pending), + '$plugins' => array( t('Active plugins'), $a->plugins ), + '$form_security_token' => get_form_security_token('admin_hubloc') + )); } function admin_page_dbsync(&$a) { - $o = ''; if(argc() > 3 && intval(argv(3)) && argv(2) === 'mark') { @@ -546,7 +569,7 @@ function admin_page_dbsync(&$a) { $o .= sprintf( t('Executing %s failed. Check system logs.'), $func); } elseif($retval === UPDATE_SUCCESS) { - $o .= sprintf( t('Update %s was successfully applied.', $func)); + $o .= sprintf( t('Update %s was successfully applied.'), $func); set_config('database',$func, 'success'); } else @@ -554,6 +577,7 @@ function admin_page_dbsync(&$a) { } else $o .= sprintf( t('Update function %s could not be found.'), $func); + return $o; } @@ -577,132 +601,193 @@ function admin_page_dbsync(&$a) { '$mark' => t('Mark success (if update was manually applied)'), '$apply' => t('Attempt to execute this update step automatically'), '$failed' => $failed - )); + )); return $o; +} + +function admin_page_queue($a) { + $o = ''; + + $expert = ((array_key_exists('expert',$_REQUEST)) ? intval($_REQUEST['expert']) : 0); + + if($_REQUEST['drophub']) { + require_once('hubloc.php'); + hubloc_mark_as_down($_REQUEST['drophub']); + } + if($_REQUEST['emptyhub']) { + $r = q("delete from outq where outq_posturl = '%s' ", + dbesc($_REQUEST['emptyhub']) + ); + } + + $r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq + where outq_delivered = 0 group by outq_posturl order by total desc"); + + for($x = 0; $x < count($r); $x ++) { + $r[$x]['eurl'] = urlencode($r[$x]['outq_posturl']); + $r[$x]['connected'] = datetime_convert('UTC',date_default_timezone_get(),$r[$x]['connected'],'Y-m-d'); + } + + $o = replace_macros(get_markup_template('admin_queue.tpl'), array( + '$banner' => t('Queue Statistics'), + '$numentries' => t('Total Entries'), + '$priority' => t('Priority'), + '$desturl' => t('Destination URL'), + '$nukehub' => t('Mark hub permanently offline'), + '$empty' => t('Empty queue for this hub'), + '$lastconn' => t('Last known contact'), + '$hasentries' => ((count($r)) ? true : false), + '$entries' => $r, + '$expert' => $expert + )); + + return $o; } /** - * Users admin page + * @brief Handle POST actions on users admin page. + * + * This function is called when on the admin user/account page the form was + * submitted to handle multiple operations at once. If one of the icons next + * to an entry are pressed the function admin_page_users() will handle this. * * @param App $a */ -function admin_page_users_post(&$a){ - $pending = ( x($_POST, 'pending') ? $_POST['pending'] : Array() ); - $users = ( x($_POST, 'user') ? $_POST['user'] : Array() ); - - check_form_security_token_redirectOnErr('/admin/users', 'admin_users'); - - if (x($_POST,'page_users_block')){ - foreach($users as $uid){ - q("UPDATE account SET account_flags = (account_flags & %d) where account_id = %d", +function admin_page_users_post($a) { + $pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() ); + $users = ( x($_POST, 'user') ? $_POST['user'] : array() ); + $blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() ); + + check_form_security_token_redirectOnErr('/admin/users', 'admin_users'); + + // change to switch structure? + // account block/unblock button was submitted + if (x($_POST, 'page_users_block')) { + for ($i = 0; $i < count($users); $i++) { + // if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag + $op = ($blocked[$i]) ? '& ~' : '| '; + q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d", intval(ACCOUNT_BLOCKED), - intval( $uid ) + intval($users[$i]) ); } notice( sprintf( tt("%s user blocked/unblocked", "%s users blocked/unblocked", count($users)), count($users)) ); } - if (x($_POST,'page_users_delete')){ - require_once("include/Contact.php"); - foreach($users as $uid){ - account_remove($uid,true,false); + // account delete button was submitted + if (x($_POST, 'page_users_delete')) { + require_once('include/Contact.php'); + foreach ($users as $uid){ + account_remove($uid, true, false); } notice( sprintf( tt("%s user deleted", "%s users deleted", count($users)), count($users)) ); } - - if (x($_POST,'page_users_approve')){ - foreach($pending as $hash){ + // registration approved button was submitted + if (x($_POST, 'page_users_approve')) { + foreach ($pending as $hash) { user_allow($hash); } } - if (x($_POST,'page_users_deny')){ - foreach($pending as $hash){ + // registration deny button was submitted + if (x($_POST, 'page_users_deny')) { + foreach ($pending as $hash) { user_deny($hash); } } + goaway($a->get_baseurl(true) . '/admin/users' ); - return; // NOTREACHED } /** - * @param App $a + * @brief Generate users admin page and handle single item operations. + * + * This function generates the users/account admin page and handles the actions + * if an icon next to an entry was clicked. If several items were selected and + * the form was submitted it is handled by the function admin_page_users_post(). + * + * @param App &$a * @return string */ function admin_page_users(&$a){ if (argc() > 2) { $uid = argv(3); - $account = q("SELECT * FROM account WHERE account_id = %d", + $account = q("SELECT * FROM account WHERE account_id = %d", intval($uid) ); if (! $account) { notice( t('Account not found') . EOL); goaway($a->get_baseurl(true) . '/admin/users' ); - } + } - switch(argv(2)){ - case "delete":{ - check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); + check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); + + switch (argv(2)){ + case 'delete': // delete user - require_once("include/Contact.php"); + require_once('include/Contact.php'); account_remove($uid,true,false); - + notice( sprintf(t("User '%s' deleted"), $account[0]['account_email']) . EOL); - }; break; - case "block":{ - check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); - q("UPDATE account SET account_flags = ( account_flags & ~%d ) where account_id = %d", + break; + case 'block': + q("UPDATE account SET account_flags = ( account_flags | %d ) WHERE account_id = %d", intval(ACCOUNT_BLOCKED), - intval( $uid ) + intval($uid) ); - notice( sprintf( (($account[0]['account_flags'] & ACCOUNT_BLOCKED) ? t("User '%s' unblocked"):t("User '%s' blocked")) , $account[0]['account_email']) . EOL); - }; break; + notice( sprintf( t("User '%s' blocked") , $account[0]['account_email']) . EOL); + break; + case 'unblock': + q("UPDATE account SET account_flags = ( account_flags & ~%d ) WHERE account_id = %d", + intval(ACCOUNT_BLOCKED), + intval($uid) + ); + + notice( sprintf( t("User '%s' unblocked"), $account[0]['account_email']) . EOL); + break; } + goaway($a->get_baseurl(true) . '/admin/users' ); - return ''; // NOTREACHED - } - + /* get pending */ $pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d )>0 ", intval(ACCOUNT_PENDING) - ); - + ); + /* get users */ $total = q("SELECT count(*) as total FROM account"); - if(count($total)) { + if (count($total)) { $a->set_pager_total($total[0]['total']); $a->set_pager_itemspage(100); } - -// WEe'll still need to link email addresses to admin/users/channels or some such, but this bit doesn't exist yet. -// That's where we need to be doing last post/channel flags/etc, not here. +// We'll still need to link email addresses to admin/users/channels or some such, but this bit doesn't exist yet. +// That's where we need to be doing last post/channel flags/etc, not here. $serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : ''); - $order = " order by account_email asc "; if($_REQUEST['order'] === 'expires') $order = " order by account_expires desc "; - if($_REQUEST['order'] === 'created') + if($_REQUEST['order'] === 'created') $order = " order by account_created desc "; - - $users =q("SELECT `account_id` , `account_email`, `account_lastlog`, `account_created`, `account_expires`, " . "`account_service_class`, ( account_flags & %d )>0 as `blocked`, " . + + $users = q("SELECT `account_id` , `account_email`, `account_lastlog`, `account_created`, `account_expires`, " . "`account_service_class`, ( account_flags & %d )>0 as `blocked`, " . "(SELECT %s FROM channel as ch " . "WHERE ch.channel_account_id = ac.account_id and not (ch.channel_pageflags & %d )>0) as `channels` " . "FROM account as ac where true $serviceclass $order limit %d offset %d ", intval(ACCOUNT_BLOCKED), db_concat('ch.channel_address', ' '), - intval(PAGE_REMOVED), + intval(PAGE_REMOVED), intval($a->pager['itemspage']), intval($a->pager['start']) ); - + // function _setup_users($e){ // $accounts = Array( // t('Normal Account'), @@ -718,9 +803,8 @@ function admin_page_users(&$a){ // return $e; // } // $users = array_map("_setup_users", $users); - - - $t = get_markup_template("admin_users.tpl"); + + $t = get_markup_template('admin_users.tpl'); $o = replace_macros($t, array( // strings // '$title' => t('Administration'), @@ -742,7 +826,7 @@ function admin_page_users(&$a){ '$confirm_delete_multi' => t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'), '$confirm_delete' => t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'), - '$form_security_token' => get_form_security_token("admin_users"), + '$form_security_token' => get_form_security_token("admin_users"), // values // '$baseurl' => $a->get_baseurl(true), @@ -751,16 +835,17 @@ function admin_page_users(&$a){ '$users' => $users, )); $o .= paginate($a); + return $o; } /** - * Channels admin page + * @brief Channels admin page. * - * @param App $a + * @param App &$a */ -function admin_page_channels_post(&$a){ +function admin_page_channels_post(&$a) { $channels = ( x($_POST, 'channel') ? $_POST['channel'] : Array() ); check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels'); @@ -770,7 +855,7 @@ function admin_page_channels_post(&$a){ q("UPDATE channel SET channel_pageflags = ( channel_pageflags & ~%d ) where channel_id = %d", intval(PAGE_CENSORED), intval( $uid ) - ); + ); proc_run('php','include/directory.php',$uid,'nopush'); } notice( sprintf( tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)) ); @@ -784,28 +869,29 @@ function admin_page_channels_post(&$a){ } goaway($a->get_baseurl(true) . '/admin/channels' ); - return; // NOTREACHED } /** - * @param App $a + * @brief + * + * @param App &$a * @return string */ function admin_page_channels(&$a){ if (argc() > 2) { $uid = argv(3); - $channel = q("SELECT * FROM channel WHERE channel_id = %d", + $channel = q("SELECT * FROM channel WHERE channel_id = %d", intval($uid) ); if (! $channel) { notice( t('Channel not found') . EOL); goaway($a->get_baseurl(true) . '/admin/channels' ); - } + } - switch(argv(2)){ + switch(argv(2)) { case "delete":{ - check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't'); + check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't'); // delete channel require_once("include/Contact.php"); channel_remove($uid,true); @@ -825,10 +911,8 @@ function admin_page_channels(&$a){ }; break; } goaway($a->get_baseurl(true) . '/admin/channels' ); - return ''; // NOTREACHED - } - + /* get channels */ $total = q("SELECT count(*) as total FROM channel where not (channel_pageflags & %d)>0", @@ -838,7 +922,7 @@ function admin_page_channels(&$a){ $a->set_pager_total($total[0]['total']); $a->set_pager_itemspage(100); } - + $order = " order by channel_name asc "; $channels = q("SELECT * from channel where not ( channel_pageflags & %d )>0 $order limit %d offset %d ", @@ -846,7 +930,7 @@ function admin_page_channels(&$a){ intval($a->pager['itemspage']), intval($a->pager['start']) ); - + if($channels) { for($x = 0; $x < count($channels); $x ++) { if($channels[$x]['channel_pageflags'] & PAGE_CENSORED) @@ -855,7 +939,7 @@ function admin_page_channels(&$a){ $channels[$x]['blocked'] = false; } } - + $t = get_markup_template("admin_channels.tpl"); $o = replace_macros($t, array( // strings // @@ -873,13 +957,14 @@ function admin_page_channels(&$a){ '$confirm_delete_multi' => t('Selected channels will be deleted!\n\nEverything that was posted in these channels on this site will be permanently deleted!\n\nAre you sure?'), '$confirm_delete' => t('The channel {0} will be deleted!\n\nEverything that was posted in this channel on this site will be permanently deleted!\n\nAre you sure?'), - '$form_security_token' => get_form_security_token("admin_channels"), + '$form_security_token' => get_form_security_token("admin_channels"), // values // '$baseurl' => $a->get_baseurl(true), '$channels' => $channels, )); $o .= paginate($a); + return $o; } @@ -891,8 +976,8 @@ function admin_page_channels(&$a){ * @return string */ function admin_page_plugins(&$a){ - - /** + + /* * Single plugin */ if ($a->argc == 3){ @@ -901,9 +986,9 @@ function admin_page_plugins(&$a){ notice( t("Item not found.") ); return ''; } - + if (x($_GET,"a") && $_GET['a']=="t"){ - check_form_security_token_redirectOnErr('/admin/plugins', 'admin_themes', 't'); + check_form_security_token_redirectOnErr('/admin/plugins', 'admin_plugins', 't'); // Toggle plugin status $idx = array_search($plugin, $a->plugins); @@ -918,27 +1003,27 @@ function admin_page_plugins(&$a){ } set_config("system","addon", implode(", ",$a->plugins)); goaway($a->get_baseurl(true) . '/admin/plugins' ); - return ''; // NOTREACHED } // display plugin details require_once('library/markdown.php'); if (in_array($plugin, $a->plugins)){ - $status="on"; $action= t("Disable"); + $status = 'on'; + $action = t('Disable'); } else { - $status="off"; $action= t("Enable"); + $status = 'off'; + $action = t('Enable'); } - - $readme=Null; + + $readme = null; if (is_file("addon/$plugin/README.md")){ $readme = file_get_contents("addon/$plugin/README.md"); $readme = Markdown($readme); } else if (is_file("addon/$plugin/README")){ $readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>"; - } - - $admin_form=""; + } + $admin_form = ''; if (is_array($a->plugins_admin) && in_array($plugin, $a->plugins_admin)){ @require_once("addon/$plugin/$plugin.php"); if(function_exists($plugin.'_plugin_admin')) { @@ -947,58 +1032,55 @@ function admin_page_plugins(&$a){ } } - - $t = get_markup_template("admin_plugins_details.tpl"); + $t = get_markup_template('admin_plugins_details.tpl'); return replace_macros($t, array( '$title' => t('Administration'), '$page' => t('Plugins'), '$toggle' => t('Toggle'), '$settings' => t('Settings'), '$baseurl' => $a->get_baseurl(true), - + '$plugin' => $plugin, '$status' => $status, '$action' => $action, '$info' => get_plugin_info($plugin), '$str_author' => t('Author: '), - '$str_maintainer' => t('Maintainer: '), - + '$str_maintainer' => t('Maintainer: '), + '$admin_form' => $admin_form, '$function' => 'plugins', '$screenshot' => '', '$readme' => $readme, - '$form_security_token' => get_form_security_token("admin_themes"), + '$form_security_token' => get_form_security_token('admin_plugins'), )); - } - - - - /** + } + + + /* * List plugins */ - $plugins = array(); - $files = glob("addon/*/"); + $files = glob('addon/*/'); if($files) { - foreach($files as $file) { + foreach($files as $file) { if (is_dir($file)){ - list($tmp, $id)=array_map("trim", explode("/",$file)); + list($tmp, $id) = array_map('trim', explode('/', $file)); $info = get_plugin_info($id); $plugins[] = array( $id, (in_array($id, $a->plugins)?"on":"off") , $info); } } } - - $t = get_markup_template("admin_plugins.tpl"); + + $t = get_markup_template('admin_plugins.tpl'); return replace_macros($t, array( '$title' => t('Administration'), '$page' => t('Plugins'), '$submit' => t('Submit'), '$baseurl' => $a->get_baseurl(true), - '$function' => 'plugins', + '$function' => 'plugins', '$plugins' => $plugins, - '$form_security_token' => get_form_security_token("admin_themes"), + '$form_security_token' => get_form_security_token('admin_plugins'), )); } @@ -1007,7 +1089,7 @@ function admin_page_plugins(&$a){ * @param string $th * @param int $result */ -function toggle_theme(&$themes,$th,&$result) { +function toggle_theme(&$themes, $th, &$result) { for($x = 0; $x < count($themes); $x ++) { if($themes[$x]['name'] === $th) { if($themes[$x]['allowed']) { @@ -1027,7 +1109,7 @@ function toggle_theme(&$themes,$th,&$result) { * @param string $th * @return int */ -function theme_status($themes,$th) { +function theme_status($themes, $th) { for($x = 0; $x < count($themes); $x ++) { if($themes[$x]['name'] === $th) { if($themes[$x]['allowed']) { @@ -1060,17 +1142,17 @@ function rebuild_theme_table($themes) { return $o; } - + /** - * Themes admin page + * @brief Themes admin page. * - * @param App $a + * @param App &$a * @return string */ function admin_page_themes(&$a){ - - $allowed_themes_str = get_config('system','allowed_themes'); - $allowed_themes_raw = explode(',',$allowed_themes_str); + + $allowed_themes_str = get_config('system', 'allowed_themes'); + $allowed_themes_raw = explode(',', $allowed_themes_str); $allowed_themes = array(); if(count($allowed_themes_raw)) foreach($allowed_themes_raw as $x) @@ -1078,23 +1160,23 @@ function admin_page_themes(&$a){ $allowed_themes[] = trim($x); $themes = array(); - $files = glob('view/theme/*'); - if($files) { - foreach($files as $file) { - $f = basename($file); - $is_experimental = intval(file_exists($file . '/.experimental')); + $files = glob('view/theme/*'); + if($files) { + foreach($files as $file) { + $f = basename($file); + $is_experimental = intval(file_exists($file . '/.experimental')); $is_supported = 1-(intval(file_exists($file . '/.unsupported'))); // Is not used yet $is_allowed = intval(in_array($f,$allowed_themes)); $themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed); - } - } + } + } if(! count($themes)) { notice( t('No themes found.')); return ''; } - /** + /* * Single theme */ @@ -1104,22 +1186,21 @@ function admin_page_themes(&$a){ notice( t("Item not found.") ); return ''; } - + if (x($_GET,"a") && $_GET['a']=="t"){ - check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't'); + check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't'); // Toggle theme status - toggle_theme($themes,$theme,$result); + toggle_theme($themes, $theme, $result); $s = rebuild_theme_table($themes); if($result) - info( sprintf('Theme %s enabled.',$theme)); + info( sprintf('Theme %s enabled.', $theme)); else - info( sprintf('Theme %s disabled.',$theme)); + info( sprintf('Theme %s disabled.', $theme)); - set_config('system','allowed_themes',$s); + set_config('system', 'allowed_themes', $s); goaway($a->get_baseurl(true) . '/admin/themes' ); - return ''; // NOTREACHED } // display theme details @@ -1130,30 +1211,28 @@ function admin_page_themes(&$a){ } else { $status="off"; $action= t("Enable"); } - + $readme=Null; if (is_file("view/theme/$theme/README.md")){ $readme = file_get_contents("view/theme/$theme/README.md"); $readme = Markdown($readme); } else if (is_file("view/theme/$theme/README")){ $readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>"; - } - - $admin_form=""; + } + + $admin_form = ''; if (is_file("view/theme/$theme/php/config.php")){ require_once("view/theme/$theme/php/config.php"); if(function_exists("theme_admin")){ $admin_form = theme_admin($a); } - } - $screenshot = array( get_theme_screenshot($theme), t('Screenshot')); if(! stristr($screenshot[0],$theme)) - $screenshot = null; + $screenshot = null; - $t = get_markup_template("admin_plugins_details.tpl"); + $t = get_markup_template('admin_plugins_details.tpl'); return replace_macros($t, array( '$title' => t('Administration'), '$page' => t('Themes'), @@ -1172,24 +1251,22 @@ function admin_page_themes(&$a){ '$screenshot' => $screenshot, '$readme' => $readme, - '$form_security_token' => get_form_security_token("admin_themes"), + '$form_security_token' => get_form_security_token('admin_themes'), )); - } - - - - /** + } + + /* * List themes */ - + $xthemes = array(); if($themes) { foreach($themes as $th) { $xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name'])); } } - - $t = get_markup_template("admin_plugins.tpl"); + + $t = get_markup_template('admin_plugins.tpl'); return replace_macros($t, array( '$title' => t('Administration'), '$page' => t('Themes'), @@ -1199,43 +1276,41 @@ function admin_page_themes(&$a){ '$plugins' => $xthemes, '$experimental' => t('[Experimental]'), '$unsupported' => t('[Unsupported]'), - '$form_security_token' => get_form_security_token("admin_themes"), + '$form_security_token' => get_form_security_token('admin_themes'), )); } /** - * Logs admin page + * @brief POST handler for logs admin page. * - * @param App $a + * @param App &$a */ - function admin_page_logs_post(&$a) { - if (x($_POST,"page_logs")) { - check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs'); + if (x($_POST, 'page_logs')) { + check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs'); - $logfile = ((x($_POST,'logfile')) ? notags(trim($_POST['logfile'])) : ''); - $debugging = ((x($_POST,'debugging')) ? true : false); - $loglevel = ((x($_POST,'loglevel')) ? intval(trim($_POST['loglevel'])) : 0); + $logfile = ((x($_POST,'logfile')) ? notags(trim($_POST['logfile'])) : ''); + $debugging = ((x($_POST,'debugging')) ? true : false); + $loglevel = ((x($_POST,'loglevel')) ? intval(trim($_POST['loglevel'])) : 0); set_config('system','logfile', $logfile); set_config('system','debugging', $debugging); set_config('system','loglevel', $loglevel); - - } - info( t("Log settings updated.") ); + info( t('Log settings updated.') ); goaway($a->get_baseurl(true) . '/admin/logs' ); - return; // NOTREACHED } /** + * @brief Logs admin page. + * * @param App $a * @return string */ function admin_page_logs(&$a){ - + $log_choices = Array( LOGGER_NORMAL => 'Normal', LOGGER_TRACE => 'Trace', @@ -1243,10 +1318,10 @@ function admin_page_logs(&$a){ LOGGER_DATA => 'Data', LOGGER_ALL => 'All' ); - - $t = get_markup_template("admin_logs.tpl"); - $f = get_config('system','logfile'); + $t = get_markup_template('admin_logs.tpl'); + + $f = get_config('system', 'logfile'); $data = ''; @@ -1275,7 +1350,7 @@ readable."); } fclose($fp); } - } + } return replace_macros($t, array( '$title' => t('Administration'), @@ -1285,13 +1360,13 @@ readable."); '$data' => $data, '$baseurl' => $a->get_baseurl(true), '$logname' => get_config('system','logfile'), - - // name, label, value, help string, extra data... - '$debugging' => array('debugging', t("Debugging"),get_config('system','debugging'), ""), - '$logfile' => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your Red top-level directory.")), - '$loglevel' => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices), - '$form_security_token' => get_form_security_token("admin_logs"), + // name, label, value, help string, extra data... + '$debugging' => array('debugging', t("Debugging"),get_config('system','debugging'), ""), + '$logfile' => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your Red top-level directory.")), + '$loglevel' => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices), + + '$form_security_token' => get_form_security_token('admin_logs'), )); } @@ -1320,7 +1395,6 @@ function admin_page_profs_post(&$a) { // add to chosen array basic or advanced goaway(z_root() . '/admin/profs'); - } function admin_page_profs(&$a) { @@ -1343,7 +1417,6 @@ function admin_page_profs(&$a) { '$field_help' => array('field_help',t('Help text'),$_REQUEST['field_help'],t('Additional info (optional)')), '$submit' => t('Save') )); - } if((argc() > 2) && intval(argv(2))) { @@ -1365,10 +1438,4 @@ function admin_page_profs(&$a) { '$submit' => t('Save') )); } - } - - - - - diff --git a/mod/attach.php b/mod/attach.php index cf72d09c6..118c67dd5 100644 --- a/mod/attach.php +++ b/mod/attach.php @@ -36,7 +36,8 @@ function attach_init(&$a) { header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"'); if($r['data']['flags'] & ATTACH_FLAG_OS ) { - $istream = fopen('store/' . $c[0]['channel_address'] . '/' . $r['data']['data'],'rb'); + $fname = dbunescbin($r['data']['data']); + $istream = fopen('store/' . $c[0]['channel_address'] . '/' . $fname,'rb'); $ostream = fopen('php://output','wb'); if($istream && $ostream) { pipe_streams($istream,$ostream); @@ -45,7 +46,7 @@ function attach_init(&$a) { } } else - echo $r['data']['data']; + echo dbunescbin($r['data']['data']); killme(); } diff --git a/mod/blocks.php b/mod/blocks.php index f755f92b0..f609164e0 100644 --- a/mod/blocks.php +++ b/mod/blocks.php @@ -33,6 +33,8 @@ function blocks_content(&$a) { $which = argv(1); + $_SESSION['return_url'] = $a->query_string; + $uid = local_channel(); $owner = 0; $channel = null; @@ -68,7 +70,6 @@ function blocks_content(&$a) { return; } - // Block design features from visitors if((! $uid) || ($uid != $owner)) { @@ -76,17 +77,12 @@ function blocks_content(&$a) { return; } + $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); - if(feature_enabled($owner,'expert')) { - $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); - if(! $mimetype) - $mimetype = 'choose'; - } - else { - $mimetype = 'text/bbcode'; + if(! $mimetype) { + $mimetype = 'choose'; } - $x = array( 'webpage' => ITEM_BUILDBLOCK, 'is_owner' => true, @@ -98,6 +94,7 @@ function blocks_content(&$a) { 'mimetype' => $mimetype, 'ptlabel' => t('Block Name'), 'profile_uid' => intval($owner), + 'expanded' => true, ); if($_REQUEST['title']) @@ -107,11 +104,10 @@ function blocks_content(&$a) { if($_REQUEST['pagetitle']) $x['pagetitle'] = $_REQUEST['pagetitle']; + $editor = status_editor($a,$x); - - $o .= status_editor($a,$x); - - $r = q("select * from item_id where uid = %d and service = 'BUILDBLOCK' order by sid asc", + $r = q("select * from item_id left join item on item_id.iid = item.id + where item_id.uid = %d and service = 'BUILDBLOCK' order by item.created desc", intval($owner) ); @@ -120,7 +116,22 @@ function blocks_content(&$a) { if($r) { $pages = array(); foreach($r as $rr) { - $pages[$rr['iid']][] = array('url' => $rr['iid'],'title' => $rr['sid']); + $element_arr = array( + 'type' => 'block', + 'body' => $rr['body'], + 'created' => $rr['created'], + 'edited' => $rr['edited'], + 'mimetype' => $rr['mimetype'], + 'pagetitle' => $rr['sid'], + 'mid' => $rr['mid'] + ); + $pages[$rr['iid']][] = array( + 'url' => $rr['iid'], + 'title' => $rr['sid'], + 'created' => $rr['created'], + 'edited' => $rr['edited'], + 'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]' + ); } } @@ -129,7 +140,15 @@ function blocks_content(&$a) { $o .= replace_macros(get_markup_template('blocklist.tpl'), array( '$baseurl' => $url, + '$title' => t('Blocks'), + '$name' => t('Block Name'), + '$created' => t('Created'), + '$edited' => t('Edited'), + '$create' => t('Create'), '$edit' => t('Edit'), + '$share' => t('Share'), + '$delete' => t('Delete'), + '$editor' => $editor, '$pages' => $pages, '$channel' => $which, '$view' => t('View'), diff --git a/mod/channel.php b/mod/channel.php index 7c98ac899..5f825fe37 100644 --- a/mod/channel.php +++ b/mod/channel.php @@ -36,6 +36,11 @@ function channel_init(&$a) { $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/feed/' . $which .'" />' . "\r\n" ; + +// Not yet ready for prime time +// $a->page['htmlhead'] .= '<link rel="openid.server" href="' . $a->get_baseurl() . '/id/' . $which .'?f=" />' . "\r\n" ; +// $a->page['htmlhead'] .= '<link rel="openid.delegate" href="' . $a->get_baseurl() . '/channel/' . $which .'" />' . "\r\n" ; + // Run profile_load() here to make sure the theme is set before // we start loading content @@ -45,6 +50,11 @@ function channel_init(&$a) { function channel_content(&$a, $update = 0, $load = false) { + + if($load) + $_SESSION['loadtime'] = datetime_convert(); + + $category = $datequery = $datequery2 = ''; $mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : ''); @@ -144,16 +154,25 @@ function channel_content(&$a, $update = 0, $load = false) { $page_mode = 'client'; + $abook_uids = " and abook.abook_channel = " . intval($a->profile['profile_uid']) . " "; + + $simple_update = (($update) ? " AND item_unseen = 1 " : ''); + + if($update && $_SESSION['loadtime']) + $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) "; + if($load) + $simple_update = ''; + if(($update) && (! $load)) { if ($mid) { - $r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d AND item_restrict = 0 + $r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d AND item_restrict = 0 AND item_wall = 1 AND item_unseen = 1 $sql_extra limit 1", - dbesc($mid), + dbesc($mid . '%'), intval($a->profile['profile_uid']) ); } else { $r = q("SELECT distinct parent AS `item_id`, created from item - left join abook on item.author_xchan = abook.abook_xchan + left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) WHERE uid = %d AND item_restrict = 0 AND item_wall = 1 AND item_unseen = 1 AND ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) @@ -162,6 +181,7 @@ function channel_content(&$a, $update = 0, $load = false) { intval($a->profile['profile_uid']), intval(ABOOK_FLAG_BLOCKED) ); + $_SESSION['loadtime'] = datetime_convert(); } } @@ -242,6 +262,9 @@ function channel_content(&$a, $update = 0, $load = false) { } + + + if((! $update) && (! $load)) { // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, @@ -322,8 +345,11 @@ function channel_content(&$a, $update = 0, $load = false) { $o .= conversation($a,$items,'channel',$update,'traditional'); } - if((! $update) || ($_COOKIE['jsAvailable'] != 1)) + if((! $update) || ($_COOKIE['jsAvailable'] != 1)) { $o .= alt_pager($a,count($items)); + if ($mid && $items[0]['title']) + $a->page['title'] = $items[0]['title'] . " - " . $a->page['title']; + } if($mid) $o .= '<div id="content-complete"></div>'; diff --git a/mod/connedit.php b/mod/connedit.php index 9a5c4c4fc..250da672a 100644 --- a/mod/connedit.php +++ b/mod/connedit.php @@ -177,7 +177,17 @@ function connedit_post(&$a) { if(($_REQUEST['pending']) && ($abook_flags & ABOOK_FLAG_PENDING)) { $abook_flags = ( $abook_flags ^ ABOOK_FLAG_PENDING ); $new_friend = true; + if(! $abook_my_perms) { + $abook_my_perms = get_channel_default_perms(local_channel()); + + $role = get_pconfig(local_channel(),'system','permissions_role'); + if($role) { + $x = get_role_perms($role); + if($x['perms_accept']) + $abook_my_perms = $x['perms_accept']; + } + } } $r = q("UPDATE abook SET abook_profile = '%s', abook_my_perms = %d , abook_closeness = %d, abook_flags = %d @@ -560,16 +570,32 @@ function connedit_content(&$a) { if(feature_enabled(local_channel(),'affinity')) { + $labels = array( + t('Me'), + t('Family'), + t('Friends'), + t('Acquaintances'), + t('All') + ); + call_hooks('affinity_labels',$labels); + $label_str = ''; + + if($labels) { + foreach($labels as $l) { + if($label_str) { + $label_str .= ", '|'"; + $label_str .= ", '" . $l . "'"; + } + else + $label_str .= "'" . $l . "'"; + } + } + $slider_tpl = get_markup_template('contact_slider.tpl'); $slide = replace_macros($slider_tpl,array( - '$me' => t('Me'), '$min' => 1, '$val' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 99), - '$intimate' => t('Best Friends'), - '$friends' => t('Friends'), - '$oldfriends' => t('Former Friends'), - '$acquaintances' => t('Acquaintances'), - '$world' => t('Unknown') + '$labels' => $label_str, )); } diff --git a/mod/delegate.php b/mod/delegate.php deleted file mode 100644 index cc399b6e5..000000000 --- a/mod/delegate.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php - -function delegate_content(&$a) { - - if(! local_channel()) { - notice( t('Permission denied.') . EOL); - return; - } - - if($a->argc > 2 && $a->argv[1] === 'add' && intval($a->argv[2])) { - - // delegated admins can view but not change delegation permissions - - if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) - goaway($a->get_baseurl() . '/delegate'); - - - $id = $a->argv[2]; - - $r = q("select `nickname` from user where uid = %d limit 1", - intval($id) - ); - if(count($r)) { - $r = q("select id from contact where uid = %d and nurl = '%s' limit 1", - intval(local_channel()), - dbesc(normalise_link($a->get_baseurl() . '/channel/' . $r[0]['nickname'])) - ); - if(count($r)) { - q("insert into manage ( uid, mid ) values ( %d , %d ) ", - intval($a->argv[2]), - intval(local_channel()) - ); - } - } - goaway($a->get_baseurl() . '/delegate'); - } - - if($a->argc > 2 && $a->argv[1] === 'remove' && intval($a->argv[2])) { - - // delegated admins can view but not change delegation permissions - - if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) - goaway($a->get_baseurl() . '/delegate'); - - q("delete from manage where uid = %d and mid = %d", - intval($a->argv[2]), - intval(local_channel()) - ); - goaway($a->get_baseurl() . '/delegate'); - - } - - $full_managers = array(); - - // These people can manage this account/page with full privilege - - $r = q("SELECT * FROM `user` WHERE `email` = '%s' AND `password` = '%s' ", - dbesc($a->user['email']), - dbesc($a->user['password']) - ); - if(count($r)) - $full_managers = $r; - - $delegates = array(); - - // find everybody that currently has delegated management to this account/page - - $r = q("select * from user where uid in ( select uid from manage where mid = %d ) ", - intval(local_channel()) - ); - - if(count($r)) - $delegates = $r; - - $uids = array(); - - if(count($full_managers)) - foreach($full_managers as $rr) - $uids[] = $rr['uid']; - - if(count($delegates)) - foreach($delegates as $rr) - $uids[] = $rr['uid']; - - // find every contact who might be a candidate for delegation - - $r = q("select nurl from contact where substring_index(contact.nurl,'/',3) = '%s' - and contact.uid = %d and contact.self = 0 and network = '%s' ", - dbesc(normalise_link($a->get_baseurl())), - intval(local_channel()), - dbesc(NETWORK_DFRN) - ); - - if(! count($r)) { - notice( t('No potential page delegates located.') . EOL); - return; - } - - $nicknames = array(); - - if(count($r)) { - foreach($r as $rr) { - $nicknames[] = "'" . dbesc(basename($rr['nurl'])) . "'"; - } - } - - $potentials = array(); - - $nicks = implode(',',$nicknames); - - // get user records for all potential page delegates who are not already delegates or managers - - $r = q("select `uid`, `username`, `nickname` from user where nickname in ( $nicks )"); - - if(count($r)) - foreach($r as $rr) - if(! in_array($rr['uid'],$uids)) - $potentials[] = $rr; - - $o = replace_macros(get_markup_template('delegate.tpl'),array( - '$header' => t('Delegate Page Management'), - '$base' => $a->get_baseurl(), - '$desc' => t('Delegates are able to manage all aspects of this account/page except for basic account settings. Please do not delegate your personal account to anybody that you do not trust completely.'), - '$head_managers' => t('Existing Page Managers'), - '$managers' => $full_managers, - '$head_delegates' => t('Existing Page Delegates'), - '$delegates' => $delegates, - '$head_potentials' => t('Potential Delegates'), - '$potentials' => $potentials, - '$remove' => t('Remove'), - '$add' => t('Add'), - '$none' => t('No entries.') - )); - - - return $o; - - -}
\ No newline at end of file diff --git a/mod/directory.php b/mod/directory.php index 329e255cf..3e94d6395 100644 --- a/mod/directory.php +++ b/mod/directory.php @@ -14,6 +14,31 @@ function directory_init(&$a) { dbesc($_GET['ignore']) ); } + + $observer = get_observer_hash(); + $global_changed = false; + $safe_changed = false; + + if(array_key_exists('global',$_REQUEST)) { + $globaldir = intval($_REQUEST['global']); + $global_changed = true; + } + if($global_changed) { + $_SESSION['globaldir'] = $globaldir; + if($observer) + set_xconfig($observer,'directory','globaldir',$globaldir); + } + + if(array_key_exists('safe',$_REQUEST)) { + $safemode = intval($_REQUEST['safe']); + $safe_changed = true; + } + if($safe_changed) { + $_SESSION['safemode'] = $safemode; + if($observer) + set_xconfig($observer,'directory','safe_mode',$safemode); + } + } function directory_content(&$a) { @@ -23,24 +48,20 @@ function directory_content(&$a) { return; } - $safe_mode = 1; - $observer = get_observer_hash(); - - if($observer) { - $safe_mode = get_xconfig($observer,'directory','safe_mode'); - } - if($safe_mode === false) - $safe_mode = 1; - else - $safe_mode = intval($safe_mode); - if(x($_REQUEST,'safe')) - $safe_mode = (intval($_REQUEST['safe'])); + $globaldir = get_globaldir_setting($observer); + // override your personal global search pref if we're doing a navbar search of the directory + if(intval($_REQUEST['navsearch'])) + $globaldir = 1; + + $safe_mode = get_safemode_setting($observer); $pubforums = null; if(array_key_exists('pubforums',$_REQUEST)) $pubforums = intval($_REQUEST['pubforums']); + if(! $pubforums) + $pubforums = null; $o = ''; nav_set_selected('directory'); @@ -61,12 +82,15 @@ function directory_content(&$a) { $suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : ''; if($suggest) { + $r = suggestion_query(local_channel(),get_observer_hash()); // Remember in which order the suggestions were $addresses = array(); + $common = array(); $index = 0; foreach($r as $rr) { + $common[$rr['xchan_addr']] = $rr['total']; $addresses[$rr['xchan_addr']] = $index++; } @@ -92,6 +116,9 @@ function directory_content(&$a) { $url = $directory['url'] . '/dirsearch'; } + $token = get_config('system','realm_token'); + + logger('mod_directory: URL = ' . $url, LOGGER_DEBUG); $contacts = array(); @@ -106,16 +133,20 @@ function directory_content(&$a) { } } - - if($url) { // We might want to make the tagadelic count (&kw=) configurable or turn it off completely. $numtags = get_config('system','directorytags'); - $kw = ((intval($numtags)) ? $numtags : 24); + $kw = ((intval($numtags)) ? $numtags : 50); $query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : ''); + if($token) + $query .= '&t=' . $token; + + if(! $globaldir) + $query .= '&hub=' . get_app()->get_hostname(); + if($search) $query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search); if(strpos($search,'@')) @@ -127,15 +158,14 @@ function directory_content(&$a) { if(! is_null($pubforums)) $query .= '&pubforums=' . intval($pubforums); - if(! is_null($pubforums)) - $query .= '&pubforums=' . intval($pubforums); + $directory_sort_order = get_config('system','directory_sort_order'); + if(! $directory_sort_order) + $directory_sort_order = 'date'; - $sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : 'normal'); + $sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : $directory_sort_order); if($sort_order) $query .= '&order=' . urlencode($sort_order); - - if($a->pager['page'] != 1) $query .= '&p=' . $a->pager['page']; @@ -277,6 +307,8 @@ function directory_content(&$a) { 'keywords' => $out, 'ignlink' => $suggest ? $a->get_baseurl() . '/directory?ignore=' . $rr['hash'] : '', 'ignore_label' => "Don't suggest", + 'common_friends' => (($common[$rr['address']]) ? intval($common[$rr['address']]) : ''), + 'common_txt' => sprintf( t('Common connections: %s'), intval($common[$rr['address']]) ), 'safe' => $safe_mode ); diff --git a/mod/dirsearch.php b/mod/dirsearch.php index 976e647cb..0b8cfdc6d 100644 --- a/mod/dirsearch.php +++ b/mod/dirsearch.php @@ -12,6 +12,7 @@ function dirsearch_content(&$a) { $ret = array('success' => false); +// logger('request: ' . print_r($_REQUEST,true)); $dirmode = intval(get_config('system','directory_mode')); @@ -21,6 +22,15 @@ function dirsearch_content(&$a) { json_return_and_die($ret); } + $access_token = $_REQUEST['t']; + + $token = get_config('system','realm_token'); + if($token && $access_token != $token) { + $result['message'] = t('This directory server requires an access token'); + return; + } + + if(argc() > 1 && argv(1) === 'sites') { $ret = list_public_sites(); json_return_and_die($ret); @@ -81,6 +91,12 @@ function dirsearch_content(&$a) { else $sync = false; + + if($hub) + $hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') "; + else + $hub_query = ''; + $sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : ''); $joiner = ' OR '; @@ -89,8 +105,6 @@ function dirsearch_content(&$a) { if($name) $sql_extra .= dir_query_build($joiner,'xchan_name',$name); - if($hub) - $sql_extra .= " $joiner xchan_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') "; if($address) $sql_extra .= dir_query_build($joiner,'xchan_addr',$address); if($city) @@ -111,8 +125,7 @@ function dirsearch_content(&$a) { $sql_extra .= dir_query_build($joiner,'xprof_keywords',$keywords); if($forums) - $sql_extra .= dir_flag_build($joiner,'xchan_pubforum',$forums); - + $safesql .= dir_flag_build(' AND ','xchan_flags',XCHAN_FLAGS_PUBFORUM, $forums); // we only support an age range currently. You must set both agege // (greater than or equal) and agele (less than or equal) @@ -156,7 +169,6 @@ function dirsearch_content(&$a) { $sql_extra .= " and xchan_addr like '%%" . get_app()->get_hostname() . "' "; } - $safesql = (($safe > 0) ? " and xchan_censored = 0 and xchan_selfcensored = 0 " : ''); if($safe < 0) $safesql = " and ( xchan_censored = 1 OR xchan_selfcensored = 1 ) "; @@ -174,8 +186,15 @@ function dirsearch_content(&$a) { } - if($sort_order == 'normal') + if($sort_order == 'normal') { $order = " order by xchan_name asc "; + + // Start the alphabetic search at 'A' + // This will make a handful of channels whose names begin with + // punctuation un-searchable in this mode + + $safesql .= " and ascii(substring(xchan_name FROM 1 FOR 1)) > 64 "; + } elseif($sort_order == 'reverse') $order = " order by xchan_name desc "; elseif($sort_order == 'reversedate') @@ -226,17 +245,17 @@ function dirsearch_content(&$a) { json_return_and_die($spkt); } else { - $r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash where ( $logic $sql_extra ) and xchan_network = 'zot' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql $order $qlimit "); + $r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql $order $qlimit ", + $ret['page'] = $page + 1; + $ret['records'] = count($r); + ); } - $ret['page'] = $page + 1; - $ret['records'] = count($r); if($r) { $entries = array(); - foreach($r as $rr) { $entry = array(); @@ -301,7 +320,7 @@ function dir_query_build($joiner,$field,$s) { } function dir_flag_build($joiner,$field,$bit,$s) { - return dbesc($joiner) . " ( " . dbesc($field) . " = " . intval($bit) . " ) "; + return dbesc($joiner) . " ( " . dbesc($field) . " & " . intval($bit) . " ) " . ((intval($s)) ? '>' : '=' ) . " 0 "; } diff --git a/mod/display.php b/mod/display.php index d1cda4e80..33fb83e70 100644 --- a/mod/display.php +++ b/mod/display.php @@ -5,6 +5,10 @@ function display_content(&$a, $update = 0, $load = false) { // logger("mod-display: update = $update load = $load"); + if($load) + $_SESSION['loadtime'] = datetime_convert(); + + if(intval(get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) { notice( t('Public access denied.') . EOL); return; @@ -105,6 +109,15 @@ function display_content(&$a, $update = 0, $load = false) { } + $simple_update = (($update) ? " AND item_unseen = 1 " : ''); + + if($update && $_SESSION['loadtime']) + $simple_update .= " and item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' "; + if($load) + $simple_update = ''; + + + if((! $update) && (! $load)) { @@ -228,6 +241,9 @@ function display_content(&$a, $update = 0, $load = false) { $o .= conversation($a, $items, 'display', $update, 'client'); } else { $o .= conversation($a, $items, 'display', $update, 'traditional'); + if ($items[0]['title']) + $a->page['title'] = $items[0]['title'] . " - " . $a->page['title']; + } if($updateable) { diff --git a/mod/editblock.php b/mod/editblock.php index 46126f94e..a0ece8133 100644 --- a/mod/editblock.php +++ b/mod/editblock.php @@ -70,7 +70,6 @@ function editblock_content(&$a) { $o = ''; - // Figure out which post we're editing $post_id = ((argc() > 2) ? intval(argv(2)) : 0); @@ -96,7 +95,6 @@ function editblock_content(&$a) { return; } - $plaintext = true; $mimeselect = ''; @@ -110,22 +108,21 @@ function editblock_content(&$a) { else $mimeselect = mimetype_select($itm[0]['uid'],$mimetype); - $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( - '$title' => t('Edit Block') + '$title' => t('Edit Block'), + '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), + '$id' => $itm[0]['id'] )); - $a->page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array( '$baseurl' => $a->get_baseurl(), '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), '$ispublic' => ' ', // t('Visible to <strong>everybody</strong>'), '$geotag' => '', '$nickname' => $channel['channel_address'], - '$confirmdelete' => t('Delete block?') + '$confirmdelete' => t('Delete block?') )); - $tpl = get_markup_template("jot.tpl"); $jotplugins = ''; @@ -141,6 +138,12 @@ function editblock_content(&$a) { '$action' => 'item', '$webpage' => ITEM_BUILDBLOCK, '$share' => t('Edit'), + '$bold' => t('Bold'), + '$italic' => t('Italic'), + '$underline' => t('Underline'), + '$quote' => t('Quote'), + '$code' => t('Code'), + '$writefiles' => (perm_is_allowed($owner, get_observer_hash(), 'post_photos') || perm_is_allowed($owner, get_observer_hash(), 'write_storage')), '$upload' => t('Upload photo'), '$attach' => t('Attach file'), '$weblink' => t('Insert web link'), @@ -170,7 +173,7 @@ function editblock_content(&$a) { '$acl' => '', '$bang' => '', '$profile_uid' => (intval($channel['channel_id'])), - '$preview' => true, // ((feature_enabled($uid,'preview')) ? t('Preview') : ''), + '$preview' => t('Preview'), '$jotplugins' => $jotplugins, '$sourceapp' => $itm[0]['app'], '$defexpire' => '', @@ -178,26 +181,6 @@ function editblock_content(&$a) { '$expires' => t('Set expiration date'), )); - - if(($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) - $o .= '<br /><br /><a class="block-delete-link" href="item/drop/' . $itm[0]['id'] . '" >' . t('Delete Block') . '</a><br />'; - - - $x = array( - 'type' => 'block', - 'title' => $itm[0]['title'], - 'body' => $itm[0]['body'], - 'term' => $itm[0]['term'], - 'created' => $itm[0]['created'], - 'edited' => $itm[0]['edited'], - 'mimetype' => $itm[0]['mimetype'], - 'pagetitle' => $page_title, - 'mid' => $itm[0]['mid'] - ); - - $o .= EOL . EOL . t('Share') . EOL . '<textarea onclick="this.select();" class="shareable_element_text" >[element]' . base64url_encode(json_encode($x)) . '[/element]</textarea>' . EOL . EOL; - - return $o; } diff --git a/mod/editlayout.php b/mod/editlayout.php index 451a5380b..11bcc10eb 100644 --- a/mod/editlayout.php +++ b/mod/editlayout.php @@ -114,7 +114,7 @@ function editlayout_content(&$a) { '$ispublic' => ' ', // t('Visible to <strong>everybody</strong>'), '$geotag' => $geotag, '$nickname' => $channel['channel_address'], - '$confirmdelete' => t('Delete layout?') + '$confirmdelete' => t('Delete layout?') )); @@ -137,6 +137,11 @@ function editlayout_content(&$a) { '$action' => 'item', '$webpage' => ITEM_TYPE_PDL, '$share' => t('Edit'), + '$bold' => t('Bold'), + '$italic' => t('Italic'), + '$underline' => t('Underline'), + '$quote' => t('Quote'), + '$code' => t('Code'), '$upload' => t('Upload photo'), '$attach' => t('Attach file'), '$weblink' => t('Insert web link'), @@ -165,7 +170,6 @@ function editlayout_content(&$a) { '$acl' => '', '$bang' => '', '$profile_uid' => (intval($owner)), - '$preview' => true, // ((feature_enabled($uid,'preview')) ? t('Preview') : ''), '$jotplugins' => $jotplugins, '$sourceapp' => t($a->sourcename), '$defexpire' => '', diff --git a/mod/editpost.php b/mod/editpost.php index 3c7829db1..0103e513c 100644 --- a/mod/editpost.php +++ b/mod/editpost.php @@ -74,7 +74,8 @@ function editpost_content(&$a) { $channel = $a->get_channel(); //$tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins)); - + + $voting = feature_enabled(local_channel(),'consensus_tools'); $category = ''; $catsenabled = ((feature_enabled(local_channel(),'categories')) ? 'categories' : ''); @@ -110,6 +111,11 @@ function editpost_content(&$a) { '$return_path' => $_SESSION['return_url'], '$action' => 'item', '$share' => t('Edit'), + '$bold' => t('Bold'), + '$italic' => t('Italic'), + '$underline' => t('Underline'), + '$quote' => t('Quote'), + '$code' => t('Code'), '$upload' => t('Upload photo'), '$attach' => t('Attach file'), '$weblink' => t('Insert web link'), @@ -118,6 +124,9 @@ function editpost_content(&$a) { '$audio' => t('Insert Vorbis [.ogg] audio'), '$setloc' => t('Set your location'), '$noloc' => t('Clear browser location'), + '$voting' => t('Toggle voting'), + '$feature_voting' => $voting, + '$consensus' => (($itm[0]['item_flags'] & ITEM_CONSENSUS) ? 1 : 0), '$wait' => t('Please wait'), '$permset' => t('Permission settings'), '$ptyp' => $itm[0]['type'], @@ -137,7 +146,7 @@ function editpost_content(&$a) { '$acl' => '', '$bang' => '', '$profile_uid' => local_channel(), - '$preview' => true, // ((feature_enabled(local_channel(),'preview')) ? t('Preview') : ''), + '$preview' => t('Preview'), '$jotplugins' => $jotplugins, '$sourceapp' => t($a->sourcename), '$catsenabled' => $catsenabled, diff --git a/mod/editwebpage.php b/mod/editwebpage.php index 87e85424e..fb0d87d4a 100644 --- a/mod/editwebpage.php +++ b/mod/editwebpage.php @@ -90,11 +90,18 @@ function editwebpage_content(&$a) { // We've already figured out which item we want and whose copy we need, // so we don't need anything fancy here - $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1", + $sql_extra = item_permissions_sql($owner); + + $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s $sql_extra LIMIT 1", intval($post_id), intval($owner) ); + if(! $itm) { + notice( t('Permission denied.') . EOL); + return; + } + if(intval($itm[0]['item_obscured'])) { $key = get_config('system','prvkey'); if($itm[0]['title']) @@ -126,7 +133,7 @@ function editwebpage_content(&$a) { $plaintext = true; if(get_config('system','page_mimetype')) - $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />'; + $mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />'; else $mimeselect = mimetype_select($itm[0]['uid'],$mimetype); @@ -135,12 +142,7 @@ function editwebpage_content(&$a) { $layoutselect = '<input type="hidden" name="layout_mid" value="' . $layout . '" />'; else $layoutselect = layout_select($itm[0]['uid'],$itm[0]['layout_mid']); - - $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( - '$title' => t('Edit Webpage') - )); - $a->page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array( '$baseurl' => $a->get_baseurl(), '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), @@ -150,7 +152,6 @@ function editwebpage_content(&$a) { '$confirmdelete' => t('Delete webpage?') )); - $tpl = get_markup_template("jot.tpl"); $jotplugins = ''; @@ -164,14 +165,22 @@ function editwebpage_content(&$a) { $rp = 'webpages/' . $which; - $o .= replace_macros($tpl,array( + logger('canwrite: ' . (perm_is_allowed($owner, get_observer_hash(), 'post_photos') || perm_is_allowed($owner, get_observer_hash(), 'write_storage'))); + + $editor = replace_macros($tpl,array( '$return_path' => $rp, '$webpage' => ITEM_TYPE_WEBPAGE, '$placeholdpagetitle' => t('Page link title'), '$pagetitle' => $page_title, + '$writefiles' => (perm_is_allowed($owner, get_observer_hash(), 'post_photos') || perm_is_allowed($owner, get_observer_hash(), 'write_storage')), '$action' => 'item', '$share' => t('Edit'), + '$bold' => t('Bold'), + '$italic' => t('Italic'), + '$underline' => t('Underline'), + '$quote' => t('Quote'), + '$code' => t('Code'), '$upload' => t('Upload photo'), '$attach' => t('Attach file'), '$weblink' => t('Insert web link'), @@ -202,7 +211,7 @@ function editwebpage_content(&$a) { 'lockstate' => (((strlen($itm[0]['allow_cid'])) || (strlen($itm[0]['allow_gid'])) || (strlen($itm[0]['deny_cid'])) || (strlen($itm[0]['deny_gid']))) ? 'lock' : 'unlock'), '$bang' => '', '$profile_uid' => (intval($owner)), - '$preview' => true, // ((feature_enabled($uid,'preview')) ? t('Preview') : ''), + '$preview' => t('Preview'), '$jotplugins' => $jotplugins, '$sourceapp' => $a->sourcename, '$defexpire' => '', @@ -211,23 +220,12 @@ function editwebpage_content(&$a) { )); - if(($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) - $o .= '<br /><br /><a class="page-delete-link" href="item/drop/' . $itm[0]['id'] . '" >' . t('Delete Webpage') . '</a><br />'; - - - $x = array( - 'type' => 'webpage', - 'title' => $itm[0]['title'], - 'body' => $itm[0]['body'], - 'term' => $itm[0]['term'], - 'created' => $itm[0]['created'], - 'edited' => $itm[0]['edited'], - 'mimetype' => $itm[0]['mimetype'], - 'pagetitle' => $page_title, - 'mid' => $itm[0]['mid'] - ); - - $o .= EOL . EOL . t('Share') . EOL . '<textarea onclick="this.select();" class="shareable_element_text" >[element]' . base64url_encode(json_encode($x)) . '[/element]</textarea>' . EOL . EOL; + $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( + '$title' => t('Edit Webpage'), + '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), + '$editor' => $editor, + '$id' => $itm[0]['id'] + )); return $o; diff --git a/mod/events.php b/mod/events.php index d02a29de6..077095fbe 100755 --- a/mod/events.php +++ b/mod/events.php @@ -8,6 +8,8 @@ require_once('include/items.php'); function events_post(&$a) { + logger('post: ' . print_r($_REQUEST,true)); + if(! local_channel()) return; @@ -83,11 +85,19 @@ function events_post(&$a) { $onerror_url = $a->get_baseurl() . "/events/" . $action . "?summary=$summary&description=$desc&location=$location&start=$start_text&finish=$finish_text&adjust=$adjust&nofinish=$nofinish"; if(strcmp($finish,$start) < 0 && !$nofinish) { notice( t('Event can not end before it has started.') . EOL); + if(intval($_REQUEST['preview'])) { + echo( t('Unable to generate preview.')); + killme(); + } goaway($onerror_url); } if((! $summary) || (! $start)) { notice( t('Event title and start time are required.') . EOL); + if(intval($_REQUEST['preview'])) { + echo( t('Unable to generate preview.')); + killme(); + } goaway($onerror_url); } @@ -102,6 +112,10 @@ function events_post(&$a) { ); if(! $x) { notice( t('Event not found.') . EOL); + if(intval($_REQUEST['preview'])) { + echo( t('Unable to generate preview.')); + killme(); + } return; } if($x[0]['allow_cid'] === '<' . $channel['channel_hash'] . '>' @@ -178,6 +192,12 @@ function events_post(&$a) { $datarray['created'] = $created; $datarray['edited'] = $edited; + if(intval($_REQUEST['preview'])) { + $html = format_event_html($datarray); + echo $html; + killme(); + } + $event = event_store_event($datarray); @@ -253,6 +273,10 @@ function events_content(&$a) { $mode = 'add'; $item_id = intval(argv(2)); } + if(argc() > 2 && argv(1) === 'drop') { + $mode = 'drop'; + $event_id = argv(2); + } if(argv(1) === 'new') { $mode = 'new'; $event_id = ''; @@ -392,6 +416,9 @@ function events_content(&$a) { $last_date = $d; // FIXME $edit = (intval($rr['item_wall']) ? array($a->get_baseurl().'/events/event/'.$rr['event_hash'],t('Edit event'),'','') : null); + + $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); @@ -405,6 +432,7 @@ function events_content(&$a) { 'hash' => $rr['event_hash'], 'start'=> $start, 'end' => $end, + 'drop' => $drop, 'allDay' => false, 'title' => $title, @@ -459,6 +487,30 @@ function events_content(&$a) { } + 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()) + ); + 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()) + ); + info( t('Event removed') . EOL); + } + else { + notice( t('Failed to remove event' ) . EOL); + } + goaway(z_root() . '/events'); + } + } + if($mode === 'edit' && $event_id) { $r = q("SELECT * FROM `event` WHERE event_hash = '%s' AND `uid` = %d LIMIT 1", dbesc($event_id), @@ -497,12 +549,14 @@ function events_content(&$a) { if(! x($orig_event)) $sh_checked = ''; else - $sh_checked = (($orig_event['allow_cid'] === '<' . $channel['channel_hash'] . '>' && (! $orig_event['allow_gid']) && (! $orig_event['deny_cid']) && (! $orig_event['deny_gid'])) ? '' : ' checked="checked" ' ); + $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'] : 'now'); @@ -587,7 +641,7 @@ function events_content(&$a) { '$n_checked' => $n_checked, '$f_text' => t('Event Finishes:'), '$f_dsel' => datetimesel($f,new DateTime(),DateTime::createFromFormat('Y',$fyear+5),DateTime::createFromFormat('Y-m-d H:i',"$fyear-$fmonth-$fday $fhour:$fminute"),'finish_text',true,true,'start_text'), - '$adjust' => array('adjust', t('Adjust for viewer timezone'), $a_checked), + '$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.'),), '$a_text' => t('Adjust for viewer timezone'), '$d_text' => t('Description:'), '$d_orig' => $d_orig, @@ -597,6 +651,7 @@ function events_content(&$a) { '$t_orig' => $t_orig, '$sh_text' => t('Share this event'), '$sh_checked' => $sh_checked, + '$preview' => t('Preview'), '$permissions' => t('Permissions'), '$acl' => (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults),false)), '$submit' => t('Submit') diff --git a/mod/filestorage.php b/mod/filestorage.php index 92474f336..8b52c086b 100644 --- a/mod/filestorage.php +++ b/mod/filestorage.php @@ -21,7 +21,7 @@ function filestorage_post(&$a) { $recurse = ((x($_POST, 'recurse')) ? intval($_POST['recurse']) : 0); $resource = ((x($_POST, 'filehash')) ? notags($_POST['filehash']) : ''); - $no_activity = ((x($_POST, 'no_activity')) ? intval($_POST['no_activity']) : 0); + $notify = ((x($_POST, 'notify')) ? intval($_POST['notify']) : 0); if(! $resource) { notice(t('Item not found.') . EOL); @@ -32,15 +32,16 @@ function filestorage_post(&$a) { $str_contact_allow = perms2str($_REQUEST['contact_allow']); $str_group_deny = perms2str($_REQUEST['group_deny']); $str_contact_deny = perms2str($_REQUEST['contact_deny']); - - attach_change_permissions($channel_id, $resource, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $recurse); - //Build directory tree and redirect $channel = $a->get_channel(); $cloudPath = get_parent_cloudpath($channel_id, $channel['channel_address'], $resource); + + //get the object before permissions change so we can catch eventual former allowed members $object = get_file_activity_object($channel_id, $resource, $cloudPath); - file_activity($channel_id, $object, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, 'post', $no_activity); + attach_change_permissions($channel_id, $resource, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $recurse); + + file_activity($channel_id, $object, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, 'post', $notify); goaway($cloudPath); } @@ -147,15 +148,15 @@ function filestorage_content(&$a) { '$aclselect' => $aclselect_e, '$lockstate' => $lockstate, '$permset' => t('Set/edit permissions'), - '$recurse' => t('Include all files and sub folders'), + '$recurse' => array('recurse', t('Include all files and sub folders'), 0, '', array(t('No'), t('Yes'))), '$backlink' => t('Return to file list'), '$isadir' => $is_a_dir, '$cpdesc' => t('Copy/paste this code to attach file to a post'), '$cpldesc' => t('Copy/paste this URL to link file from a web page'), '$submit' => t('Submit'), - '$attach_btn_title' => t('Attach this file to a new post'), + '$attach_btn_title' => t('Share this file'), '$link_btn_title' => t('Show URL to this file'), - '$activity_btn_title' => t('Do not show in shared with me folder of your connections') + '$notify' => array('notify', t('Notify your contacts about this file'), 0, '', array(t('No'), t('Yes'))) )); echo $o; diff --git a/mod/home.php b/mod/home.php index bd0f271c0..3cbaf097c 100644 --- a/mod/home.php +++ b/mod/home.php @@ -7,6 +7,7 @@ require_once('include/conversation.php'); function home_init(&$a) { $ret = array(); + call_hooks('home_init',$ret); $splash = ((argc() > 1 && argv(1) === 'splash') ? true : false); @@ -35,6 +36,10 @@ function home_content(&$a, $update = 0, $load = false) { $o = ''; + + if($load) + $_SESSION['loadtime'] = datetime_convert(); + if(x($_SESSION,'theme')) unset($_SESSION['theme']); if(x($_SESSION,'mobile_theme')) @@ -67,22 +72,40 @@ function home_content(&$a, $update = 0, $load = false) { if($channel_address) { $page_id = 'home'; + $randpage_id = 'home-%'; $u = q("select channel_id from channel where channel_address = '%s' limit 1", dbesc($channel_address) ); + $randfunc = db_getfunc('RAND'); + $r = q("select item.* from item left join item_id on item.id = item_id.iid - where item.uid = %d and sid = '%s' and service = 'WEBPAGE' and - item_type = %d limit 1", + where item.uid = %d and ( sid = '%s' or sid like '%s' ) and service = 'WEBPAGE' and + item_type = %d ORDER BY $randfunc limit 1", intval($u[0]['channel_id']), dbesc($page_id), - intval(ITEM_TYPE_WEBPAGE) + dbesc($randpage_id), + intval(ITEM_WEBPAGE) ); if($r) { xchan_query($r); $r = fetch_post_tags($r,true); + + if($r[0]['layout_mid']) { + $l = q("select body from item where mid = '%s' and uid = %d limit 1", + dbesc($r[0]['layout_mid']), + intval($u[0]['channel_id']) + ); + + if($l) { + require_once('include/comanche.php'); + comanche_parser($a,$l[0]['body']); + $a->pdl = $l[0]['body']; + } + } + $a->profile = array('profile_uid' => $u[0]['channel_id']); $a->profile_uid = $u[0]['channel_id']; $o .= prepare_page($r[0]); @@ -164,16 +187,23 @@ function home_content(&$a, $update = 0, $load = false) { } require_once('include/identity.php'); - $sys = get_sys_channel(); - $uids = " and item.uid = " . intval($sys['channel_id']) . " "; - $a->data['firehose'] = intval($sys['channel_id']); + + if(get_config('system','site_firehose')) { + require_once('include/security.php'); + $uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0 and (item_flags & " . intval(ITEM_WALL) . " ) > 0 "; + } + else { + $sys = get_sys_channel(); + $uids = " and item.uid = " . intval($sys['channel_id']) . " "; + $a->data['firehose'] = intval($sys['channel_id']); + } $page_mode = 'list'; $simple_update = (($update) ? " and item.item_unseen = 1 " : ''); if($update && $_SESSION['loadtime']) - $simple_update .= " and item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' "; + $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) "; if($load) $simple_update = ''; @@ -185,8 +215,6 @@ function home_content(&$a, $update = 0, $load = false) { if($load) { - $_SESSION['loadtime'] = datetime_convert(); - // Fetch a page full of parent items for this page $r = q("SELECT distinct item.id AS item_id, $ordering FROM item @@ -199,8 +227,20 @@ function home_content(&$a, $update = 0, $load = false) { intval(ABOOK_FLAG_BLOCKED) ); + } + elseif($update) { + $r = q("SELECT distinct item.id AS item_id, $ordering FROM item + left join abook on item.author_xchan = abook.abook_xchan + WHERE true $uids AND item.item_restrict = 0 + AND item.parent = item.id $simple_update + and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) + $sql_extra3 $sql_extra $sql_nets", + intval(ABOOK_FLAG_BLOCKED) + ); + $_SESSION['loadtime'] = datetime_convert(); + } // Then fetch all the children of the parents that are on this page $parents_str = ''; $update_unseen = ''; diff --git a/mod/id.php b/mod/id.php new file mode 100644 index 000000000..bd4c1fa89 --- /dev/null +++ b/mod/id.php @@ -0,0 +1,310 @@ +<?php +/** + * @file mod/id.php + * @brief OpenID implementation + */ + +require 'library/openid/provider/provider.php'; + + +$attrMap = array( + 'namePerson/first' => t('First Name'), + 'namePerson/last' => t('Last Name'), + 'namePerson/friendly' => t('Nickname'), + 'namePerson' => t('Full Name'), + 'contact/internet/email' => t('Email'), + 'contact/email' => t('Email'), + 'media/image/aspect11' => t('Profile Photo'), + 'media/image' => t('Profile Photo'), + 'media/image/default' => t('Profile Photo'), + 'media/image/16x16' => t('Profile Photo 16px'), + 'media/image/32x32' => t('Profile Photo 32px'), + 'media/image/48x48' => t('Profile Photo 48px'), + 'media/image/64x64' => t('Profile Photo 64px'), + 'media/image/80x80' => t('Profile Photo 80px'), + 'media/image/128x128' => t('Profile Photo 128px'), + 'timezone' => t('Timezone'), + 'contact/web/default' => t('Homepage URL'), + 'language/pref' => t('Language'), + 'birthDate/birthYear' => t('Birth Year'), + 'birthDate/birthMonth' => t('Birth Month'), + 'birthDate/birthday' => t('Birth Day'), + 'birthDate' => t('Birthdate'), + 'gender' => t('Gender'), +); + + +/** + * @brief Entrypoint for the OpenID implementation. + * + * @param App &$a + */ +function id_init(&$a) { + + logger('id: ' . print_r($_REQUEST, true)); + + if(argc() > 1) { + $which = argv(1); + } else { + $a->error = 404; + return; + } + + $profile = ''; + $channel = $a->get_channel(); + profile_load($a,$which,$profile); + + $op = new MysqlProvider; + $op->server(); +} + +/** + * @brief Returns user data needed for OpenID. + * + * If no $handle is provided we will use local_channel() by default. + * + * @param string $handle (default null) + * @return boolean|array + */ +function getUserData($handle = null) { + if (! local_channel()) { + notice( t('Permission denied.') . EOL); + get_app()->page['content'] = login(); + + return false; + } + +// logger('handle: ' . $handle); + + if ($handle) { + $r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1", + dbesc($handle) + ); + } else { + $r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d", + intval(local_channel()) + ); + } + + if (! r) + return false; + + $x = q("select * from account where account_id = %d limit 1", + intval($r[0]['channel_account_id']) + ); + if ($x) + $r[0]['email'] = $x[0]['account_email']; + + $p = q("select * from profile where is_default = 1 and uid = %d limit 1", + intval($r[0]['channel_account_id']) + ); + + $gender = ''; + if ($p[0]['gender'] == t('Male')) + $gender = 'M'; + if ($p[0]['gender'] == t('Female')) + $gender = 'F'; + + $r[0]['firstName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],0,strpos($r[0]['channel_name'],' ')) : $r[0]['channel_name']); + $r[0]['lastName'] = ((strpos($r[0]['channel_name'],' ')) ? substr($r[0]['channel_name'],strpos($r[0]['channel_name'],' ')+1) : ''); + $r[0]['namePerson'] = $r[0]['channel_name']; + $r[0]['pphoto'] = $r[0]['xchan_photo_l']; + $r[0]['pphoto16'] = z_root() . '/photo/profile/16/' . $r[0]['channel_id'] . '.jpg'; + $r[0]['pphoto32'] = z_root() . '/photo/profile/32/' . $r[0]['channel_id'] . '.jpg'; + $r[0]['pphoto48'] = z_root() . '/photo/profile/48/' . $r[0]['channel_id'] . '.jpg'; + $r[0]['pphoto64'] = z_root() . '/photo/profile/64/' . $r[0]['channel_id'] . '.jpg'; + $r[0]['pphoto80'] = z_root() . '/photo/profile/80/' . $r[0]['channel_id'] . '.jpg'; + $r[0]['pphoto128'] = z_root() . '/photo/profile/128/' . $r[0]['channel_id'] . '.jpg'; + $r[0]['timezone'] = $r[0]['channel_timezone']; + $r[0]['url'] = $r[0]['xchan_url']; + $r[0]['language'] = (($x[0]['account_language']) ? $x[0]['account_language'] : 'en'); + $r[0]['birthyear'] = ((intval(substr($p[0]['dob'],0,4))) ? intval(substr($p[0]['dob'],0,4)) : ''); + $r[0]['birthmonth'] = ((intval(substr($p[0]['dob'],5,2))) ? intval(substr($p[0]['dob'],5,2)) : ''); + $r[0]['birthday'] = ((intval(substr($p[0]['dob'],8,2))) ? intval(substr($p[0]['dob'],8,2)) : ''); + $r[0]['birthdate'] = (($r[0]['birthyear'] && $r[0]['birthmonth'] && $r[0]['birthday']) ? $p[0]['dob'] : ''); + $r[0]['gender'] = $gender; + + return $r[0]; + +/* +* if(isset($_POST['login'],$_POST['password'])) { +* $login = mysql_real_escape_string($_POST['login']); +* $password = sha1($_POST['password']); +* $q = mysql_query("SELECT * FROM Users WHERE login = '$login' AND password = '$password'"); +* if($data = mysql_fetch_assoc($q)) { +* return $data; +* } +* if($handle) { +* echo 'Wrong login/password.'; +* } +* } +* if($handle) { +* ?> +* <form action="" method="post"> +* <input type="hidden" name="openid.assoc_handle" value="<?php echo $handle?>"> +* Login: <input type="text" name="login"><br> +* Password: <input type="password" name="password"><br> +* <button>Submit</button> +* </form> +* <?php +* die(); +* } +*/ + +} + + +/** + * @brief MySQL provider for OpenID implementation. + * + */ +class MysqlProvider extends LightOpenIDProvider { + + // See http://openid.net/specs/openid-attribute-properties-list-1_0-01.html + // This list contains a few variations of these attributes to maintain + // compatibility with legacy clients + + private $attrFieldMap = array( + 'namePerson/first' => 'firstName', + 'namePerson/last' => 'lastName', + 'namePerson/friendly' => 'channel_address', + 'namePerson' => 'namePerson', + 'contact/internet/email' => 'email', + 'contact/email' => 'email', + 'media/image/aspect11' => 'pphoto', + 'media/image' => 'pphoto', + 'media/image/default' => 'pphoto', + 'media/image/16x16' => 'pphoto16', + 'media/image/32x32' => 'pphoto32', + 'media/image/48x48' => 'pphoto48', + 'media/image/64x64' => 'pphoto64', + 'media/image/80x80' => 'pphoto80', + 'media/image/128x128' => 'pphoto128', + 'timezone' => 'timezone', + 'contact/web/default' => 'url', + 'language/pref' => 'language', + 'birthDate/birthYear' => 'birthyear', + 'birthDate/birthMonth' => 'birthmonth', + 'birthDate/birthday' => 'birthday', + 'birthDate' => 'birthdate', + 'gender' => 'gender', + ); + + function setup($identity, $realm, $assoc_handle, $attributes) { + global $attrMap; + +// logger('identity: ' . $identity); +// logger('realm: ' . $realm); +// logger('assoc_handle: ' . $assoc_handle); +// logger('attributes: ' . print_r($attributes,true)); + + $data = getUserData($assoc_handle); + + +/** @FIXME this needs to be a template with localised strings */ + + $o .= '<form action="" method="post">' + . '<input type="hidden" name="openid.assoc_handle" value="' . $assoc_handle . '">' + . '<input type="hidden" name="login" value="' . $_POST['login'] .'">' + . '<input type="hidden" name="password" value="' . $_POST['password'] .'">' + . "<b>$realm</b> wishes to authenticate you."; + if($attributes['required'] || $attributes['optional']) { + $o .= " It also requests following information (required fields marked with *):" + . '<ul>'; + + foreach($attributes['required'] as $attr) { + if(isset($this->attrMap[$attr])) { + $o .= '<li>' + . '<input type="checkbox" name="attributes[' . $attr . ']"> ' + . $this->attrMap[$attr] . ' <span class="required">*</span></li>'; + } + } + + foreach($attributes['optional'] as $attr) { + if(isset($this->attrMap[$attr])) { + $o .= '<li>' + . '<input type="checkbox" name="attributes[' . $attr . ']"> ' + . $this->attrMap[$attr] . '</li>'; + } + } + $o .= '</ul>'; + } + $o .= '<br>' + . '<button name="once">Allow once</button> ' + . '<button name="always">Always allow</button> ' + . '<button name="cancel">cancel</button> ' + . '</form>'; + + get_app()->page['content'] .= $o; + } + + function checkid($realm, &$attributes) { + + logger('checkid: ' . $realm); + logger('checkid attrs: ' . print_r($attributes,true)); + + if(isset($_POST['cancel'])) { + $this->cancel(); + } + + $data = getUserData(); + if(! $data) { + return false; + } + + $q = get_pconfig(local_channel(), 'openid', $realm); + + $attrs = array(); + if($q) { + $attrs = $q; + } elseif(isset($_POST['attributes'])) { + $attrs = array_keys($_POST['attributes']); + } elseif(!isset($_POST['once']) && !isset($_POST['always'])) { + return false; + } + + $attributes = array(); + foreach($attrs as $attr) { + if(isset($this->attrFieldMap[$attr])) { + $attributes[$attr] = $data[$this->attrFieldMap[$attr]]; + } + } + + if(isset($_POST['always'])) { + set_pconfig(local_channel(),'openid',$realm,array_keys($attributes)); + } + + return z_root() . '/id/' . $data['channel_address']; + } + + function assoc_handle() { + logger('assoc_handle'); + $channel = get_app()->get_channel(); + + return z_root() . '/channel/' . $channel['channel_address']; + } + + function setAssoc($handle, $data) { + logger('setAssoc'); + $channel = channelx_by_nick(basename($handle)); + if($channel) + set_pconfig($channel['channel_id'],'openid','associate',$data); + } + + function getAssoc($handle) { + logger('getAssoc: ' . $handle); + + $channel = channelx_by_nick(basename($handle)); + if($channel) + return get_pconfig($channel['channel_id'], 'openid', 'associate'); + + return false; + } + + function delAssoc($handle) { + logger('delAssoc'); + $channel = channelx_by_nick(basename($handle)); + if($channel) + return del_pconfig($channel['channel_id'], 'openid', 'associate'); + } +} diff --git a/mod/import.php b/mod/import.php index bd95311df..030b714bc 100644 --- a/mod/import.php +++ b/mod/import.php @@ -248,7 +248,7 @@ function import_post(&$a) { if($seize) { - // replace our existing xchan if we're seizing control + // replace any existing xchan we may have on this site if we're seizing control $r = q("delete from xchan where xchan_hash = '%s'", dbesc($channel['channel_hash']) diff --git a/mod/item.php b/mod/item.php index 74c043d5a..ecb54e604 100644 --- a/mod/item.php +++ b/mod/item.php @@ -22,7 +22,6 @@ require_once('include/attach.php'); 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. @@ -35,6 +34,23 @@ function item_post(&$a) { $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(); @@ -59,6 +75,8 @@ function item_post(&$a) { $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. @@ -97,7 +115,7 @@ function item_post(&$a) { * Check service class limits */ if ($uid && !(x($_REQUEST,'parent')) && !(x($_REQUEST,'post_id'))) { - $ret = item_check_service_class($uid,x($_REQUEST,'webpage')); + $ret = item_check_service_class($uid,(($_REQUEST['webpage'] == ITEM_WEBPAGE) ? true : false)); if (!$ret['success']) { notice( t($ret['message']) . EOL) ; if(x($_REQUEST,'return')) @@ -114,13 +132,6 @@ function item_post(&$a) { $item_flags = $item_restrict = 0; - /** - * Is this a reply to something? - */ - - $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0); - $parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : ''); - $route = ''; $parent_item = null; $parent_contact = null; @@ -273,6 +284,9 @@ function item_post(&$a) { $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); @@ -378,7 +392,8 @@ function item_post(&$a) { $coord = notags(trim($_REQUEST['coord'])); $verb = notags(trim($_REQUEST['verb'])); $title = escape_tags(trim($_REQUEST['title'])); - $body = $_REQUEST['body']; + $body = trim($_REQUEST['body']); + $body .= trim($_REQUEST['attachment']); $postopts = ''; $private = ( @@ -516,12 +531,13 @@ function item_post(&$a) { $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("/([^\]\='".'"'."\/]|^|\#\^)(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); @@ -581,7 +597,7 @@ function item_post(&$a) { if($results) { // Set permissions based on tag replacements - set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item); + set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private); $post_tags = array(); foreach($results as $result) { @@ -671,13 +687,20 @@ function item_post(&$a) { $item_thead_top = ((! $parent) ? 1 : 0); +<<<<<<< HEAD if ((! $plink) && ($item_thread_top)) { +======= + if($consensus) + $item_flags |= ITEM_CONSENSUS; + + if ((! $plink) && ($item_flags & ITEM_THREAD_TOP)) { +>>>>>>> master $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; @@ -716,6 +739,7 @@ function item_post(&$a) { $datarray['term'] = $post_tags; $datarray['plink'] = $plink; $datarray['route'] = $route; + $datarray['item_unseen'] = $item_unseen; // preview mode - prepare the body for display and send it via json @@ -726,7 +750,7 @@ function item_post(&$a) { $datarray['author'] = $observer; $datarray['attach'] = json_encode($datarray['attach']); $o = conversation($a,array($datarray),'search',false,'preview'); - logger('preview: ' . $o, LOGGER_DEBUG); +// logger('preview: ' . $o, LOGGER_DEBUG); echo json_encode(array('preview' => $o)); killme(); } @@ -833,6 +857,13 @@ function item_post(&$a) { 'otype' => 'item' )); } + + if($uid && $uid == $profile_uid && (! $datarray['item_restrict'])) { + 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 @@ -915,6 +946,10 @@ function item_content(&$a) { if(local_channel() && local_channel() == $i[0]['uid']) $local_delete = true; + $sys = get_sys_channel(); + if(is_site_admin() && $sys['channel_id'] == $i[0]['uid']) + $can_delete = true; + $ob_hash = get_observer_hash(); if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) $can_delete = true; @@ -1043,36 +1078,48 @@ function fix_attached_file_permissions($channel,$observer_hash,$body, function item_check_service_class($channel_id,$iswebpage) { $ret = array('success' => false, $message => ''); + if ($iswebpage) { +<<<<<<< HEAD $r = q("select count(i.id) as total from item i right join channel c on (i.author_xchan=c.channel_hash and i.uid=c.channel_id ) and i.parent=i.id and i.item_type = %d and i.item_deleted = 0 and i.uid= %d ", intval(ITEM_TYPE_WEBPAGE), +======= + // note: we aren't counting comanche templates and blocks, only webpages + $r = q("select count(id) as total from item where parent = id + and ( item_restrict & %d ) > 0 and ( item_restrict & %d ) = 0 and uid = %d ", + intval(ITEM_WEBPAGE), + intval(ITEM_DELETED), +>>>>>>> master intval($channel_id) ); } else { - $r = q("select count(i.id) as total from item i - right join channel c on (i.author_xchan=c.channel_hash and i.uid=c.channel_id ) - and i.parent=i.id and (i.item_restrict=0) and i.uid= %d ", - intval($channel_id) - ); + $r = q("select count(id) as total from item where parent = id and item_restrict = 0 and (item_flags & %d) > 0 and uid = %d ", + intval(ITEM_WALL), + intval($channel_id) + ); } - if(! ($r && count($r))) { - $ret['message'] = t('Unable to obtain identity information from database'); + + if(! $r) { + $ret['message'] = t('Unable to obtain post information from database.'); return $ret; } + if (!$iswebpage) { - if(! service_class_allows($channel_id,'total_items',$r[0]['total'])) { - $result['message'] .= upgrade_message().sprintf(t("You have reached your limit of %1$.0f top level posts."),$r[0]['total']); - return $result; - } + $max = service_class_fetch($channel_id,'total_items'); + if(! service_class_allows($channel_id,'total_items',$r[0]['total'])) { + $result['message'] .= upgrade_message() . sprintf( t('You have reached your limit of %1$.0f top level posts.'),$max); + return $result; + } } else { - if(! service_class_allows($channel_id,'total_pages',$r[0]['total'])) { - $result['message'] .= upgrade_message().sprintf(t("You have reached your limit of %1$.0f webpages."),$r[0]['total']); - return $result; - } + $max = service_class_fetch($channel_id,'total_pages'); + if(! service_class_allows($channel_id,'total_pages',$r[0]['total'])) { + $result['message'] .= upgrade_message() . sprintf( t('You have reached your limit of %1$.0f webpages.'),$max); + return $result; + } } $ret['success'] = true; diff --git a/mod/layouts.php b/mod/layouts.php index 3ce891d85..b2be39802 100644 --- a/mod/layouts.php +++ b/mod/layouts.php @@ -33,6 +33,8 @@ function layouts_content(&$a) { $which = argv(1); + $_SESSION['return_url'] = $a->query_string; + $uid = local_channel(); $owner = 0; $channel = null; @@ -98,7 +100,6 @@ function layouts_content(&$a) { header('Content-disposition: attachment; filename="' . $r[0]['sid'] . '.pdl"'); echo json_encode($r); killme(); - } } @@ -111,7 +112,7 @@ function layouts_content(&$a) { 'id' => 'layout-help-tab', )); - $o .= replace_macros(get_markup_template('common_tabs.tpl'),array('$tabs' => $tabs)); + //$o .= replace_macros(get_markup_template('common_tabs.tpl'),array('$tabs' => $tabs)); // Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages @@ -122,13 +123,15 @@ function layouts_content(&$a) { 'webpage' => ITEM_TYPE_PDL, 'is_owner' => true, 'nickname' => $a->profile['channel_address'], - 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + //do we need that at this place? + //'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), 'bang' => '', 'showacl' => false, 'visitor' => false, 'nopreview' => 1, 'ptlabel' => t('Layout Name'), 'profile_uid' => intval($owner), + 'expanded' => true ); if($_REQUEST['title']) @@ -139,7 +142,7 @@ function layouts_content(&$a) { $x['pagetitle'] = $_REQUEST['pagetitle']; - $o .= status_editor($a,$x); + $editor = status_editor($a,$x); $r = q("select iid, sid, mid from item_id left join item on item.id = item_id.iid where item_id.uid = %d and service = 'PDL' order by sid asc", @@ -156,23 +159,24 @@ function layouts_content(&$a) { 'title' => $rr['sid'], 'mid' => $rr['mid'] ); - } + } } //Build the base URL for edit links $url = z_root() . '/editlayout/' . $which; $o .= replace_macros(get_markup_template('layoutlist.tpl'), array( + '$title' => t('Layouts'), + '$create' => t('Create'), + '$help' => array('text' => t('Help'), 'url' => 'help/Comanche', 'title' => t('Comanche page description language help')), + '$editor' => $editor, '$baseurl' => $url, '$edit' => t('Edit'), '$share' => t('Share'), '$pages' => $pages, '$channel' => $which, '$view' => t('View'), - '$preview' => '1', - )); - - return $o; + return $o; } diff --git a/mod/like.php b/mod/like.php index 6316b38f9..35c72bb12 100755 --- a/mod/like.php +++ b/mod/like.php @@ -49,6 +49,18 @@ function like_content(&$a) { case 'unabstain': $activity = ACTIVITY_ABSTAIN; break; + case 'attendyes': + case 'unattendyes': + $activity = ACTIVITY_ATTEND; + break; + case 'attendno': + case 'unattendno': + $activity = ACTIVITY_ATTENDNO; + break; + case 'attendmaybe': + case 'unattendmaybe': + $activity = ACTIVITY_ATTENDMAYBE; + break; default: return; break; @@ -276,21 +288,53 @@ function like_content(&$a) { else killme(); - $r = q("SELECT id FROM item WHERE verb = '%s' AND item_restrict = 0 - AND author_xchan = '%s' AND ( parent = %d OR thr_parent = '%s') LIMIT 1", - dbesc($activity), + + $verbs = " '".dbesc($activity)."' "; + $multi_undo = 0; + + // event participation and consensus items are essentially radio toggles. If you make a subsequent choice, + // we need to eradicate your first choice. + + if($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) { + $verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' "; + $multi_undo = 1; + } + if($activity === ACTIVITY_AGREE || $activity === ACTIVITY_DISAGREE || $activity === ACTIVITY_ABSTAIN) { + $verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' "; + $multi_undo = 1; + } + + $r = q("SELECT id, parent, uid, verb FROM item WHERE verb in ( $verbs ) AND item_restrict = 0 + AND author_xchan = '%s' AND ( parent = %d OR thr_parent = '%s') and uid = %d ", dbesc($observer['xchan_hash']), intval($item_id), - dbesc($item['mid']) + dbesc($item['mid']), + intval($owner_uid) ); if($r) { // already liked it. Drop that item. require_once('include/items.php'); - drop_item($r[0]['id'],false,DROPITEM_PHASE1); - return; - } + foreach($r as $rr) { + drop_item($rr['id'],false,DROPITEM_PHASE1); + // set the changed timestamp on the parent so we'll see the update without a page reload + $z = q("update item set changed = '%s' where id = %d and uid = %d", + dbesc(datetime_convert()), + intval($rr['parent']), + intval($rr['uid']) + ); + // Prior activity was a duplicate of the one we're submitting, just undo it; + // don't fall through and create another + if(activity_match($rr['verb'],$activity)) + $multi_undo = false; + } + if($interactive) + return; + + if(! $multi_undo) + killme(); + } } $mid = item_message_id(); @@ -303,6 +347,8 @@ function like_content(&$a) { } else { $post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status')); + if($item['obj_type'] === ACTIVITY_OBJ_EVENT) + $post_type = t('event'); $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink'])); $objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE ); @@ -358,8 +404,12 @@ function like_content(&$a) { $bodyverb = t('%1$s doesn\'t agree with %2$s\'s %3$s'); if($verb === 'abstain') $bodyverb = t('%1$s abstains from a decision on %2$s\'s %3$s'); - - + if($verb === 'attendyes') + $bodyverb = t('%1$s is attending %2$s\'s %3$s'); + if($verb === 'attendno') + $bodyverb = t('%1$s is not attending %2$s\'s %3$s'); + if($verb === 'attendmaybe') + $bodyverb = t('%1$s may attend %2$s\'s %3$s'); if(! isset($bodyverb)) killme(); diff --git a/mod/lockview.php b/mod/lockview.php index a46fb6d69..84c16f658 100644 --- a/mod/lockview.php +++ b/mod/lockview.php @@ -14,10 +14,13 @@ function lockview_content(&$a) { if(! $item_id) killme(); - if (!in_array($type, array('item','photo','event'))) + if (!in_array($type, array('item','photo','event', 'menu_item'))) killme(); - $r = q("SELECT * FROM %s WHERE id = %d LIMIT 1", + //we have different naming in in menu_item table + $id = (($type == 'menu_item') ? 'mitem_id' : 'id'); + + $r = q("SELECT * FROM %s WHERE $id = %d LIMIT 1", dbesc($type), intval($item_id) ); @@ -27,7 +30,10 @@ function lockview_content(&$a) { $item = $r[0]; - if($item['uid'] != local_channel()) { + //we have different naming in in menu_item table + $uid = (($type == 'menu_item') ? $item['mitem_channel_id'] : $item['uid']); + + if($uid != local_channel()) { echo '<li>' . t('Remote privacy information not available.') . '</li>'; killme(); } diff --git a/mod/magic.php b/mod/magic.php index c31fa71ae..df8ac39a8 100644 --- a/mod/magic.php +++ b/mod/magic.php @@ -10,11 +10,10 @@ function magic_init(&$a) { logger('mod_magic: args: ' . print_r($_REQUEST,true),LOGGER_DATA); $addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : ''); - $hash = ((x($_REQUEST,'hash')) ? $_REQUEST['hash'] : ''); $dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : ''); $test = ((x($_REQUEST,'test')) ? intval($_REQUEST['test']) : 0); $rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0); - + $delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : ''); $parsed = parse_url($dest); if(! $parsed) { @@ -100,6 +99,29 @@ function magic_init(&$a) { $ret['message'] .= 'Local site - you are already authenticated.' . EOL; return $ret; } + + $delegation_success = false; + if($delegate) { + $r = q("select * from channel left join hubloc on channel_hash = hubloc_hash where hubloc_addr = '%s' limit 1", + dbesc($delegate) + ); + if($r && intval($r[0]['channel_id'])) { + $allowed = perm_is_allowed($r[0]['channel_id'],get_observer_hash(),'delegate'); + if($allowed) { + $_SESSION['delegate_channel'] = $r[0]['channel_id']; + $_SESSION['delegate'] = get_observer_hash(); + $_SESSION['account_id'] = intval($r[0]['channel_account_id']); + change_channel($r[0]['channel_id']); + $delegation_success = true; + } + } + } + + + + // FIXME: check and honour local delegation + + goaway($dest); } @@ -123,6 +145,9 @@ function magic_init(&$a) { $target_url = $x[0]['hubloc_callback'] . '/?f=&auth=' . urlencode($channel['channel_address'] . '@' . $a->get_hostname()) . '&sec=' . $token . '&dest=' . urlencode($dest) . '&version=' . ZOT_REVISION; + if($delegate) + $target_url .= '&delegate=' . urlencode($delegate); + logger('mod_magic: redirecting to: ' . $target_url, LOGGER_DEBUG); if($test) { diff --git a/mod/manage.php b/mod/manage.php index ed63f63f9..aa356abad 100644 --- a/mod/manage.php +++ b/mod/manage.php @@ -2,7 +2,7 @@ function manage_content(&$a) { - if(! get_account_id()) { + if((! get_account_id()) || ($_SESSION['delegate'])) { notice( t('Permission denied.') . EOL); return; } @@ -57,8 +57,7 @@ function manage_content(&$a) { $c = q("SELECT id, item_restrict, item_wall FROM item - WHERE (item_restrict = %d) and item_unseen = 1 and uid = %d", - intval(ITEM_VISIBLE), + WHERE item_restrict = 0 and item_unseen = 1 and uid = %d", intval($channels[$x]['channel_id']) ); @@ -144,6 +143,22 @@ function manage_content(&$a) { array( 'new_channel', t('Create a new channel'), t('Create a new channel')) ); + $delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where + abook_channel = %d and (abook_their_perms & %d) > 0", + intval(local_channel()), + intval(PERMS_A_DELEGATE) + ); + if(! $delegates) + $delegates = null; + + if($delegates) { + for($x = 0; $x < count($delegates); $x ++) { + $delegates[$x]['link'] = 'magic?f=&dest=' . urlencode($delegates[$x]['xchan_url']) . '&delegate=' . urlencode($delegates[$x]['xchan_addr']); + } + } + + + $o = replace_macros(get_markup_template('channels.tpl'), array( '$header' => t('Channel Manager'), '$msg_selected' => t('Current Channel'), @@ -153,9 +168,12 @@ function manage_content(&$a) { '$msg_make_default' => t('Make Default'), '$links' => $links, '$all_channels' => $channels, - '$mail_format' => t('%d new messages'), - '$intros_format' => t('%d new introductions'), + '$mail_format' => t('%d new messages'), + '$intros_format' => t('%d new introductions'), '$channel_usage_message' => $channel_usage_message, + '$delegate_header' => t('Delegated Channels'), + '$delegates' => $delegates, + )); diff --git a/mod/match.php b/mod/match.php index 5a01ba645..fd739ba2c 100644 --- a/mod/match.php +++ b/mod/match.php @@ -1,14 +1,20 @@ <?php -// FIXME - this has never been properly ported from Friendica -// It takes keywords from your profile and queries the directory server for -// matching keywords from other profiles. - - +/** + * @brief Controller for /match. + * + * It takes keywords from your profile and queries the directory server for + * matching keywords from other profiles. + * + * @FIXME this has never been properly ported from Friendica. + * + * @param App &$a + * @return void|string + */ function match_content(&$a) { $o = ''; - if(! local_channel()) + if (! local_channel()) return; $_SESSION['return_url'] = $a->get_baseurl() . '/' . $a->cmd; @@ -18,22 +24,22 @@ function match_content(&$a) { $r = q("SELECT `keywords` FROM `profile` WHERE `is_default` = 1 AND `uid` = %d LIMIT 1", intval(local_channel()) ); - if(! count($r)) - return; - if(! $r[0]['keywords']) { - notice( t('No keywords to match. Please add keywords to your default profile.') . EOL); + if (! count($r)) return; + if (! $r[0]['keywords']) { + notice( t('No keywords to match. Please add keywords to your default profile.') . EOL); + return; } $params = array(); $tags = trim($r[0]['keywords']); - - if($tags) { + + if ($tags) { $params['s'] = $tags; - if($a->pager['page'] != 1) + if ($a->pager['page'] != 1) $params['p'] = $a->pager['page']; - + // if(strlen(get_config('system','directory_submit_url'))) // $x = post_url('http://dir.friendica.com/msearch', $params); // else @@ -41,18 +47,14 @@ function match_content(&$a) { $j = json_decode($x); - if($j->total) { + if ($j->total) { $a->set_pager_total($j->total); $a->set_pager_itemspage($j->items_page); } - if(count($j->results)) { - - - + if (count($j->results)) { $tpl = get_markup_template('match.tpl'); - foreach($j->results as $jj) { - + foreach ($j->results as $jj) { $connlnk = $a->get_baseurl() . '/follow/?url=' . $jj->url; $o .= replace_macros($tpl,array( '$url' => zid($jj->url), @@ -64,14 +66,13 @@ function match_content(&$a) { '$tags' => $jj->tags )); } - } - else { + } else { info( t('No matches') . EOL); - } - + } } $o .= cleardiv(); $o .= paginate($a); + return $o; } diff --git a/mod/menu.php b/mod/menu.php index 7e9c580a8..0dbbfde9c 100644 --- a/mod/menu.php +++ b/mod/menu.php @@ -3,11 +3,20 @@ require_once('include/menu.php'); require_once('include/identity.php'); +function menu_init(&$a) { + if (array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { + $sys = get_sys_channel(); + if ($sys && intval($sys['channel_id'])) { + $a->is_sys = true; + } + } +} + function menu_post(&$a) { $uid = local_channel(); - if(array_key_exists('sys',$_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { + if(array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { $sys = get_sys_channel(); $uid = intval($sys['channel_id']); $a->is_sys = true; @@ -17,7 +26,7 @@ function menu_post(&$a) { return; $_REQUEST['menu_channel_id'] = $uid; - + if($_REQUEST['menu_bookmark']) $_REQUEST['menu_flags'] |= MENU_BOOKMARK; if($_REQUEST['menu_system']) @@ -28,7 +37,7 @@ function menu_post(&$a) { $_REQUEST['menu_id'] = intval(argv(1)); $r = menu_edit($_REQUEST); if($r) { - info( t('Menu updated.') . EOL); + //info( t('Menu updated.') . EOL); goaway(z_root() . '/mitem/' . $menu_id . (($a->is_sys) ? '?f=&sys=1' : '')); } else @@ -37,14 +46,13 @@ function menu_post(&$a) { else { $r = menu_create($_REQUEST); if($r) { - info( t('Menu created.') . EOL); + //info( t('Menu created.') . EOL); goaway(z_root() . '/mitem/' . $r . (($a->is_sys) ? '?f=&sys=1' : '')); } else notice( t('Unable to create menu.'). EOL); } - } @@ -52,7 +60,7 @@ function menu_content(&$a) { $uid = local_channel(); - if($a->is_sys && is_site_admin()) { + if ($a->is_sys && is_site_admin()) { $sys = get_sys_channel(); $uid = intval($sys['channel_id']); } @@ -62,8 +70,10 @@ function menu_content(&$a) { return ''; } - if(argc() == 1) { + + + // list menus $x = menu_list($uid); if($x) { @@ -72,65 +82,68 @@ function menu_content(&$a) { } } + $create = replace_macros(get_markup_template('menuedit.tpl'), array( + '$menu_name' => array('menu_name', t('Menu Name'), '', t('Unique name (not visible on webpage) - required'), '*'), + '$menu_desc' => array('menu_desc', t('Menu Title'), '', t('Visible on webpage - leave empty for no title'), ''), + '$menu_bookmark' => array('menu_bookmark', t('Allow Bookmarks'), 0 , t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))), + '$submit' => t('Submit and proceed'), + '$sys' => $a->is_sys, + '$display' => 'none' + )); + $o = replace_macros(get_markup_template('menulist.tpl'),array( - '$title' => t('Manage Menus'), + '$title' => t('Menus'), + '$create' => $create, '$menus' => $x, + '$nametitle' => t('Menu Name'), + '$desctitle' => t('Menu Title'), '$edit' => t('Edit'), '$drop' => t('Drop'), '$new' => t('New'), '$bmark' => t('Bookmarks allowed'), - '$hintnew' => t('Create a new menu'), + '$hintnew' => t('Create'), '$hintdrop' => t('Delete this menu'), '$hintcontent' => t('Edit menu contents'), - '$hintedit' => t('Edit this menu') + '$hintedit' => t('Edit this menu'), + '$sys' => $a->is_sys )); return $o; } - if(argc() > 1) { - if(argv(1) === 'new') { - $o = replace_macros(get_markup_template('menuedit.tpl'), array( - '$header' => t('New Menu'), - '$menu_name' => array('menu_name', t('Menu name'), '', t('Must be unique, only seen by you'), '*'), - '$menu_desc' => array('menu_desc', t('Menu title'), '', t('Menu title as seen by others'), ''), - '$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), 0 , t('Menu may be used to store saved bookmarks'), ''), - '$submit' => t('Create') - )); - return $o; - } + if(intval(argv(1))) { - elseif(intval(argv(1))) { - $m = menu_fetch_id(intval(argv(1)),$uid); - if(! $m) { - notice( t('Menu not found.') . EOL); - return ''; - } if(argc() == 3 && argv(2) == 'drop') { $r = menu_delete_id(intval(argv(1)),$uid); - if($r) - info( t('Menu deleted.') . EOL); - else + if(!$r) notice( t('Menu could not be deleted.'). EOL); goaway(z_root() . '/menu' . (($a->is_sys) ? '?f=&sys=1' : '')); } - else { - $o = replace_macros(get_markup_template('menuedit.tpl'), array( - '$header' => t('Edit Menu'), - '$menu_id' => intval(argv(1)), - '$hintedit' => t('Add or remove entries to this menu'), - '$editcontents' => t('Edit menu contents'), - '$menu_name' => array('menu_name', t('Menu name'), $m['menu_name'], t('Must be unique, only seen by you'), '*'), - '$menu_desc' => array('menu_desc', t('Menu title'), $m['menu_desc'], t('Menu title as seen by others'), ''), - '$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), (($m['menu_flags'] & MENU_BOOKMARK) ? 1 : 0), t('Menu may be used to store saved bookmarks'), ''), - '$menu_system' => (($m['menu_flags'] & MENU_SYSTEM) ? 1 : 0), - '$submit' => t('Modify') - )); - return $o; + + $m = menu_fetch_id(intval(argv(1)),$uid); + + if(! $m) { + notice( t('Menu not found.') . EOL); + return ''; } + + $o = replace_macros(get_markup_template('menuedit.tpl'), array( + '$header' => t('Edit Menu'), + '$menu_id' => intval(argv(1)), + '$hintedit' => t('Add or remove entries to this menu'), + '$editcontents' => t('Edit menu contents'), + '$menu_name' => array('menu_name', t('Menu name'), $m['menu_name'], t('Must be unique, only seen by you'), '*'), + '$menu_desc' => array('menu_desc', t('Menu title'), $m['menu_desc'], t('Menu title as seen by others'), ''), + '$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), (($m['menu_flags'] & MENU_BOOKMARK) ? 1 : 0), t('Menu may be used to store saved bookmarks'), ''), + '$menu_system' => (($m['menu_flags'] & MENU_SYSTEM) ? 1 : 0), + '$submit' => t('Modify') + )); + + return $o; + } else { notice( t('Not found.') . EOL); diff --git a/mod/mitem.php b/mod/mitem.php index b561ec7d6..06c66a323 100644 --- a/mod/mitem.php +++ b/mod/mitem.php @@ -41,14 +41,17 @@ function mitem_post(&$a) { return; } - - if(! $a->data['menu']) return; $channel = $a->get_channel(); + if(!$_REQUEST['mitem_desc'] || !$_REQUEST['mitem_link']) { + notice( t('Unable to create element.') . EOL); + return; + } + $_REQUEST['mitem_channel_id'] = $uid; $_REQUEST['menu_id'] = $a->data['menu']['menu_id']; @@ -64,7 +67,7 @@ function mitem_post(&$a) { $_REQUEST['mitem_id'] = $mitem_id; $r = menu_edit_item($_REQUEST['menu_id'],$uid,$_REQUEST); if($r) { - info( t('Menu element updated.') . EOL); + //info( t('Menu element updated.') . EOL); goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . (($a->is_sys) ? '?f=&sys=1' : '')); } else @@ -74,8 +77,13 @@ function mitem_post(&$a) { else { $r = menu_add_item($_REQUEST['menu_id'],$uid,$_REQUEST); if($r) { - info( t('Menu element added.') . EOL); - goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . (($a->is_sys) ? '?f=&sys=1' : '')); + //info( t('Menu element added.') . EOL); + if($_REQUEST['submit']) { + goaway(z_root() . '/menu' . (($a->is_sys) ? '?f=&sys=1' : '')); + } + if($_REQUEST['submit-more']) { + goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . '?f=&display=block' . (($a->is_sys) ? '&sys=1' : '') ); + } } else notice( t('Unable to add menu element.') . EOL); @@ -84,6 +92,7 @@ function mitem_post(&$a) { + } @@ -115,6 +124,14 @@ function mitem_content(&$a) { $m = menu_fetch($a->data['menu']['menu_name'],$uid,$ob_hash); $a->data['menu_item'] = $m; + $perm_defaults = array( + 'allow_cid' => $channel['channel_allow_cid'], + 'allow_gid' => $channel['channel_allow_gid'], + 'deny_cid' => $channel['channel_deny_cid'], + 'deny_gid' => $channel['channel_deny_gid'] + ); + + $lockstate = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'); if(argc() == 2) { $r = q("select * from menu_item where mitem_menu_id = %d and mitem_channel_id = %d order by mitem_order asc, mitem_desc asc", @@ -122,61 +139,61 @@ function mitem_content(&$a) { intval($uid) ); + if($_GET['display']) { + $display = $_GET['display']; + } + else { + $display = (($r) ? 'none' : 'block'); + } + + $create = replace_macros(get_markup_template('mitemedit.tpl'), array( + '$menu_id' => $a->data['menu']['menu_id'], + '$permissions' => t('Menu Item Permissions'), + '$permdesc' => t("\x28click to open/close\x29"), + '$aclselect' => populate_acl($perm_defaults,false), + '$mitem_desc' => array('mitem_desc', t('Link Name'), '', 'Visible name of the link','*'), + '$mitem_link' => array('mitem_link', t('Link Target'), '', 'URL of the link', '*'), + '$usezid' => array('usezid', t('Use RedMatrix magic-auth if available'), true, ''), + '$newwin' => array('newwin', t('Open link in new window'), false,''), + '$mitem_order' => array('mitem_order', t('Order in list'),'0',t('Higher numbers will sink to bottom of listing')), + '$submit' => t('Submit and finish'), + '$submit_more' => t('Submit and continue'), + '$display' => $display, + '$lockstate' => $lockstate + )); $o .= replace_macros(get_markup_template('mitemlist.tpl'),array( - '$title' => t('Manage Menu Elements'), - '$menuname' => $a->data['menu']['menu_name'], - '$menudesc' => $a->data['menu']['menu_desc'], - '$edmenu' => t('Edit menu'), - '$menu_id' => $a->data['menu']['menu_id'], - '$mlist' => $r, - '$edit' => t('Edit element'), - '$drop' => t('Drop element'), - '$new' => t('New element'), - '$hintmenu' => t('Edit this menu container'), - '$hintnew' => t('Add menu element'), - '$hintdrop' => t('Delete this menu item'), - '$hintedit' => t('Edit this menu item') + '$title' => t('Menu:'), + '$create' => $create, + '$nametitle' => t('Link Name'), + '$targettitle' => t('Link Target'), + '$menuname' => $a->data['menu']['menu_name'], + '$menudesc' => $a->data['menu']['menu_desc'], + '$edmenu' => t('Edit menu'), + '$menu_id' => $a->data['menu']['menu_id'], + '$mlist' => $r, + '$edit' => t('Edit element'), + '$drop' => t('Drop element'), + '$new' => t('New element'), + '$hintmenu' => t('Edit this menu container'), + '$hintnew' => t('Add menu element'), + '$hintdrop' => t('Delete this menu item'), + '$hintedit' => t('Edit this menu item'), )); - + return $o; } if(argc() > 2) { - if(argv(2) === 'new') { - - $perm_defaults = array( - 'allow_cid' => $channel['channel_allow_cid'], - 'allow_gid' => $channel['channel_allow_gid'], - 'deny_cid' => $channel['channel_deny_cid'], - 'deny_gid' => $channel['channel_deny_gid'] - ); + if(intval(argv(2))) { - $o = replace_macros(get_markup_template('mitemedit.tpl'), array( - '$header' => t('New Menu Element'), - '$menu_id' => $a->data['menu']['menu_id'], - '$permissions' => t('Menu Item Permissions'), - '$permdesc' => t("\x28click to open/close\x29"), - '$aclselect' => populate_acl($perm_defaults,false), - '$mitem_desc' => array('mitem_desc', t('Link text'), '', '','*'), - '$mitem_link' => array('mitem_link', t('URL of link'), '', '', '*'), - '$usezid' => array('usezid', t('Use RedMatrix magic-auth if available'), true, ''), - '$newwin' => array('newwin', t('Open link in new window'), false,''), -// permissions go here - '$mitem_order' => array('mitem_order', t('Order in list'),'0',t('Higher numbers will sink to bottom of listing')), - '$submit' => t('Create') - )); - return $o; - } - - - elseif(intval(argv(2))) { $m = q("select * from menu_item where mitem_id = %d and mitem_channel_id = %d limit 1", intval(argv(2)), intval($uid) ); + if(! $m) { notice( t('Menu item not found.') . EOL); goaway(z_root() . '/menu'. (($a->is_sys) ? '?f=&sys=1' : '')); @@ -184,6 +201,8 @@ function mitem_content(&$a) { $mitem = $m[0]; + $lockstate = (($mitem['allow_cid'] || $mitem['allow_gid'] || $mitem['deny_cid'] || $mitem['deny_gid']) ? 'lock' : 'unlock'); + if(argc() == 4 && argv(3) == 'drop') { $r = menu_del_item($mitem['mitem_menu_id'], $uid, intval(argv(2))); if($r) @@ -193,27 +212,25 @@ function mitem_content(&$a) { goaway(z_root() . '/mitem/' . $mitem['mitem_menu_id'] . (($a->is_sys) ? '?f=&sys=1' : '')); } - else { - - // edit menu item - - $o = replace_macros(get_markup_template('mitemedit.tpl'), array( - '$header' => t('Edit Menu Element'), - '$menu_id' => $a->data['menu']['menu_id'], - '$permissions' => t('Menu Item Permissions'), - '$permdesc' => t("\x28click to open/close\x29"), - '$aclselect' => populate_acl($mitem,false), - '$mitem_id' => intval(argv(2)), - '$mitem_desc' => array('mitem_desc', t('Link text'), $mitem['mitem_desc'], '','*'), - '$mitem_link' => array('mitem_link', t('URL of link'), $mitem['mitem_link'], '', '*'), - '$usezid' => array('usezid', t('Use RedMatrix magic-auth if available'), (($mitem['mitem_flags'] & MENU_ITEM_ZID) ? 1 : 0), ''), - '$newwin' => array('newwin', t('Open link in new window'), (($mitem['mitem_flags'] & MENU_ITEM_NEWWIN) ? 1 : 0),''), -// permissions go here - '$mitem_order' => array('mitem_order', t('Order in list'),$mitem['mitem_order'],t('Higher numbers will sink to bottom of listing')), - '$submit' => t('Modify') - )); - return $o; - } + + // edit menu item + $o = replace_macros(get_markup_template('mitemedit.tpl'), array( + '$header' => t('Edit Menu Element'), + '$menu_id' => $a->data['menu']['menu_id'], + '$permissions' => t('Menu Item Permissions'), + '$permdesc' => t("\x28click to open/close\x29"), + '$aclselect' => populate_acl($mitem,false), + '$mitem_id' => intval(argv(2)), + '$mitem_desc' => array('mitem_desc', t('Link text'), $mitem['mitem_desc'], '','*'), + '$mitem_link' => array('mitem_link', t('URL of link'), $mitem['mitem_link'], '', '*'), + '$usezid' => array('usezid', t('Use RedMatrix magic-auth if available'), (($mitem['mitem_flags'] & MENU_ITEM_ZID) ? 1 : 0), ''), + '$newwin' => array('newwin', t('Open link in new window'), (($mitem['mitem_flags'] & MENU_ITEM_NEWWIN) ? 1 : 0),''), + '$mitem_order' => array('mitem_order', t('Order in list'),$mitem['mitem_order'],t('Higher numbers will sink to bottom of listing')), + '$submit' => t('Submit'), + '$lockstate' => $lockstate + )); + + return $o; } } } diff --git a/mod/network.php b/mod/network.php index dc67df37f..9ebdf7198 100644 --- a/mod/network.php +++ b/mod/network.php @@ -13,6 +13,12 @@ function network_init(&$a) { return; } + if((count($_GET) < 2) || (count($_GET) < 3 && $_GET['JS'])) { + $network_options = get_pconfig(local_channel(),'system','network_page_default'); + if($network_options) + goaway('network' . '?f=&' . $network_options); + } + $channel = $a->get_channel(); $a->profile_uid = local_channel(); head_set_icon($channel['xchan_photo_s']); @@ -21,12 +27,13 @@ function network_init(&$a) { function network_content(&$a, $update = 0, $load = false) { - if(! local_channel()) { $_SESSION['return_url'] = $a->query_string; return login(false); } + if($load) + $_SESSION['loadtime'] = datetime_convert(); $arr = array('query' => $a->query_string); @@ -110,16 +117,32 @@ function network_content(&$a, $update = 0, $load = false) { if(x($_GET,'search') || x($_GET,'file')) $nouveau = true; - if($cid) - $def_acl = array('allow_cid' => '<' . intval($cid) . '>'); - + if($cid) { + $r = q("SELECT abook_xchan FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1", + intval($cid), + intval(local_channel()) + ); + if(! $r) { + if($update) { + killme(); + } + notice( t('No such channel') . EOL ); + goaway($a->get_baseurl(true) . '/network'); + // NOTREACHED + } + $def_acl = array('allow_cid' => '<' . $r[0]['abook_xchan'] . '>'); + } if(! $update) { - $o .= network_tabs(); + $tabs = network_tabs(); + $o .= $tabs; // search terms header - if($search) - $o .= '<h2>' . t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT,'UTF-8') . '</h2>'; + if($search) { + $o .= replace_macros(get_markup_template("section_title.tpl"),array( + '$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT,'UTF-8') + )); + } nav_set_selected('network'); @@ -130,7 +153,6 @@ function network_content(&$a, $update = 0, $load = false) { 'deny_gid' => $channel['channel_deny_gid'] ); - $x = array( 'is_owner' => true, 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), @@ -143,8 +165,8 @@ function network_content(&$a, $update = 0, $load = false) { 'profile_uid' => local_channel() ); - $o .= status_editor($a,$x); - + $status_editor = status_editor($a,$x); + $o .= $status_editor; } @@ -180,9 +202,15 @@ function network_content(&$a, $update = 0, $load = false) { $x = group_rec_byhash(local_channel(), $group_hash); - if($x) - $o = '<h2>' . t('Collection: ') . $x['name'] . '</h2>' . $o; + if($x) { + $title = replace_macros(get_markup_template("section_title.tpl"),array( + '$title' => t('Collection: ') . $x['name'] + )); + } + $o = $tabs; + $o .= $title; + $o .= $status_editor; } @@ -194,7 +222,12 @@ function network_content(&$a, $update = 0, $load = false) { ); if($r) { $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) and item_restrict = 0 ) "; - $o = '<h2>' . t('Connection: ') . $r[0]['xchan_name'] . '</h2>' . $o; + $title = replace_macros(get_markup_template("section_title.tpl"),array( + '$title' => t('Connection: ') . $r[0]['xchan_name'] + )); + $o = $tabs; + $o .= $title; + $o .= $status_editor; } else { notice( t('Invalid connection.') . EOL); @@ -330,6 +363,8 @@ function network_content(&$a, $update = 0, $load = false) { } + $abook_uids = " and abook.abook_channel = " . local_channel() . " "; + if($firehose && (! get_config('system','disable_discover_tab'))) { require_once('include/identity.php'); $sys = get_sys_channel(); @@ -345,7 +380,7 @@ function network_content(&$a, $update = 0, $load = false) { else $page_mode = 'client'; - $simple_update = (($update) ? " and item.item_unseen = 1 " : ''); + $simple_update = (($update) ? " and item_unseen = 1 " : ''); // This fixes a very subtle bug so I'd better explain it. You wake up in the morning or return after a day // or three and look at your matrix page - after opening up your browser. The first page loads just as it @@ -360,7 +395,7 @@ function network_content(&$a, $update = 0, $load = false) { // which are both ITEM_UNSEEN and have "changed" since that time. Cross fingers... if($update && $_SESSION['loadtime']) - $simple_update .= " and item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' "; + $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) "; if($load) $simple_update = ''; @@ -368,10 +403,13 @@ function network_content(&$a, $update = 0, $load = false) { // "New Item View" - show all items unthreaded in reverse created date order $items = q("SELECT item.*, item.id AS item_id, received FROM item + left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) WHERE true $uids AND item_restrict = 0 + and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) $simple_update $sql_extra $sql_nets - ORDER BY item.received DESC $pager_sql " + ORDER BY item.received DESC $pager_sql ", + intval(ABOOK_FLAG_BLOCKED) ); require_once('include/items.php'); @@ -391,12 +429,10 @@ function network_content(&$a, $update = 0, $load = false) { if($load) { - $_SESSION['loadtime'] = datetime_convert(); - // Fetch a page full of parent items for this page $r = q("SELECT distinct item.id AS item_id, $ordering FROM item - left join abook on item.author_xchan = abook.abook_xchan + left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) WHERE true $uids AND item.item_restrict = 0 AND item.parent = item.id and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) @@ -407,16 +443,15 @@ function network_content(&$a, $update = 0, $load = false) { } else { - if(! $firehose) { - // update - $r = q("SELECT item.parent AS item_id FROM item - left join abook on item.author_xchan = abook.abook_xchan - WHERE true $uids AND item.item_restrict = 0 $simple_update - and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) - $sql_extra3 $sql_extra $sql_nets ", - intval(ABOOK_FLAG_BLOCKED) - ); - } + // this is an update + $r = q("SELECT item.parent AS item_id FROM item + left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) + WHERE true $uids AND item.item_restrict = 0 $simple_update + and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null) + $sql_extra3 $sql_extra $sql_nets ", + intval(ABOOK_FLAG_BLOCKED) + ); + $_SESSION['loadtime'] = datetime_convert(); } // Then fetch all the children of the parents that are on this page diff --git a/mod/openid.php b/mod/openid.php index b0f927f34..70da2690a 100644 --- a/mod/openid.php +++ b/mod/openid.php @@ -85,7 +85,7 @@ function openid_content(&$a) { $url = trim($_REQUEST['openid_identity'],'/'); if(strpos($url,'http') === false) $url = 'https://' . $url; - $pphoto = get_default_profile_photo(); + $pphoto = z_root() . '/' . get_default_profile_photo(); $parsed = @parse_url($url); if($parsed) { $host = $parsed['host']; diff --git a/mod/page.php b/mod/page.php index 1830b964b..eedfd472c 100644 --- a/mod/page.php +++ b/mod/page.php @@ -55,11 +55,12 @@ function page_init(&$a) { $sql_options = item_permissions_sql($u[0]['channel_id']); $r = q("select item.* from item left join item_id on item.id = item_id.iid - where item.uid = %d and sid = '%s' and service = 'WEBPAGE' and - item_type = %d $sql_options $revision limit 1", + where item.uid = %d and sid = '%s' and (( service = 'WEBPAGE' and item_type = %d ) + OR ( service = 'PDL' AND item_type = %d )) $sql_options $revision limit 1", intval($u[0]['channel_id']), dbesc($page_id), - intval(ITEM_TYPE_WEBPAGE) + intval(ITEM_TYPE_WEBPAGE), + intval(ITEM_PDL) ); if(! $r) { @@ -83,7 +84,12 @@ function page_init(&$a) { return; } - if($r[0]['layout_mid']) { + if($r[0]['item_restrict'] == ITEM_PDL) { + require_once('include/comanche.php'); + comanche_parser(get_app(),$r[0]['body']); + get_app()->pdl = $r[0]['body']; + } + elseif($r[0]['layout_mid']) { $l = q("select body from item where mid = '%s' and uid = %d limit 1", dbesc($r[0]['layout_mid']), intval($u[0]['channel_id']) @@ -92,13 +98,12 @@ function page_init(&$a) { if($l) { require_once('include/comanche.php'); comanche_parser(get_app(),$l[0]['body']); + get_app()->pdl = $l[0]['body']; } } $a->data['webpage'] = $r; - - } @@ -110,17 +115,11 @@ function page_content(&$a) { if(! $r) return; - // logger('layout: ' . print_r($a->layout,true)); - - // Use of widgets should be determined by Comanche, but we don't have it on system pages yet, so... - - // I recommend we now get rid of this bit - it's quite a hack to work around... - mike - - if ($perms['write_pages']) { - $chan = $a->channel['channel_id']; - $who = $channel_address; - $which = $r[0]['id']; - $o .= writepages_widget($who,$which); + if($r[0]['item_restrict'] == ITEM_PDL) { + $r[0]['body'] = t('Ipsum Lorem'); + $r[0]['mimetype'] = 'text/plain'; + $r[0]['title'] = ''; + } xchan_query($r); diff --git a/mod/parse_url.php b/mod/parse_url.php index 23d608411..b6c0559f9 100644 --- a/mod/parse_url.php +++ b/mod/parse_url.php @@ -1,5 +1,6 @@ <?php +require_once('include/oembed.php'); /* To-Do https://developers.google.com/+/plugins/snippet/ @@ -252,6 +253,42 @@ function parse_url_content(&$a) { logger('parse_url: ' . $url); + $result = z_fetch_url($url,false,0,array('novalidate' => true, 'nobody' => true)); + if($result['success']) { + $hdrs=array(); + $h = explode("\n",$result['header']); + foreach ($h as $l) { + list($k,$v) = array_map("trim", explode(":", trim($l), 2)); + $hdrs[$k] = $v; + } + if (array_key_exists('Content-Type', $hdrs)) + $type = $hdrs['Content-Type']; + if($type) { + $zrl = is_matrix_url($url); + if(stripos($type,'image/') !== false) { + if($zrl) + echo $br . '[zmg]' . $url . '[/zmg]' . $br; + else + echo $br . '[img]' . $url . '[/img]' . $br; + killme(); + } + if(stripos($type,'video/') !== false) { + if($zrl) + echo $br . '[zvideo]' . $url . '[/zvideo]' . $br; + else + echo $br . '[video]' . $url . '[/video]' . $br; + killme(); + } + if(stripos($type,'audio/') !== false) { + if($zrl) + echo $br . '[zaudio]' . $url . '[/zaudio]' . $br; + else + echo $br . '[audio]' . $url . '[/audio]' . $br; + killme(); + } + } + } + $template = $br . '#^[url=%s]%s[/url]%s' . $br; $arr = array('url' => $url, 'text' => ''); @@ -263,6 +300,11 @@ function parse_url_content(&$a) { killme(); } + $x = oembed_process($url); + if($x) { + echo $x; + killme(); + } if($url && $title && $text) { diff --git a/mod/photos.php b/mod/photos.php index c6ad92abc..7cbb798a8 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -542,7 +542,7 @@ function photos_content(&$a) { '$nickname' => $a->data['channel']['channel_address'], '$newalbum_label' => t('Enter a new album name'), '$newalbum_placeholder' => t('or select an existing one (doubleclick)'), - '$nosharetext' => t('Do not show a status post for this upload'), + '$visible' => array('visible', t('Create a status post for this upload'), 0, '', array(t('No'), t('Yes'))), '$albums' => $albums['albums'], '$selname' => $selname, '$permissions' => t('Permissions'), @@ -832,6 +832,8 @@ function photos_content(&$a) { dbesc($datum) ); + $map = null; + if($linked_items) { xchan_query($linked_items); @@ -871,6 +873,10 @@ function photos_content(&$a) { intval(local_channel()) ); } + + if($link_item['coord']) { + $map = generate_map($link_item['coord']); + } } // logger('mod_photo: link_item' . print_r($link_item,true)); @@ -963,14 +969,22 @@ function photos_content(&$a) { $like = ''; $dislike = ''; + $conv_responses = array( + 'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')), + 'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')), + 'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title')) + ); + + + if($r) { foreach($r as $item) { - like_puller($a,$item,$alike,'like'); - like_puller($a,$item,$dlike,'dislike'); + builtin_activity_puller($item, $conv_responses); } + $like_count = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid']] : ''); $like_list = ((x($alike,$link_item['mid'])) ? $alike[$link_item['mid'] . '-l'] : ''); if (count($like_list) > MAX_LIKERS) { @@ -1073,6 +1087,13 @@ function photos_content(&$a) { $dislike_e = $dislike; + $response_verbs = array('like'); + if(feature_enabled($owner_uid,'dislike')) + $response_verbs[] = 'dislike'; + + + $responses = get_responses($conv_responses,$response_verbs,'',$link_item); + $photo_tpl = get_markup_template('photo_view.tpl'); $o .= replace_macros($photo_tpl, array( '$id' => $link_item['id'], //$ph[0]['id'], @@ -1087,7 +1108,10 @@ function photos_content(&$a) { '$unknown' => t('Unknown'), '$tag_hdr' => t('In This Photo:'), '$tags' => $tags, + 'responses' => $responses, '$edit' => $edit, + '$map' => $map, + '$map_text' => t('Map'), '$likebuttons' => $likebuttons, '$like' => $like_e, '$dislike' => $dislike_e, diff --git a/mod/ping.php b/mod/ping.php index a15f4c925..f84bc498d 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -272,9 +272,8 @@ function ping_init(&$a) { $result = array(); $r = q("SELECT * FROM item - WHERE item_restrict = %d and item_unseen = 1 and uid = %d - and author_xchan != '%s' ORDER BY created DESC", - intval(ITEM_VISIBLE), + WHERE item_restrict = 0 and item_unseen = 1 and uid = %d + and author_xchan != '%s' ORDER BY created DESC limit 300", intval(local_channel()), dbesc($ob_hash) ); @@ -287,7 +286,7 @@ function ping_init(&$a) { $result[] = format_notification($item); } } - logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA); +// logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA); echo json_encode(array('notify' => $result)); killme(); } @@ -295,7 +294,7 @@ function ping_init(&$a) { if(argc() > 1 && (argv(1) === 'intros')) { $result = array(); - $r = q("SELECT * FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d) > 0 and not ((abook_flags & %d) > 0 or xchan_deleted = 1 or xchan_orphan = 1) ORDER BY abook_created DESC", + $r = q("SELECT * FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and (abook_flags & %d) > 0 and not ((abook_flags & %d) > 0 or xchan_deleted = 1 or xchan_orphan = 1) ORDER BY abook_created DESC LIMIT 50", intval(local_channel()), intval(ABOOK_FLAG_PENDING), intval(ABOOK_FLAG_SELF|ABOOK_FLAG_IGNORED) @@ -326,7 +325,7 @@ function ping_init(&$a) { $r = q("SELECT * FROM event left join xchan on event_xchan = xchan_hash WHERE `event`.`uid` = %d AND start < '%s' AND start > '%s' and `ignore` = 0 - ORDER BY `start` DESC ", + ORDER BY `start` DESC LIMIT 1000", intval(local_channel()), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval($evdays) . ' days')), dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) @@ -378,9 +377,8 @@ function ping_init(&$a) { if($vnotify & (VNOTIFY_NETWORK|VNOTIFY_CHANNEL)) { $r = q("SELECT id, item_restrict, item_flags FROM item - WHERE (item_restrict = %d) and item_unseen = 1 and uid = %d + WHERE (item_restrict = 0) and item_unseen = 1 and uid = %d and author_xchan != '%s'", - intval(ITEM_VISIBLE), intval(local_channel()), dbesc($ob_hash) ); diff --git a/mod/post.php b/mod/post.php index 14cdfd9be..fe0860cc6 100644 --- a/mod/post.php +++ b/mod/post.php @@ -1,20 +1,21 @@ -<?php /** @file */ +<?php /** - * Zot endpoint + * @file mod/post.php + * + * @brief Zot endpoint. + * */ - require_once('include/zot.php'); - -function post_init(&$a) { - - // Most access to this endpoint is via the post method. - // Here we will pick out the magic auth params which arrive - // as a get request, and the only communications to arrive this way. - /** + * @brief HTTP POST entry point for Zot. + * + * Most access to this endpoint is via the post method. + * Here we will pick out the magic auth params which arrive as a get request, + * and the only communications to arrive this way. + * * Magic Auth * ========== * @@ -24,75 +25,79 @@ function post_init(&$a) { * The endpoint is typically https://$remotesite/post - or whatever was specified as the callback url in prior communications * (we will bootstrap an address and fetch a zot info packet if possible where no prior communications exist) * - * Four GET parameters are supplied: - * - ** auth => the urlencoded webbie (channel@host.domain) of the channel requesting access - ** dest => the desired destination URL (urlencoded) - ** sec => a random string which is also stored on $mysite for use during the verification phase. - ** version => the zot revision + * Five GET parameters are supplied: + * * auth => the urlencoded webbie (channel@host.domain) of the channel requesting access + * * dest => the desired destination URL (urlencoded) + * * sec => a random string which is also stored on $mysite for use during the verification phase. + * * version => the zot revision + * * delegate => optional urlencoded webbie of a local channel to invoke delegation rights for * * When this packet is received, an "auth-check" zot message is sent to $mysite. * (e.g. if $_GET['auth'] is foobar@podunk.edu, a zot packet is sent to the podunk.edu zot endpoint, which is typically /post) * If no information has been recorded about the requesting identity a zot information packet will be retrieved before * continuing. - * + * * The sender of this packet is an arbitrary/random site channel. The recipients will be a single recipient corresponding * to the guid and guid_sig we have associated with the requesting auth identity * - * - * { - * "type":"auth_check", - * "sender":{ - * "guid":"kgVFf_...", - * "guid_sig":"PT9-TApz...", - * "url":"http:\/\/podunk.edu", - * "url_sig":"T8Bp7j..." - * }, - * "recipients":{ - * { - * "guid":"ZHSqb...", - * "guid_sig":"JsAAXi..." - * } - * } - * "callback":"\/post", - * "version":1, - * "secret":"1eaa661", - * "secret_sig":"eKV968b1..." - * } - * + * \code{.json} + * { + * "type":"auth_check", + * "sender":{ + * "guid":"kgVFf_...", + * "guid_sig":"PT9-TApz...", + * "url":"http:\/\/podunk.edu", + * "url_sig":"T8Bp7j..." + * }, + * "recipients":{ + * { + * "guid":"ZHSqb...", + * "guid_sig":"JsAAXi..." + * } + * } + * "callback":"\/post", + * "version":1, + * "secret":"1eaa661", + * "secret_sig":"eKV968b1..." + * } + * \endcode * * auth_check messages MUST use encapsulated encryption. This message is sent to the origination site, which checks the 'secret' to see * if it is the same as the 'sec' which it passed originally. It also checks the secret_sig which is the secret signed by the * destination channel's private key and base64url encoded. If everything checks out, a json packet is returned: * - * { - * "success":1, - * "confirm":"q0Ysovd1u..." - * "service_class":(optional) - * "level":(optional) - * } + * \code{.json} + * { + * "success":1, + * "confirm":"q0Ysovd1u...", + * "service_class":(optional) + * "level":(optional) + * } + * \endcode * * 'confirm' in this case is the base64url encoded RSA signature of the concatenation of 'secret' with the * base64url encoded whirlpool hash of the requestor's guid and guid_sig; signed with the source channel private key. * This prevents a man-in-the-middle from inserting a rogue success packet. Upon receipt and successful * verification of this packet, the destination site will redirect to the original destination URL and indicate a successful remote login. * Service_class can be used by cooperating sites to provide different access rights based on account rights and subscription plans. It is - * a string whose contents are not defined by protocol. Example: "basic" or "gold". - * - * + * a string whose contents are not defined by protocol. Example: "basic" or "gold". * + * @param[in,out] App &$a */ - - if(array_key_exists('auth',$_REQUEST)) { +function post_init(&$a) { + + if (array_key_exists('auth', $_REQUEST)) { $ret = array('success' => false, 'message' => ''); logger('mod_zot: auth request received.'); - $address = $_REQUEST['auth']; - $desturl = $_REQUEST['dest']; - $sec = $_REQUEST['sec']; - $version = $_REQUEST['version']; - $test = ((x($_REQUEST,'test')) ? intval($_REQUEST['test']) : 0); + $address = $_REQUEST['auth']; + $desturl = $_REQUEST['dest']; + $sec = $_REQUEST['sec']; + $version = $_REQUEST['version']; + $delegate = $_REQUEST['delegate']; + + $test = ((x($_REQUEST, 'test')) ? intval($_REQUEST['test']) : 0); // They are authenticating ultimately to the site and not to a particular channel. // Any channel will do, providing it's currently active. We just need to have an @@ -102,10 +107,10 @@ function post_init(&$a) { intval(PAGE_REMOVED) ); - if(! $c) { + if (! $c) { // nobody here logger('mod_zot: auth: unable to find a response channel'); - if($test) { + if ($test) { $ret['message'] .= 'no local channels found.' . EOL; json_return_and_die($ret); } @@ -118,12 +123,12 @@ function post_init(&$a) { dbesc($address) ); - if(! $x) { + if (! $x) { // finger them if they can't be found. - $ret = zot_finger($address,null); - if($ret['success']) { - $j = json_decode($ret['body'],true); - if($j) + $ret = zot_finger($address, null); + if ($ret['success']) { + $j = json_decode($ret['body'], true); + if ($j) import_xchan($j); $x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' order by hubloc_id desc limit 1", dbesc($address) @@ -158,64 +163,65 @@ function post_init(&$a) { // Also check that they are coming from the same site as they authenticated with originally. $already_authed = ((($remote) && ($x[0]['hubloc_hash'] == $remote) && ($x[0]['hubloc_url'] === $_SESSION['remote_hub'])) ? true : false); + if($delegate && $delegate !== $_SESSION['delegate_channel']) + $already_authed = false; $j = array(); - if(! $already_authed) { + if (! $already_authed) { // Auth packets MUST use ultra top-secret hush-hush mode - e.g. the entire packet is encrypted using the site private key // The actual channel sending the packet ($c[0]) is not important, but this provides a generic zot packet with a sender // which can be verified $p = zot_build_packet($c[0],$type = 'auth_check', array(array('guid' => $x[0]['hubloc_guid'],'guid_sig' => $x[0]['hubloc_guid_sig'])), $x[0]['hubloc_sitekey'], $sec); - if($test) { + if ($test) { $ret['message'] .= 'auth check packet created using sitekey ' . $x[0]['hubloc_sitekey'] . EOL; $ret['message'] .= 'packet contents: ' . $p . EOL; } $result = zot_zot($x[0]['hubloc_callback'],$p); - - if(! $result['success']) { + if (! $result['success']) { logger('mod_zot: auth_check callback failed.'); - if($test) { + if ($test) { $ret['message'] .= 'auth check request to your site returned .' . print_r($result, true) . EOL; json_return_and_die($ret); } goaway($desturl); } - $j = json_decode($result['body'],true); - if(! $j) { + $j = json_decode($result['body'], true); + if (! $j) { logger('mod_zot: auth_check json data malformed.'); if($test) { $ret['message'] .= 'json malformed: ' . $result['body'] . EOL; json_return_and_die($ret); } - } + } } - if($test) { + if ($test) { $ret['message'] .= 'auth check request returned .' . print_r($j, true) . EOL; - } + } - if($already_authed || $j['success']) { - if($j['success']) { + if ($already_authed || $j['success']) { + if ($j['success']) { // legit response, but we do need to check that this wasn't answered by a man-in-middle - if(! rsa_verify($sec . $x[0]['xchan_hash'],base64url_decode($j['confirm']),$x[0]['xchan_pubkey'])) { + if (! rsa_verify($sec . $x[0]['xchan_hash'],base64url_decode($j['confirm']),$x[0]['xchan_pubkey'])) { logger('mod_zot: auth: final confirmation failed.'); - if($test) { + if ($test) { $ret['message'] .= 'final confirmation failed. ' . $sec . print_r($j,true) . print_r($x[0],true); json_return_and_die($ret); } - + goaway($desturl); } - if(array_key_exists('service_class',$j)) + if (array_key_exists('service_class',$j)) $remote_service_class = $j['service_class']; - if(array_key_exists('level',$j)) + if (array_key_exists('level',$j)) $remote_level = $j['level']; - if(array_key_exists('DNT',$j)) + if (array_key_exists('DNT',$j)) $DNT = $j['DNT']; } // everything is good... maybe @@ -224,35 +230,54 @@ function post_init(&$a) { // tell them to logout if they're logged in locally as anything but the target remote account // in which case just shut up because they don't need to be doing this at all. - if($a->channel['channel_hash'] != $x[0]['xchan_hash']) { + if ($a->channel['channel_hash'] != $x[0]['xchan_hash']) { logger('mod_zot: auth: already authenticated locally as somebody else.'); notice( t('Remote authentication blocked. You are logged into this site locally. Please logout and retry.') . EOL); - if($test) { + if ($test) { $ret['message'] .= 'already logged in locally with a conflicting identity.' . EOL; json_return_and_die($ret); } - } goaway($desturl); } + // log them in - if($test) { + if ($test) { $ret['success'] = true; $ret['message'] .= 'Authentication Success!' . EOL; json_return_and_die($ret); } + $delegation_success = false; + if ($delegate) { + $r = q("select * from channel left join xchan on channel_hash = xchan_hash where xchan_addr = '%s' limit 1", + dbesc($delegate) + ); + if ($r && intval($r[0]['channel_id'])) { + $allowed = perm_is_allowed($r[0]['channel_id'],$x[0]['xchan_hash'],'delegate'); + if ($allowed) { + $_SESSION['delegate_channel'] = $r[0]['channel_id']; + $_SESSION['delegate'] = $x[0]['xchan_hash']; + $_SESSION['account_id'] = intval($r[0]['channel_account_id']); + require_once('include/security.php'); + change_channel($r[0]['channel_id']); + $delegation_success = true; + } + } + } $_SESSION['authenticated'] = 1; - $_SESSION['visitor_id'] = $x[0]['xchan_hash']; - $_SESSION['my_url'] = $x[0]['xchan_url']; - $_SESSION['my_address'] = $address; - $_SESSION['remote_service_class'] = $remote_service_class; - $_SESSION['remote_level'] = $remote_level; - $_SESSION['remote_hub'] = $remote_hub; - $_SESSION['DNT'] = $DNT; - + if (! $delegation_success) { + $_SESSION['visitor_id'] = $x[0]['xchan_hash']; + $_SESSION['my_url'] = $x[0]['xchan_url']; + $_SESSION['my_address'] = $address; + $_SESSION['remote_service_class'] = $remote_service_class; + $_SESSION['remote_level'] = $remote_level; + $_SESSION['remote_hub'] = $remote_hub; + $_SESSION['DNT'] = $DNT; + } + $arr = array('xchan' => $x[0], 'url' => $desturl, 'session' => $_SESSION); call_hooks('magic_auth_success',$arr); $a->set_observer($x[0]); @@ -260,22 +285,23 @@ function post_init(&$a) { $a->set_groups(init_groups_visitor($_SESSION['visitor_id'])); info(sprintf( t('Welcome %s. Remote authentication successful.'),$x[0]['xchan_name'])); logger('mod_zot: auth success from ' . $x[0]['xchan_addr']); - } else { if($test) { $ret['message'] .= 'auth failure. ' . print_r($_REQUEST,true) . print_r($j,true) . EOL; json_return_and_die($ret); } - logger('mod_zot: magic-auth failure - not authenticated: ' . $x[0]['xchan_addr']); } - // FIXME - we really want to save the return_url in the session before we visit rmagic. - // This does however prevent a recursion if you visit rmagic directly, as it would otherwise send you back here again. - // But z_root() probably isn't where you really want to go. + /** + * @FIXME we really want to save the return_url in the session before we + * visit rmagic. This does however prevent a recursion if you visit + * rmagic directly, as it would otherwise send you back here again. + * But z_root() probably isn't where you really want to go. + */ - if($test) { + if ($test) { $ret['message'] .= 'auth failure fallthrough ' . print_r($_REQUEST,true) . print_r($j,true) . EOL; json_return_and_die($ret); } @@ -285,41 +311,40 @@ function post_init(&$a) { goaway($desturl); } - return; } /** - * @function post_post(&$a) - * zot communications and messaging + * @brief zot communications and messaging. * - * Sender HTTP posts to this endpoint ($site/post typically) with 'data' parameter set to json zot message packet. - * This packet is optionally encrypted, which we will discover if the json has an 'iv' element. - * $contents => array( 'alg' => 'aes256cbc', 'iv' => initialisation vector, 'key' => decryption key, 'data' => encrypted data); - * $contents->iv and $contents->key are random strings encrypted with this site's RSA public key and then base64url encoded. - * Currently only 'aes256cbc' is used, but this is extensible should that algorithm prove inadequate. + * Sender HTTP posts to this endpoint ($site/post typically) with 'data' parameter set to json zot message packet. + * This packet is optionally encrypted, which we will discover if the json has an 'iv' element. + * $contents => array( 'alg' => 'aes256cbc', 'iv' => initialisation vector, 'key' => decryption key, 'data' => encrypted data); + * $contents->iv and $contents->key are random strings encrypted with this site's RSA public key and then base64url encoded. + * Currently only 'aes256cbc' is used, but this is extensible should that algorithm prove inadequate. * - * Once decrypted, one will find the normal json_encoded zot message packet. + * Once decrypted, one will find the normal json_encoded zot message packet. * * Defined packet types are: notify, purge, refresh, force_refresh, auth_check, ping, and pickup * * Standard packet: (used by notify, purge, refresh, force_refresh, and auth_check) - * + * \code{.json} * { - * "type": "notify", - * "sender":{ - * "guid":"kgVFf_1...", - * "guid_sig":"PT9-TApzp...", - * "url":"http:\/\/podunk.edu", - * "url_sig":"T8Bp7j5...", - * }, - * "recipients": { optional recipient array }, - * "callback":"\/post", - * "version":1, - * "secret":"1eaa...", - * "secret_sig": "df89025470fac8..." + * "type": "notify", + * "sender":{ + * "guid":"kgVFf_1...", + * "guid_sig":"PT9-TApzp...", + * "url":"http:\/\/podunk.edu", + * "url_sig":"T8Bp7j5...", + * }, + * "recipients": { optional recipient array }, + * "callback":"\/post", + * "version":1, + * "secret":"1eaa...", + * "secret_sig": "df89025470fac8..." * } - * + * \endcode + * * Signature fields are all signed with the sender channel private key and base64url encoded. * Recipients are arrays of guid and guid_sig, which were previously signed with the recipients private * key and base64url encoded and later obtained via channel discovery. Absence of recipients indicates @@ -327,108 +352,116 @@ function post_init(&$a) { * * "pickup" packet: * The pickup packet is sent in response to a notify packet from another site - * + * \code{.json} * { - * "type":"pickup", - * "url":"http:\/\/example.com", - * "callback":"http:\/\/example.com\/post", - * "callback_sig":"teE1_fLI...", - * "secret":"1eaa...", - * "secret_sig":"O7nB4_..." + * "type":"pickup", + * "url":"http:\/\/example.com", + * "callback":"http:\/\/example.com\/post", + * "callback_sig":"teE1_fLI...", + * "secret":"1eaa...", + * "secret_sig":"O7nB4_..." * } + * \endcode * - * In the pickup packet, the sig fields correspond to the respective data element signed with this site's system - * private key and then base64url encoded. + * In the pickup packet, the sig fields correspond to the respective data + * element signed with this site's system private key and then base64url encoded. * The "secret" is the same as the original secret from the notify packet. * - * If verification is successful, a json structure is returned - * containing a success indicator and an array of type 'pickup'. - * Each pickup element contains the original notify request and a message field whose contents are - * dependent on the message type + * If verification is successful, a json structure is returned containing a + * success indicator and an array of type 'pickup'. + * Each pickup element contains the original notify request and a message field + * whose contents are dependent on the message type. * - * This JSON array is AES encapsulated using the site public key of the site that sent the initial zot pickup packet. + * This JSON array is AES encapsulated using the site public key of the site + * that sent the initial zot pickup packet. * Using the above example, this would be example.com. - * - * + * + * \code{.json} * { - * "success":1, - * "pickup":{ - * "notify":{ - * "type":"notify", - * "sender":{ - * "guid":"kgVFf_...", - * "guid_sig":"PT9-TApz...", - * "url":"http:\/\/z.podunk.edu", - * "url_sig":"T8Bp7j5D..." - * }, - * "callback":"\/post", - * "version":1, - * "secret":"1eaa661..." - * }, - * "message":{ - * "type":"activity", - * "message_id":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", - * "message_top":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", - * "message_parent":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", - * "created":"2012-11-20 04:04:16", - * "edited":"2012-11-20 04:04:16", - * "title":"", - * "body":"Hi Nickordo", - * "app":"", - * "verb":"post", - * "object_type":"", - * "target_type":"", - * "permalink":"", - * "location":"", - * "longlat":"", - * "owner":{ - * "name":"Indigo", - * "address":"indigo@podunk.edu", - * "url":"http:\/\/podunk.edu", - * "photo":{ - * "mimetype":"image\/jpeg", - * "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" + * "success":1, + * "pickup":{ + * "notify":{ + * "type":"notify", + * "sender":{ + * "guid":"kgVFf_...", + * "guid_sig":"PT9-TApz...", + * "url":"http:\/\/z.podunk.edu", + * "url_sig":"T8Bp7j5D..." * }, - * "guid":"kgVFf_...", - * "guid_sig":"PT9-TAp...", + * "callback":"\/post", + * "version":1, + * "secret":"1eaa661..." * }, - * "author":{ - * "name":"Indigo", - * "address":"indigo@podunk.edu", - * "url":"http:\/\/podunk.edu", - * "photo":{ - * "mimetype":"image\/jpeg", - * "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" + * "message":{ + * "type":"activity", + * "message_id":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", + * "message_top":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", + * "message_parent":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", + * "created":"2012-11-20 04:04:16", + * "edited":"2012-11-20 04:04:16", + * "title":"", + * "body":"Hi Nickordo", + * "app":"", + * "verb":"post", + * "object_type":"", + * "target_type":"", + * "permalink":"", + * "location":"", + * "longlat":"", + * "owner":{ + * "name":"Indigo", + * "address":"indigo@podunk.edu", + * "url":"http:\/\/podunk.edu", + * "photo":{ + * "mimetype":"image\/jpeg", + * "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" + * }, + * "guid":"kgVFf_...", + * "guid_sig":"PT9-TAp...", * }, - * "guid":"kgVFf_...", - * "guid_sig":"PT9-TAp..." + * "author":{ + * "name":"Indigo", + * "address":"indigo@podunk.edu", + * "url":"http:\/\/podunk.edu", + * "photo":{ + * "mimetype":"image\/jpeg", + * "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" + * }, + * "guid":"kgVFf_...", + * "guid_sig":"PT9-TAp..." + * } * } * } * } - *} + * \endcode * - * Currently defined message types are 'activity', 'mail', 'profile', 'location' and 'channel_sync', - * which each have different content schemas. + * Currently defined message types are 'activity', 'mail', 'profile', 'location' + * and 'channel_sync', which each have different content schemas. * * Ping packet: - * A ping packet does not require any parameters except the type. It may or may not be encrypted. - * + * A ping packet does not require any parameters except the type. It may or may + * not be encrypted. + * + * \code{.json} * { - * "type": "ping" + * "type": "ping" * } - * + * \endcode + * * On receipt of a ping packet a ping response will be returned: * + * \code{.json} * { * "success" : 1, * "site" { - * "url":"http:\/\/podunk.edu", - * "url_sig":"T8Bp7j5...", - * "sitekey": "-----BEGIN PUBLIC KEY----- - * MIICIjANBgkqhkiG9w0BAQE..." - * } + * "url": "http:\/\/podunk.edu", + * "url_sig": "T8Bp7j5...", + * "sitekey": "-----BEGIN PUBLIC KEY----- + * MIICIjANBgkqhkiG9w0BAQE..." + * } * } - * + * \endcode + * * The ping packet can be used to verify that a site has not been re-installed, and to * initiate corrective action if it has. The url_sig is signed with the site private key * and base64url encoded - and this should verify with the enclosed sitekey. Failure to @@ -442,24 +475,22 @@ function post_init(&$a) { * If you have no records which match this url_sig and key - no corrective action should * be taken as this packet may have been returned by an imposter. * + * @param[in,out] App &$a */ - - function post_post(&$a) { - $encrypted_packet = false; $ret = array('success' => false); $data = json_decode($_REQUEST['data'],true); - - /** - * Many message packets will arrive encrypted. The existence of an 'iv' element - * tells us we need to unencapsulate the AES-256-CBC content using the site private key + /* + * Many message packets will arrive encrypted. The existence of an 'iv' + * element tells us we need to unencapsulate the AES-256-CBC content using + * the site private key. */ - if(array_key_exists('iv',$data)) { + if($data && array_key_exists('iv',$data)) { $encrypted_packet = true; $data = crypto_unencapsulate($data,get_config('system','prvkey')); logger('mod_zot: decrypt1: ' . $data, LOGGER_DATA); @@ -502,12 +533,11 @@ function post_post(&$a) { if($msgtype === 'pickup') { - /** + /* * The 'pickup' message arrives with a tracking ID which is associated with a particular outq_hash * First verify that that the returned signatures verify, then check that we have an outbound queue item * with the correct hash. * If everything verifies, find any/all outbound messages in the queue for this hubloc and send them back - * */ if((! $data['secret']) || (! $data['secret_sig'])) { @@ -560,7 +590,7 @@ function post_post(&$a) { json_return_and_die($ret); } - /** + /* * If we made it to here, the signatures verify, but we still don't know if the tracking ID is valid. * It wouldn't be an error if the tracking ID isn't found, because we may have sent this particular * queue item with another pickup (after the tracking ID for the other pickup was verified). @@ -576,7 +606,7 @@ function post_post(&$a) { json_return_and_die($ret); } - /** + /* * Everything is good if we made it here, so find all messages that are going to this location * and send them all. */ @@ -585,7 +615,7 @@ function post_post(&$a) { dbesc($data['callback']) ); if($r) { - logger('mod_zot: succesful pickup message received from ' . $data['callback'] . ' ' . count($r) . ' message(s) picked up', LOGGER_DEBUG); + logger('mod_zot: successful pickup message received from ' . $data['callback'] . ' ' . count($r) . ' message(s) picked up', LOGGER_DEBUG); $ret['success'] = true; $ret['pickup'] = array(); @@ -614,33 +644,31 @@ function post_post(&$a) { $encrypted = crypto_encapsulate(json_encode($ret),$sitekey); json_return_and_die($encrypted); - /** pickup: end */ + /* pickup: end */ } - - - /** + /* * All other message types require us to verify the sender. This is a generic check, so we * will do it once here and bail if anything goes wrong. */ - if(array_key_exists('sender',$data)) { + if (array_key_exists('sender',$data)) { $sender = $data['sender']; - } + } - /** Check if the sender is already verified here */ + /* Check if the sender is already verified here */ $hub = zot_gethub($sender); - if(! $hub) { + if (! $hub) { - /** Have never seen this guid or this guid coming from this location. Check it and register it. */ + /* Have never seen this guid or this guid coming from this location. Check it and register it. */ // (!!) this will validate the sender $result = zot_register_hub($sender); - if((! $result['success']) || (! ($hub = zot_gethub($sender)))) { + if ((! $result['success']) || (! ($hub = zot_gethub($sender)))) { $ret['message'] = 'Hub not available.'; logger('mod_zot: no hub'); json_return_and_die($ret); @@ -670,15 +698,13 @@ function post_post(&$a) { q("update xchan set xchan_orphan = 0 where xchan_orphan = 1 and xchan_hash = '%s'", dbesc($hub['hubloc_hash']) ); - } - + } - /** + /* * This hub has now been proven to be valid. * Any hub with the same URL and a different sitekey cannot be valid. * Get rid of them (mark them deleted). There's a good chance they were re-installs. - * */ q("update hubloc set hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s' ", @@ -686,15 +712,15 @@ function post_post(&$a) { dbesc($hub['hubloc_sitekey']) ); - // TODO: check which hub is primary and take action if mismatched + /** @TODO check which hub is primary and take action if mismatched */ - if(array_key_exists('recipients',$data)) + if (array_key_exists('recipients', $data)) $recipients = $data['recipients']; - if($msgtype === 'auth_check') { + if ($msgtype === 'auth_check') { - /** + /* * Requestor visits /magic/?dest=somewhere on their own site with a browser * magic redirects them to $destsite/post [with auth args....] * $destsite sends an auth_check packet to originator site @@ -709,12 +735,12 @@ function post_post(&$a) { */ logger('mod_zot: auth_check', LOGGER_DEBUG); - if(! $encrypted_packet) { + if (! $encrypted_packet) { logger('mod_zot: auth_check packet was not encrypted.'); $ret['message'] .= 'no packet encryption' . EOL; json_return_and_die($ret); } - + $arr = $data['sender']; $sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); @@ -732,7 +758,7 @@ function post_post(&$a) { // First verify their signature. We will have obtained a zot-info packet from them as part of the sender // verification. - if((! $y) || (! rsa_verify($data['secret'],base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) { + if ((! $y) || (! rsa_verify($data['secret'], base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) { logger('mod_zot: auth_check: sender not found or secret_sig invalid.'); $ret['message'] .= 'sender not found or sig invalid ' . print_r($y,true) . EOL; json_return_and_die($ret); @@ -742,14 +768,14 @@ function post_post(&$a) { $ret['message'] .= 'recipients ' . print_r($recipients,true) . EOL; - if($data['recipients']) { + if ($data['recipients']) { $arr = $data['recipients'][0]; - $recip_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); + $recip_hash = make_xchan_hash($arr['guid'], $arr['guid_sig']); $c = q("select channel_id, channel_account_id, channel_prvkey from channel where channel_hash = '%s' limit 1", dbesc($recip_hash) ); - if(! $c) { + if (! $c) { logger('mod_zot: auth_check: recipient channel not found.'); $ret['message'] .= 'recipient not found.' . EOL; json_return_and_die($ret); @@ -765,7 +791,7 @@ function post_post(&$a) { dbesc($data['secret']), dbesc($data['sender']['url']) ); - if(! $z) { + if (! $z) { logger('mod_zot: auth_check: verification key not found.'); $ret['message'] .= 'verification key not found' . EOL; json_return_and_die($ret); @@ -781,70 +807,66 @@ function post_post(&$a) { logger('mod_zot: auth_check: success', LOGGER_DEBUG); $ret['success'] = true; $ret['confirm'] = $confirm; - if($u && $u[0]['account_service_class']) + if ($u && $u[0]['account_service_class']) $ret['service_class'] = $u[0]['account_service_class']; // Set "do not track" flag if this site or this channel's profile is restricted // in some way - if(intval(get_config('system','block_public'))) + if (intval(get_config('system','block_public'))) $ret['DNT'] = true; - if(! perm_is_allowed($c[0]['channel_id'],'','view_profile')) + if (! perm_is_allowed($c[0]['channel_id'],'','view_profile')) $ret['DNT'] = true; - if(get_pconfig($c[0]['channel_id'],'system','do_not_track')) + if (get_pconfig($c[0]['channel_id'],'system','do_not_track')) $ret['DNT'] = true; - if(get_pconfig($c[0]['channel_id'],'system','hide_online_status')) + if (get_pconfig($c[0]['channel_id'],'system','hide_online_status')) $ret['DNT'] = true; json_return_and_die($ret); - } json_return_and_die($ret); } - if($msgtype === 'request') { + if ($msgtype === 'request') { // request a particular post/conversation by message_id $x = zot_process_message_request($data); json_return_and_die($x); } - - if($msgtype === 'purge') { - if($recipients) { + if ($msgtype === 'purge') { + if ($recipients) { // basically this means "unfriend" - foreach($recipients as $recip) { + foreach ($recipients as $recip) { $r = q("select channel.*,xchan.* from channel left join xchan on channel_hash = xchan_hash where channel_guid = '%s' and channel_guid_sig = '%s' limit 1", dbesc($recip['guid']), dbesc($recip['guid_sig']) ); - if($r) { + if ($r) { $r = q("select abook_id from abook where uid = %d and abook_xchan = '%s' limit 1", intval($r[0]['channel_id']), dbesc(make_xchan_hash($sender['guid'],$sender['guid_sig'])) ); - if($r) { + if ($r) { contact_remove($r[0]['channel_id'],$r[0]['abook_id']); } } } - } - else { + } else { // Unfriend everybody - basically this means the channel has committed suicide $arr = $data['sender']; $sender_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); - + require_once('include/Contact.php'); remove_all_xchan_resources($sender_hash); $ret['success'] = true; json_return_and_die($ret); - } } - if(($msgtype === 'refresh') || ($msgtype === 'force_refresh')) { + if (($msgtype === 'refresh') || ($msgtype === 'force_refresh')) { // remote channel info (such as permissions or photo or something) // has been updated. Grab a fresh copy and sync it. @@ -852,11 +874,11 @@ function post_post(&$a) { // force_refresh unconditionally creates a directory update record, // even if no changes were detected upon processing. - if($recipients) { + if ($recipients) { // This would be a permissions update, typically for one connection - foreach($recipients as $recip) { + foreach ($recipients as $recip) { $r = q("select channel.*,xchan.* from channel left join xchan on channel_hash = xchan_hash where channel_guid = '%s' and channel_guid_sig = '%s' limit 1", @@ -868,44 +890,41 @@ function post_post(&$a) { 'xchan_guid' => $sender['guid'], 'xchan_guid_sig' => $sender['guid_sig'], 'hubloc_url' => $sender['url'] - ),$r[0], (($msgtype === 'force_refresh') ? true : false)); + ), $r[0], (($msgtype === 'force_refresh') ? true : false)); } - } - else { + } else { // system wide refresh - + $x = zot_refresh(array( 'xchan_guid' => $sender['guid'], 'xchan_guid_sig' => $sender['guid_sig'], 'hubloc_url' => $sender['url'] - ),null,(($msgtype === 'force_refresh') ? true : false)); + ), null, (($msgtype === 'force_refresh') ? true : false)); } $ret['success'] = true; json_return_and_die($ret); } - if($msgtype === 'notify') { + if ($msgtype === 'notify') { + + logger('notify received from ' . $hub['hubloc_url']); + + $async = get_config('system','queued_fetch'); - if($async) { + if ($async) { // add to receive queue // qreceive_add($data); - } - else { + } else { $x = zot_fetch($data); $ret['delivery_report'] = $x; } $ret['success'] = true; json_return_and_die($ret); - } - // catchall json_return_and_die($ret); - - } - diff --git a/mod/pubsites.php b/mod/pubsites.php index c31bbcf97..ff3854492 100644 --- a/mod/pubsites.php +++ b/mod/pubsites.php @@ -22,10 +22,13 @@ function pubsites_content(&$a) { if($ret['success']) { $j = json_decode($ret['body'],true); if($j) { - $o .= '<table border="1"><tr><td>' . t('Site URL') . '</td><td>' . t('Access Type') . '</td><td>' . t('Registration Policy') . '</td><td>' . t('Location') . '</td></tr>'; + $rate_meta = ((local_channel()) ? '<td>' . t('Rate this hub') . '</td>' : ''); + $o .= '<table border="1"><tr><td>' . t('Site URL') . '</td><td>' . t('Access Type') . '</td><td>' . t('Registration Policy') . '</td><td>' . t('Location') . '</td><td>' . t('View hub ratings') . '</td>' . $rate_meta . '</tr>'; if($j['sites']) { foreach($j['sites'] as $jj) { - $o .= '<tr><td>' . '<a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" >' . $jj['url'] . '</a>' . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><td>' . $jj['location'] . '</td></tr>'; + $host = strtolower(substr($jj['url'],strpos($jj['url'],'://')+3)); + $rate_links = ((local_channel()) ? '<td><a href="rate?f=&target=' . $host . '" class="btn-btn-default"><i class="icon-check"></i> ' . t('Rate') . '</a></td>' : ''); + $o .= '<tr><td>' . '<a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" >' . $jj['url'] . '</a>' . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><td>' . $jj['location'] . '</td><td><a href="ratings/' . $host . '" class="btn-btn-default"><i class="icon-eye-open"></i> ' . t('View ratings') . '</a></td>' . $rate_links . '</tr>'; } } diff --git a/mod/randprof.php b/mod/randprof.php index bddb3251a..9817685c8 100644 --- a/mod/randprof.php +++ b/mod/randprof.php @@ -6,6 +6,7 @@ function randprof_init(&$a) { $x = random_profile(); if($x) goaway(chanlink_url($x)); - // FIXME this doesn't work at the moment as a fallback + + /** FIXME this doesn't work at the moment as a fallback */ goaway($a->get_baseurl() . '/profile'); } diff --git a/mod/rate.php b/mod/rate.php index 694b88ddd..a3a36b4a9 100644 --- a/mod/rate.php +++ b/mod/rate.php @@ -21,6 +21,15 @@ function rate_init(&$a) { if($r) { $a->poi = $r[0]; } + else { + $r = q("select * from site where site_url like '%s' ", + dbesc('%' . $target) + ); + if($r) { + $a->data['site'] = $r[0]; + $a->data['site']['site_url'] = strtolower($r[0]['site_url']); + } + } } @@ -119,12 +128,15 @@ function rate_content(&$a) { dbesc($channel['channel_hash']), dbesc($a->data['target']) ); - if($r) + if($r) { $a->data['xlink'] = $r[0]; - - $rating_val = $r[0]['xlink_rating']; - $rating_text = $r[0]['xlink_rating_text']; - + $rating_val = $r[0]['xlink_rating']; + $rating_text = $r[0]['xlink_rating_text']; + } + else { + $rating_val = 0; + $rating_text = ''; + } // if unset default to enabled if($poco_rating === false) @@ -142,6 +154,8 @@ function rate_content(&$a) { $o = replace_macros(get_markup_template('rating_form.tpl'),array( '$header' => t('Rating'), + '$website' => t('Website:'), + '$site' => (($a->data['site']) ? '<a href="' . $a->data['site']['site_url'] . '" >' . $a->data['site']['site_url'] . '</a>' : ''), 'target' => $a->data['target'], '$tgt_name' => (($a->poi && $a->poi['xchan_name']) ? $a->poi['xchan_name'] : sprintf( t('Remote Channel [%s] (not yet known on this site)'), substr($a->data['target'],0,16))), '$lbl_rating' => t('Rating (this information is public)'), diff --git a/mod/ratings.php b/mod/ratings.php index fe7865778..dc98eb238 100644 --- a/mod/ratings.php +++ b/mod/ratings.php @@ -35,7 +35,7 @@ function ratings_init(&$a) { $results = false; - $x = z_fetch_url($url . '/ratingsearch/' . $hash); + $x = z_fetch_url($url . '/ratingsearch/' . urlencode($hash)); if($x['success']) @@ -48,8 +48,9 @@ function ratings_init(&$a) { return; } - $a->poi = $results['target']; - + if(array_key_exists('xchan_hash',$results['target'])) + $a->poi = $results['target']; + $friends = array(); $others = array(); @@ -62,9 +63,9 @@ function ratings_init(&$a) { } } - $a->data = array_merge($friends,$others); + $a->data = array('target' => $results['target'], 'results' => array_merge($friends,$others)); - if(! $a->data) { + if(! $a->data['results']) { notice( t('No ratings') . EOL); } @@ -90,11 +91,17 @@ function ratings_content(&$a) { if(! $poco_rating) return; + $site_target = ((array_key_exists('target',$a->data) && array_key_exists('site_url',$a->data['target'])) ? + '<a href="' . $a->data['target']['site_url'] . '" >' . $a->data['target']['site_url'] . '</a>' : ''); + + $o = replace_macros(get_markup_template('prep.tpl'),array( '$header' => t('Ratings'), '$rating_lbl' => t('Rating: ' ), + '$website' => t('Website: '), + '$site' => $site_target, '$rating_text_lbl' => t('Description: '), - '$raters' => $a->data + '$raters' => $a->data['results'] )); return $o; diff --git a/mod/ratingsearch.php b/mod/ratingsearch.php index ec2db570b..9c4f2f827 100644 --- a/mod/ratingsearch.php +++ b/mod/ratingsearch.php @@ -33,17 +33,28 @@ function ratingsearch_init(&$a) { ); if($p) - $ret['target'] = $p[0]; + $target = $p[0]['xchan_hash']; else { - $ret['message'] = 'channel not found'; - json_return_and_die($ret); + $p = q("select * from site where site_url like '%s' ", + dbesc('%' . $hash) + ); + if($p) { + $target = strtolower($hash); + } + else { + $ret['message'] = 'Rating target not found'; + json_return_and_die($ret); + } } + if($p) + $ret['target'] = $p[0]; + $ret['success'] = true; $r = q("select * from xlink left join xchan on xlink_xchan = xchan_hash where xlink_link = '%s' and xlink_rating != 0 and xlink_static = 1 order by xchan_name asc", - dbesc($p[0]['xchan_hash']) + dbesc($target) ); if($r) { diff --git a/mod/regdir.php b/mod/regdir.php index eecc99ca5..dce50e76a 100644 --- a/mod/regdir.php +++ b/mod/regdir.php @@ -1,12 +1,24 @@ <?php - +/** + * With args, register a directory server for this realm. + * With no args, return a JSON array of directory servers for this realm. + * + * @FIXME Not yet implemented: Some realms may require authentication to join their realm. + * The RED_GLOBAL realm does not require authentication. + * We would then need a flag in the site table to indicate that they've been + * validated by the PRIMARY directory for that realm. Sites claiming to be PRIMARY + * but are not the realm PRIMARY will be marked invalid. + * + * @param App &$a + */ function regdir_init(&$a) { $result = array('success' => false); $url = $_REQUEST['url']; - + $access_token = $_REQUEST['t']; + $valid = 0; // we probably don't need the realm as we will find out in the probe. // What we may want to die is throw an error if you're trying to register in a different realm @@ -16,54 +28,76 @@ function regdir_init(&$a) { if(! $realm) $realm = DIRECTORY_REALM; + if($realm === DIRECTORY_REALM) { + $valid = 1; + } else { + $token = get_config('system','realm_token'); + if($token && $access_token != $token) { + $result['message'] = 'This realm requires an access token'; + return; + } + $valid = 1; + } + $dirmode = intval(get_config('system','directory_mode')); - if($dirmode == DIRECTORY_MODE_NORMAL) { + if ($dirmode == DIRECTORY_MODE_NORMAL) { $ret['message'] = t('This site is not a directory server'); json_return_and_die($ret); } $m = null; - if($url) { + if ($url) { $m = parse_url($url); - if((! $m) || (! @dns_get_record($m['host'], DNS_A + DNS_CNAME + DNS_PTR)) || (! filter_var($m['host'], FILTER_VALIDATE_IP) )) { + if ((! $m) || ((! @dns_get_record($m['host'], DNS_A + DNS_CNAME + DNS_PTR)) && (! filter_var($m['host'], FILTER_VALIDATE_IP) ))) { + $result['message'] = 'unparseable url'; json_return_and_die($result); } - $f = zot_finger('sys@' . $m['host']); + $f = zot_finger('[system]@' . $m['host']); if($f['success']) { $j = json_decode($f['body'],true); if($j['success'] && $j['guid']) { $x = import_xchan($j); if($x['success']) { $result['success'] = true; - json_return_and_die($result); } } } + if(! $result['success']) + $valid = 0; + + q("update site set site_valid = %d where site_url = '%s' limit 1", + intval($valid), + strtolower($url) + ); + json_return_and_die($result); - } - else { - if($dirmode == DIRECTORY_MODE_STANDALONE) { + } else { + + // We can put this in the sql without the condition after 31 august 2015 assuming + // most directory servers will have updated by then + // This just makes sure it happens if I forget + + $sql_extra = ((datetime_convert() > datetime_convert('UTC','UTC','2015-08-31')) ? ' and site_valid = 1 ' : '' ); + if ($dirmode == DIRECTORY_MODE_STANDALONE) { $r = array(array('site_url' => z_root())); - } - else { - $r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s'", + } else { + $r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s' $sql_extra ", dbesc(get_directory_realm()) ); } - if($r) { + if ($r) { $result['success'] = true; $result['directories'] = array(); - foreach($r as $rr) + foreach ($r as $rr) $result['directories'][] = $rr['site_url']; + json_return_and_die($result); } } json_return_and_die($result); - - -}
\ No newline at end of file +}
\ No newline at end of file diff --git a/mod/regmod.php b/mod/regmod.php index bdb794347..c0a75ef48 100644 --- a/mod/regmod.php +++ b/mod/regmod.php @@ -13,7 +13,7 @@ function regmod_content(&$a) { return $o; } - if((!is_site_admin()) || (x($_SESSION,'submanage') && intval($_SESSION['submanage']))) { + if(! is_site_admin()) { notice( t('Permission denied.') . EOL); return ''; } diff --git a/mod/removeaccount.php b/mod/removeaccount.php index 18aaa2517..f3fa53f75 100644 --- a/mod/removeaccount.php +++ b/mod/removeaccount.php @@ -5,7 +5,7 @@ function removeaccount_post(&$a) { if(! local_channel()) return; - if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) + if($_SESSION['delegate']) return; if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password'])))) @@ -55,7 +55,7 @@ function removeaccount_content(&$a) { '$basedir' => $a->get_baseurl(), '$hash' => $hash, '$title' => t('Remove This Account'), - '$desc' => t('This will completely remove this account including all its channels from the network. Once this has been done it is not recoverable.'), + '$desc' => array(t('WARNING: '), t('This account and all its channels will be completely removed from the network. '), t('This action is permanent and can not be undone!')), '$passwd' => t('Please enter your password for verification:'), '$global' => array('global', t('Remove this account, all its channels and all its channel clones from the network'), false, t('By default only the instances of the channels located on this hub will be removed from the network')), '$submit' => t('Remove Account') @@ -63,4 +63,4 @@ function removeaccount_content(&$a) { return $o; -}
\ No newline at end of file +} diff --git a/mod/removeme.php b/mod/removeme.php index 492738b77..b604bc7db 100644 --- a/mod/removeme.php +++ b/mod/removeme.php @@ -5,7 +5,7 @@ function removeme_post(&$a) { if(! local_channel()) return; - if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) + if($_SESSION['delegate']) return; if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password'])))) @@ -55,12 +55,12 @@ function removeme_content(&$a) { '$basedir' => $a->get_baseurl(), '$hash' => $hash, '$title' => t('Remove This Channel'), - '$desc' => t('This will completely remove this channel from the network. Once this has been done it is not recoverable.'), + '$desc' => array(t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!')), '$passwd' => t('Please enter your password for verification:'), - '$global' => array('global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network')), + '$global' => array('global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), array(t('No'),t('Yes'))), '$submit' => t('Remove Channel') )); return $o; -}
\ No newline at end of file +} diff --git a/mod/rmagic.php b/mod/rmagic.php index 49525bd32..597c6ed9c 100644 --- a/mod/rmagic.php +++ b/mod/rmagic.php @@ -33,6 +33,8 @@ function rmagic_post(&$a) { $openid = new LightOpenID(z_root()); $openid->identity = $address; $openid->returnUrl = z_root() . '/openid'; + $openid->required = array('namePerson/friendly', 'namePerson'); + $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default'); goaway($openid->authUrl()); } catch (Exception $e) { notice( t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.').'<br /><br >'. t('The error message was:').' '.$e->getMessage()); diff --git a/mod/rpost.php b/mod/rpost.php index 2bea18c43..0c0916646 100644 --- a/mod/rpost.php +++ b/mod/rpost.php @@ -17,6 +17,7 @@ require_once('include/zot.php'); * f= placeholder, often required * title= Title of post * body= Body of post + * url= URL which will be parsed and the results appended to the body * source= Source application * remote_return= absolute URL to return after posting is finished * type= choices are 'html' or 'bbcode', default is 'bbcode' @@ -93,20 +94,18 @@ function rpost_content(&$a) { $channel = $a->get_channel(); - $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( - '$title' => t('Edit post') - )); - - -// $a->page['htmlhead'] .= replace_macros(get_markup_template('jot-header.tpl'), array( -// '$baseurl' => $a->get_baseurl(), -// '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), -// '$ispublic' => ' ', // t('Visible to <strong>everybody</strong>'), -// '$geotag' => $geotag, -// '$nickname' => $channel['channel_address'] -// )); - + $channel_acl = array( + 'allow_cid' => $channel['channel_allow_cid'], + 'allow_gid' => $channel['channel_allow_gid'], + 'deny_cid' => $channel['channel_deny_cid'], + 'deny_gid' => $channel['channel_deny_gid'] + ); + if($_REQUEST['url']) { + $x = z_fetch_url(z_root() . '/parse_url?f=&url=' . urlencode($_REQUEST['url'])); + if($x['success']) + $_REQUEST['body'] = $_REQUEST['body'] . $x['body']; + } $x = array( 'is_owner' => true, @@ -115,19 +114,23 @@ function rpost_content(&$a) { 'nickname' => $channel['channel_address'], 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - 'acl' => populate_acl($channel), + 'acl' => populate_acl($channel_acl), 'bang' => '', -// 'channel_select' => true, 'visitor' => true, 'profile_uid' => local_channel(), 'title' => $_REQUEST['title'], 'body' => $_REQUEST['body'], + 'attachment' => $_REQUEST['attachment'], 'source' => ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''), 'return_path' => 'rpost/return' ); + $editor = status_editor($a,$x); - $o .= status_editor($a,$x); + $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( + '$title' => t('Edit post'), + '$editor' => $editor + )); return $o; diff --git a/mod/search.php b/mod/search.php index 02b250bbe..6d79f5eee 100644 --- a/mod/search.php +++ b/mod/search.php @@ -14,6 +14,10 @@ function search_content(&$a,$update = 0, $load = false) { return; } } + + if($load) + $_SESSION['loadtime'] = datetime_convert(); + nav_set_selected('search'); require_once("include/bbcode.php"); @@ -53,12 +57,12 @@ function search_content(&$a,$update = 0, $load = false) { } if(strpos($search,'@') === 0) { $search = substr($search,1); - goaway(z_root() . '/directory' . '?f=1&search=' . $search); + goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search); } // look for a naked webbie if(strpos($search,'@') !== false) { - goaway(z_root() . '/directory' . '?f=1&search=' . $search); + goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search); } if(! $search) @@ -149,24 +153,26 @@ function search_content(&$a,$update = 0, $load = false) { } if(local_channel()) { $r = q("SELECT $prefix mid, item.id as item_id, item.* from item - WHERE item_restrict = 0 + WHERE item_restrict = 0 AND ( item_flags & %d ) = 0 AND ((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND item_private = 0 ) OR ( `item`.`uid` = %d )) OR item.owner_xchan = '%s' ) $sql_extra $suffix $pager_sql ", + intval(ITEM_OBSCURED), intval(local_channel()), dbesc($sys['xchan_hash']) ); } if($r === null) { $r = q("SELECT $prefix mid, item.id as item_id, item.* from item - WHERE item_restrict = 0 + WHERE item_restrict = 0 AND ( item_flags & %d ) = 0 AND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND item_private = 0 ) and owner_xchan in ( " . stream_perms_xchans(($observer) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) $pub_sql ) OR owner_xchan = '%s') $sql_extra $suffix $pager_sql", + intval(ITEM_OBSCURED), dbesc($sys['xchan_hash']) ); } diff --git a/mod/settings.php b/mod/settings.php index 8c927a97c..56949f9d4 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -19,6 +19,9 @@ function settings_init(&$a) { if(! local_channel()) return; + if($_SESSION['delegate']) + return; + $a->profile_uid = local_channel(); // default is channel settings in the absence of other arguments @@ -39,13 +42,13 @@ function settings_post(&$a) { if(! local_channel()) return; + if($_SESSION['delegate']) + return; + $channel = $a->get_channel(); logger('mod_settings: ' . print_r($_REQUEST,true)); - if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) - return; - if((argc() > 1) && (argv(1) === 'oauth') && x($_POST,'remove')){ check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); @@ -114,6 +117,13 @@ function settings_post(&$a) { check_form_security_token_redirectOnErr('/settings/featured', 'settings_featured'); call_hooks('feature_settings_post', $_POST); + + if($_POST['dspr-submit']) { + set_pconfig(local_channel(),'system','diaspora_public_comments',intval($_POST['dspr_pubcomment'])); + set_pconfig(local_channel(),'system','prevent_tag_hijacking',intval($_POST['dspr_hijack'])); + info( t('Diaspora Policy Settings updated.') . EOL); + } + build_sync_packet(); return; } @@ -178,7 +188,7 @@ function settings_post(&$a) { 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',$nosmile); + 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); @@ -543,14 +553,14 @@ function settings_post(&$a) { } -if(! function_exists('settings_content')) { + function settings_content(&$a) { $o = ''; nav_set_selected('settings'); - if(! local_channel()) { + if((! local_channel()) || ($_SESSION['delegate'])) { notice( t('Permission denied.') . EOL ); return login(); } @@ -560,12 +570,7 @@ function settings_content(&$a) { if($channel) head_set_icon($channel['xchan_photo_s']); -// if(x($_SESSION,'submanage') && intval($_SESSION['submanage'])) { -// notice( t('Permission denied.') . EOL ); -// return; -// } - - + $yes_no = array(t('No'),t('Yes')); if((argc() > 1) && (argv(1) === 'oauth')) { @@ -648,18 +653,35 @@ function settings_content(&$a) { } if((argc() > 1) && (argv(1) === 'featured')) { $settings_addons = ""; + + $o = ''; + $diaspora_enabled = get_config('system','diaspora_enabled'); $r = q("SELECT * FROM `hook` WHERE `hook` = 'feature_settings' "); - if(! count($r)) + if((! $r) && (! $diaspora_enabled)) $settings_addons = t('No feature settings configured'); + if($diaspora_enabled) { + $pubcomments = get_pconfig(local_channel(),'system','diaspora_public_comments'); + if($pubcomments === false) + $pubcomments = 1; + $hijacking = get_pconfig(local_channel(),'system','prevent_tag_hijacking'); + + + } + call_hooks('feature_settings', $settings_addons); - - + $tpl = get_markup_template("settings_addons.tpl"); $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("settings_featured"), - '$title' => t('Feature Settings'), + '$title' => t('Feature/Addon Settings'), + '$diaspora_enabled' => $diaspora_enabled, + '$dsprdesc' => t('Settings for the built-in Diaspora emulator'), + '$pubcomments' => array('dspr_pubcomment', t('Allow any Diaspora member to comment on your public posts'), $pubcomments, '', $yes_no), + '$dsprtitle' => t('Diaspora Policy Settings'), + '$hijacking' => array('dspr_hijack', t('Prevent your hashtags from being redirected to other sites'), $hijacking, '', $yes_no), + '$dsprsubmit' => t('Submit'), '$settings_addons' => $settings_addons )); return $o; @@ -683,14 +705,12 @@ function settings_content(&$a) { $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("settings_account"), '$title' => t('Account Settings'), - '$h_pass' => t('Password Settings'), - '$password1'=> array('npassword', t('New Password:'), '', ''), - '$password2'=> array('confirm', t('Confirm:'), '', t('Leave password fields blank unless changing')), + '$password1'=> array('npassword', t('Enter New Password:'), '', ''), + '$password2'=> array('confirm', t('Confirm New Password:'), '', t('Leave password fields blank unless changing')), '$submit' => t('Submit'), '$email' => array('email', t('Email Address:'), $email, ''), '$removeme' => t('Remove Account'), - '$removeaccount' => t('Remove this account from this server including all its channels'), - '$permanent' => t('Warning: This action is permanent and cannot be reversed.'), + '$removeaccount' => t('Remove this account including all its channels'), '$account_settings' => $account_settings )); return $o; @@ -824,18 +844,18 @@ function settings_content(&$a) { '$baseurl' => $a->get_baseurl(true), '$uid' => local_channel(), - '$theme' => array('theme', t('Display Theme:'), $theme_selected, '', $themes, 'preview'), - '$mobile_theme' => array('mobile_theme', t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, ''), - '$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, ''), + '$theme' => (($themes) ? array('theme', t('Display Theme:'), $theme_selected, '', $themes, 'preview') : false), + '$mobile_theme' => (($mobile_themes) ? array('mobile_theme', t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, '') : false), + '$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, '', $yes_no), '$ajaxint' => array('browser_update', t("Update browser every xx seconds"), $browser_update, t('Minimum of 10 seconds, no maximum')), '$itemspage' => array('itemspage', t("Maximum number of conversations to load at any time:"), $itemspage, t('Maximum of 100 items')), - '$nosmile' => array('nosmile', t("Don't show emoticons"), $nosmile, ''), - '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, ''), + '$nosmile' => array('nosmile', t("Show emoticons (smilies) as images"), 1-intval($nosmile), '', $yes_no), + '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no), '$layout_editor' => t('System Page Layout Editor - (advanced)'), '$theme_config' => $theme_config, '$expert' => feature_enabled(local_channel(),'expert'), - '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_channel(),'system','channel_list_mode'), t('(comments displayed separately)')), - '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on matrix page'), get_pconfig(local_channel(),'system','network_list_mode'), t('(comments displayed separately)')), + '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_channel(),'system','channel_list_mode'), t('(comments displayed separately)'), $yes_no), + '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on matrix page'), get_pconfig(local_channel(),'system','network_list_mode'), t('(comments displayed separately)'), $yes_no), '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')), '$network_divmore_height' => array('network_divmore_height', t('Matrix page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')), @@ -952,12 +972,12 @@ function settings_content(&$a) { } else { $profile_in_dir = replace_macros($opt_tpl,array( - '$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', array(t('No'),t('Yes'))), + '$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no), )); } $suggestme = replace_macros($opt_tpl,array( - '$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', array(t('No'),t('Yes'))), + '$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no), )); @@ -1026,15 +1046,15 @@ function settings_content(&$a) { '$email' => array('email', t('Email Address:'), $email, ''), '$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()), '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')), - '$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), ''), + '$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no), - '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)')), + '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no), '$h_prv' => t('Security and Privacy Settings'), '$permissions_set' => $permissions_set, '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'), - '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online')), + '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no), '$lbl_pmacro' => t('Simple Privacy Settings:'), '$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'), @@ -1042,7 +1062,7 @@ function settings_content(&$a) { '$pmacro1' => t('Private - <em>default private, never open or public</em>'), '$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'), '$permiss_arr' => $permiss, - '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'),array(t('No'),t('Yes'))), + '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no), '$lbl_p2macro' => t('Advanced Privacy Settings'), @@ -1064,34 +1084,34 @@ function settings_content(&$a) { '$h_not' => t('Notification Settings'), '$activity_options' => t('By default post a status message when:'), - '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, ''), - '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, ''), - '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, ''), + '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no), + '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no), + '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no), '$lbl_not' => t('Send a notification email when:'), - '$notify1' => array('notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, ''), - '$notify2' => array('notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, ''), - '$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, ''), - '$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, ''), - '$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, ''), - '$notify6' => array('notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, ''), - '$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, ''), - '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, ''), + '$notify1' => array('notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no), + '$notify2' => array('notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no), + '$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no), + '$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no), + '$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no), + '$notify6' => array('notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no), + '$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no), + '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no), '$lbl_vnot' => t('Show visual notifications including:'), - '$vnotify1' => array('vnotify1', t('Unseen matrix activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, ''), - '$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, ''), - '$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended')), - '$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, ''), - '$vnotify5' => array('vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, ''), - '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes')), - '$vnotify7' => array('vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, ''), - '$vnotify8' => array('vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended')), - '$vnotify9' => array('vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended')), - '$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended')), - '$vnotify11' => array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, ''), - '$always_show_in_notices' => array('always_show_in_notices', t('Also show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, ''), + '$vnotify1' => array('vnotify1', t('Unseen matrix activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no), + '$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no), + '$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no), + '$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no), + '$vnotify5' => array('vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no), + '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no), + '$vnotify7' => array('vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no), + '$vnotify8' => array('vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no), + '$vnotify9' => array('vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no), + '$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no), + '$vnotify11' => array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no), + '$always_show_in_notices' => array('always_show_in_notices', t('Also show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no), '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')), @@ -1103,8 +1123,8 @@ function settings_content(&$a) { '$lbl_misc' => t('Miscellaneous Settings'), '$menus' => $menu, '$menu_desc' => t('Personal menu to display in your channel pages'), - '$removeme' => t('Remove this channel'), - '$permanent' => t('Warning: This action is permanent and cannot be reversed.'), + '$removeme' => t('Remove Channel'), + '$removechannel' => t('Remove this channel.'), )); call_hooks('settings_form',$o); @@ -1113,5 +1133,5 @@ function settings_content(&$a) { return $o; } -}} +} diff --git a/mod/setup.php b/mod/setup.php index d192eaf21..b885388be 100755 --- a/mod/setup.php +++ b/mod/setup.php @@ -233,10 +233,10 @@ function setup_content(&$a) { check_htconfig($checks); - check_smarty3($checks); - check_store($checks); + check_smarty3($checks); + check_keys($checks); if(x($_POST,'phpath')) @@ -535,7 +535,7 @@ function check_store(&$checks) { $status = true; $help = ""; - @os_mkdir('store',STORAGE_DEFAULT_PERMISSIONS); + @os_mkdir(TEMPLATE_BUILD_PATH,STORAGE_DEFAULT_PERMISSIONS,true); if( !is_writable('store') ) { diff --git a/mod/share.php b/mod/share.php index 923971694..d5a389bdf 100644 --- a/mod/share.php +++ b/mod/share.php @@ -13,7 +13,6 @@ function share_init(&$a) { if(! (local_channel() || remote_channel())) killme(); - $r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1", intval($post_id) ); @@ -30,13 +29,12 @@ function share_init(&$a) { if(! $r) killme(); - // FIXME - we only share bbcode + /** @FIXME we only share bbcode */ if($r[0]['mimetype'] !== 'text/bbcode') killme(); - // FIXME - eventually we want to post remotely via rpost - // on your home site. + /** @FIXME eventually we want to post remotely via rpost on your home site */ // When that works remove this next bit: if(! local_channel()) @@ -64,20 +62,20 @@ function share_init(&$a) { echo $o; killme(); } - + $observer = $a->get_observer(); $parsed = $observer['xchan_url']; if($parsed) { $post_url = $parsed['scheme'] . ':' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '') . '/rpost'; - // FIXME - we were probably called from JS - // so we don't know the return page. - // in fact we won't be able to load the remote page. - // we might need an iframe + + /** + * @FIXME we were probably called from JS so we don't know the return page. + * In fact we won't be able to load the remote page. + * we might need an iframe + */ $x = z_post_url($post_url, array('f' => '', 'body' => $o )); killme(); } - - } diff --git a/mod/sharedwithme.php b/mod/sharedwithme.php index d91987027..bee072ea7 100644 --- a/mod/sharedwithme.php +++ b/mod/sharedwithme.php @@ -12,33 +12,9 @@ function sharedwithme_content(&$a) { $is_owner = (local_channel() && (local_channel() == $channel['channel_id'])); - //maintenance - see if a file got dropped and remove it systemwide - this should possibly go to include/poller - $x = q("SELECT * FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d", - dbesc(ACTIVITY_UPDATE), - dbesc(ACTIVITY_OBJ_FILE), - intval(local_channel()) - ); - - if($x) { - - foreach($x as $xx) { - - $object = json_decode($xx['object'],true); - - $d_mid = $object['d_mid']; - $u_mid = $xx['mid']; - - $y = q("DELETE FROM item WHERE obj_type = '%s' AND (verb = '%s' AND mid = '%s') OR (verb = '%s' AND mid = '%s')", - dbesc(ACTIVITY_OBJ_FILE), - dbesc(ACTIVITY_POST), - dbesc($d_mid), - dbesc(ACTIVITY_UPDATE), - dbesc($u_mid) - ); - - } - - } + //check for updated items and remove them + require_once('include/sharedwithme.php'); + apply_updates(); //drop single file - localuser if((argc() > 2) && (argv(2) === 'drop')) { @@ -66,7 +42,7 @@ function sharedwithme_content(&$a) { } //list files - $r = q("SELECT * FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d AND owner_xchan != '%s'", + $r = q("SELECT id, uid, object, item_unseen FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d AND owner_xchan != '%s'", dbesc(ACTIVITY_POST), dbesc(ACTIVITY_OBJ_FILE), intval(local_channel()), @@ -74,8 +50,10 @@ function sharedwithme_content(&$a) { ); $items =array(); + $ids = ''; if($r) { + foreach($r as $rr) { $object = json_decode($rr['object'],true); @@ -87,10 +65,27 @@ function sharedwithme_content(&$a) { $item['objfilename'] = $object['filename']; $item['objfilesize'] = userReadableSize($object['filesize']); $item['objedited'] = $object['edited']; + $item['unseen'] = $rr['item_unseen']; $items[] = $item; + if($item['unseen'] > 0) { + $ids .= " '" . $rr['id'] . "',"; + } + } + + } + + if($ids) { + + //remove trailing , + $ids = rtrim($ids, ","); + + q("UPDATE item SET item_unseen = 0 WHERE id IN ( $ids ) AND uid = %d", + intval(local_channel()) + ); + } $o = profile_tabs($a, $is_owner, $channel['channel_address']); @@ -98,6 +93,7 @@ function sharedwithme_content(&$a) { $o .= replace_macros(get_markup_template('sharedwithme.tpl'), array( '$header' => t('Files: shared with me'), '$name' => t('Name'), + '$label_new' => t('NEW'), '$size' => t('Size'), '$lastmod' => t('Last Modified'), '$dropall' => t('Remove all files'), diff --git a/mod/siteinfo.php b/mod/siteinfo.php index 1f3cd4479..856909a27 100644 --- a/mod/siteinfo.php +++ b/mod/siteinfo.php @@ -50,6 +50,21 @@ function siteinfo_init(&$a) { $site_info = get_config('system','info'); $site_name = get_config('system','sitename'); + if(! get_config('system','hidden_version_siteinfo')) { + $version = RED_VERSION; + if(@is_dir('.git') && function_exists('shell_exec')) { + $commit = trim( @shell_exec('git log -1 --format="%h"')); + if(! get_config('system','hidden_tag_siteinfo')) + $tag = trim( @shell_exec('git describe --tags --abbrev=0')); + else + $tag = ''; + } + if(! isset($commit) || strlen($commit) > 16) + $commit = ''; + } + else { + $version = $commit = ''; + } //Statistics $channels_total_stat = intval(get_config('system','channels_total_stat')); @@ -57,9 +72,12 @@ function siteinfo_init(&$a) { $channels_active_monthly_stat = intval(get_config('system','channels_active_monthly_stat')); $local_posts_stat = intval(get_config('system','local_posts_stat')); $hide_in_statistics = intval(get_config('system','hide_in_statistics')); + $site_expire = intval(get_config('system', 'default_expire_days')); + $data = Array( - 'version' => RED_VERSION, + 'version' => $version, + 'version_tag' => $tag, 'commit' => $commit, 'url' => z_root(), 'plugins' => $visible_plugins, @@ -68,6 +86,7 @@ function siteinfo_init(&$a) { 'language' => get_config('system','language'), 'diaspora_emulation' => get_config('system','diaspora_enabled'), 'rss_connections' => get_config('system','feed_contacts'), + 'expiration' => $site_expire, 'default_service_restrictions' => $service_class, 'admin' => $admin, 'site_name' => (($site_name) ? $site_name : ''), @@ -134,7 +153,7 @@ function siteinfo_content(&$a) { $o = replace_macros(get_markup_template('siteinfo.tpl'), array( '$title' => t('Red'), - '$description' => t('This is a hub of the Red Matrix - a global cooperative network of decentralized privacy enhanced websites.'), + '$description' => t('This is a hub of redmatrix - a global cooperative network of decentralized privacy enhanced websites.'), '$version' => $version, '$tag_txt' => t('Tag: '), '$tag' => $tag, @@ -142,9 +161,9 @@ function siteinfo_content(&$a) { '$lastpoll' => get_poller_runtime(), '$commit' => $commit, '$web_location' => t('Running at web location') . ' ' . z_root(), - '$visit' => t('Please visit <a href="https://redmatrix.me">RedMatrix.me</a> to learn more about the Red Matrix.'), + '$visit' => t('Please visit <a href="https://redmatrix.me">redmatrix.me</a> to learn more about the Red Matrix.'), '$bug_text' => t('Bug reports and issues: please visit'), - '$bug_link_url' => 'https://github.com/friendica/red/issues', + '$bug_link_url' => 'https://github.com/redmatrix/redmatrix/issues', '$bug_link_text' => 'redmatrix issues', '$contact' => t('Suggestions, praise, etc. - please email "redmatrix" at librelist - dot com'), '$donate' => $donate, diff --git a/mod/suggest.php b/mod/suggest.php index fec0e85a4..438d884ca 100644 --- a/mod/suggest.php +++ b/mod/suggest.php @@ -44,6 +44,7 @@ function suggest_content(&$a) { $arr[] = array( 'url' => chanlink_url($rr['xchan_url']), + 'common' => $rr['total'], 'profile' => $rr['xchan_url'], 'name' => $rr['xchan_name'], 'photo' => $rr['xchan_photo_m'], diff --git a/mod/thing.php b/mod/thing.php index 289e968ca..b4b8ad027 100644 --- a/mod/thing.php +++ b/mod/thing.php @@ -1,4 +1,8 @@ -<?php /** @file */ +<?php +/** + * @file mod/thing.php + * @brief + */ require_once('include/items.php'); require_once('include/contact_selectors.php'); @@ -9,9 +13,6 @@ function thing_init(&$a) { if(! local_channel()) return; - - - $account_id = $a->get_account(); $channel = $a->get_channel(); @@ -26,19 +27,18 @@ function thing_init(&$a) { $hash = random_string(); - $verbs = obj_verbs(); - /** + /** * verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants" * We use the first person form when creating an activity, but the third person for use in activities - * FIXME: There is no accounting for verb gender for languages where this is significant. We may eventually + * @FIXME There is no accounting for verb gender for languages where this is significant. We may eventually * require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module. */ $translated_verb = $verbs[$verb][1]; - /** + /* * The site administrator can do things that normals cannot. * This is restricted because it will likely cause * an activitystreams protocol violation and the activity might @@ -50,14 +50,14 @@ function thing_init(&$a) { if(! $translated_verb) { if(is_site_admin()) $translated_verb = $verb; - } - - /** + } + + /* * Things, objects: We do not provide definite (a, an) or indefinite (the) articles or singular/plural designators * That needs to be specified in your thing. e.g. Mike has "a carrot", Greg wants "balls", Bob likes "the Boston Red Sox". */ - /** + /* * Future work on this module might produce more complex activities with targets, e.g. Phillip likes Karen's moustache * and to describe other non-thing objects like channels, such as Karl wants Susan - where Susan represents a channel profile. */ @@ -65,8 +65,6 @@ function thing_init(&$a) { if((! $name) || (! $translated_verb)) return; - - if($term_hash) { $t = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", intval(TERM_OBJ_THING), @@ -115,7 +113,6 @@ function thing_init(&$a) { $local_photo_type = $arr[3]; } - $r = q("select * from term where uid = %d and otype = %d and type = %d and term = '%s' limit 1", intval(local_channel()), intval(TERM_OBJ_THING), @@ -159,14 +156,12 @@ function thing_init(&$a) { info( t('Thing added')); - if($activity) { $arr = array(); $links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $term['url'])); if($local_photo) $links[] = array('rel' => 'photo', 'type' => $local_photo_type, 'href' => $local_photo); - $objtype = ACTIVITY_OBJ_THING; $obj = json_encode(array( @@ -186,7 +181,6 @@ function thing_init(&$a) { $arr['item_wall'] = 1; $arr['item_thread_top'] = 1; - $ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]'; $plink = '[zrl=' . $term['url'] . ']' . $term['term'] . '[/zrl]'; @@ -214,14 +208,14 @@ function thing_init(&$a) { else $arr['allow_cid'] = '<' . get_observer_hash() . '>'; } - + $ret = post_activity_item($arr); } } function thing_content(&$a) { - + if(argc() == 2) { $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", @@ -251,12 +245,10 @@ function thing_content(&$a) { } $thing_hash = ''; - if(argc() == 3 && argv(1) === 'edit') { $thing_hash = argv(2); - $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_type = %d and term_hash = '%s' limit 1", intval(TERM_OBJ_THING), dbesc($thing_hash) @@ -267,7 +259,6 @@ function thing_content(&$a) { return ''; } - $o .= replace_macros(get_markup_template('thing_edit.tpl'),array( '$thing_hdr' => t('Edit Thing'), '$multiprof' => feature_enabled(local_channel(),'multi_profiles'), @@ -302,7 +293,6 @@ function thing_content(&$a) { 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), @@ -312,6 +302,7 @@ function thing_content(&$a) { dbesc($thing_hash), intval(local_channel()) ); + return $o; } @@ -330,6 +321,4 @@ function thing_content(&$a) { )); return $o; - - } diff --git a/mod/viewconnections.php b/mod/viewconnections.php index e35d5ca21..c1da07292 100644 --- a/mod/viewconnections.php +++ b/mod/viewconnections.php @@ -28,6 +28,10 @@ function viewconnections_content(&$a) { return; } + if(! $_REQUEST['aj']) + $_SESSION['return_url'] = $a->query_string; + + $is_owner = ((local_channel() && local_channel() == $a->profile['uid']) ? true : false); $abook_flags = ABOOK_FLAG_PENDING|ABOOK_FLAG_SELF; @@ -53,7 +57,7 @@ function viewconnections_content(&$a) { intval($a->pager['start']) ); - if(! $r) { + if((! $r) && (! $_REQUEST['aj'])) { info( t('No connections.') . EOL ); return $o; } @@ -80,13 +84,30 @@ function viewconnections_content(&$a) { } - $tpl = get_markup_template("viewcontact_template.tpl"); - $o .= replace_macros($tpl, array( - '$title' => t('View Connections'), - '$contacts' => $contacts, - '$paginate' => paginate($a), - )); + if($_REQUEST['aj']) { + if($contacts) { + $o = replace_macros(get_markup_template('viewcontactsajax.tpl'),array( + '$contacts' => $contacts + )); + } + 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>"; + $tpl = get_markup_template("viewcontact_template.tpl"); + $o .= replace_macros($tpl, array( + '$title' => t('View Connections'), + '$contacts' => $contacts, +// '$paginate' => paginate($a), + )); + } + if(! $contacts) + $o .= '<div id="content-complete"></div>'; return $o; } diff --git a/mod/viewsrc.php b/mod/viewsrc.php index ac7000689..931175a44 100644 --- a/mod/viewsrc.php +++ b/mod/viewsrc.php @@ -36,6 +36,7 @@ function viewsrc_content(&$a) { } if(is_ajax()) { + print '<div><i class="icon-pencil"> ' . t('Source of Item') . ' ' . $r[0]['id'] . '</i></div>'; echo $o; killme(); } diff --git a/mod/wall_attach.php b/mod/wall_attach.php index 47c097416..4b7103802 100644 --- a/mod/wall_attach.php +++ b/mod/wall_attach.php @@ -2,15 +2,43 @@ require_once('include/attach.php'); require_once('include/identity.php'); +require_once('include/photos.php'); function wall_attach_post(&$a) { if(argc() > 1) $channel = get_channel_by_nick(argv(1)); - else + elseif($_FILES['media']) { + require_once('include/api.php'); + $user_info = api_get_user($a); + $nick = $user_info['screen_name']; + $channel = get_channel_by_nick($user_info['screen_name']); + } + + if(! $channel) killme(); - $r = attach_store($channel,get_observer_hash()); + $observer = $a->get_observer(); + + + if($_FILES['userfile']['tmp_name']) { + $x = @getimagesize($_FILES['userfile']['tmp_name']); + logger('getimagesize: ' . print_r($x,true), LOGGER_DATA); + if(($x) && ($x[2] === IMAGETYPE_GIF || $x[2] === IMAGETYPE_JPEG || $x[2] === IMAGETYPE_PNG)) { + $args = array( 'source' => 'editor', 'visible' => 0, 'contact_allow' => array($channel['channel_hash'])); + $ret = photo_upload($channel,$observer,$args); + if($ret['success']) { + echo "\n\n" . $ret['body'] . "\n\n"; + killme(); + } + if($using_api) + return; + notice($ret['message']); + killme(); + } + } + + $r = attach_store($channel,(($observer) ? $observer['xchan_hash'] : '')); if(! $r['success']) { notice( $r['message'] . EOL); diff --git a/mod/wall_upload.php b/mod/wall_upload.php index 7ed1859a8..31a497f0f 100644 --- a/mod/wall_upload.php +++ b/mod/wall_upload.php @@ -32,8 +32,7 @@ function wall_upload_post(&$a) { $observer = $a->get_observer(); - $args = array( 'source' => 'editor', 'album' => t('Wall Photos'), - 'not_visible' => 1, 'contact_allow' => array($channel['channel_hash'])); + $args = array( 'source' => 'editor', 'visible' => 0, 'contact_allow' => array($channel['channel_hash'])); $ret = photo_upload($channel,$observer,$args); diff --git a/mod/webpages.php b/mod/webpages.php index a31d9bec3..7dead3371 100644 --- a/mod/webpages.php +++ b/mod/webpages.php @@ -32,6 +32,8 @@ function webpages_content(&$a) { } $which = argv(1); + + $_SESSION['return_url'] = $a->query_string; $uid = local_channel(); $owner = 0; @@ -68,26 +70,20 @@ function webpages_content(&$a) { return; } - if(feature_enabled($owner,'expert')) { - $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); - if(! $mimetype) - $mimetype = 'choose'; - } - else { - $mimetype = 'text/bbcode'; + $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); + + if(! $mimetype) { + $mimetype = 'choose'; } $layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout')); if(! $layout) $layout = 'choose'; - // Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages // Nickname is set to the observers xchan, and profile_uid to the owner's. // This lets you post pages at other people's channels. - - if((! $channel) && ($uid) && ($uid == $a->profile_uid)) { $channel = $a->get_channel(); } @@ -102,8 +98,8 @@ function webpages_content(&$a) { else $channel_acl = array(); - - $o = profile_tabs($a,true); + $is_owner = ($uid && $uid == $owner); + $o = profile_tabs($a, $is_owner, $a->profile['channel_address']); $x = array( 'webpage' => ITEM_TYPE_WEBPAGE, @@ -111,11 +107,13 @@ function webpages_content(&$a) { 'nickname' => $a->profile['channel_address'], 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), 'bang' => '', - 'acl' => (($uid && $uid == $owner) ? populate_acl($channel_acl,false) : ''), + 'acl' => (($is_owner) ? populate_acl($channel_acl,false) : ''), + 'showacl' => (($is_owner) ? true : false), 'visitor' => true, 'profile_uid' => intval($owner), 'mimetype' => $mimetype, 'layout' => $layout, + 'expanded' => true ); if($_REQUEST['title']) @@ -125,14 +123,16 @@ function webpages_content(&$a) { if($_REQUEST['pagetitle']) $x['pagetitle'] = $_REQUEST['pagetitle']; - $o .= status_editor($a,$x); + $editor = status_editor($a,$x); // Get a list of webpages. We can't display all them because endless scroll makes that unusable, // so just list titles and an edit link. - //TODO - this should be replaced with pagelist_widget + /** @TODO - this should be replaced with pagelist_widget */ + + $sql_extra = item_permissions_sql($owner); $r = q("select * from item_id left join item on item_id.iid = item.id - where item_id.uid = %d and service = 'WEBPAGE' order by item.created desc", + where item_id.uid = %d and service = 'WEBPAGE' $sql_extra order by item.created desc", intval($owner) ); @@ -142,12 +142,28 @@ function webpages_content(&$a) { $pages = array(); foreach($r as $rr) { unobscure($rr); + + $lockstate = (($rr['allow_cid'] || $rr['allow_gid'] || $rr['deny_cid'] || $rr['deny_gid']) ? 'lock' : 'unlock'); + + $element_arr = array( + 'type' => 'webpage', + 'title' => $rr['title'], + 'body' => $rr['body'], + 'term' => $rr['term'], + 'created' => $rr['created'], + 'edited' => $rr['edited'], + 'mimetype' => $rr['mimetype'], + 'pagetitle' => $rr['sid'], + 'mid' => $rr['mid'] + ); $pages[$rr['iid']][] = array( - 'url' => $rr['iid'], - 'pagetitle' => $rr['sid'], - 'title' => $rr['title'], - 'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']), - 'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']) + 'url' => $rr['iid'], + 'pagetitle' => $rr['sid'], + 'title' => $rr['title'], + 'created' => datetime_convert('UTC',date_default_timezone_get(),$rr['created']), + 'edited' => datetime_convert('UTC',date_default_timezone_get(),$rr['edited']), + 'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]', + 'lockstate' => $lockstate ); } } @@ -157,21 +173,23 @@ function webpages_content(&$a) { $url = z_root() . '/editwebpage/' . $which; $o .= replace_macros(get_markup_template('webpagelist.tpl'), array( - '$listtitle' => t('Webpages'), + '$listtitle' => t('Webpages'), '$baseurl' => $url, + '$create' => t('Create'), '$edit' => t('Edit'), + '$share' => t('Share'), + '$delete' => t('Delete'), '$pages' => $pages, '$channel' => $which, + '$editor' => $editor, '$view' => t('View'), '$preview' => t('Preview'), '$actions_txt' => t('Actions'), '$pagelink_txt' => t('Page Link'), - '$title_txt' => t('Title'), + '$title_txt' => t('Page Title'), '$created_txt' => t('Created'), '$edited_txt' => t('Edited') - )); return $o; - } diff --git a/mod/zfinger.php b/mod/zfinger.php index 42085fb52..2f544d10e 100644 --- a/mod/zfinger.php +++ b/mod/zfinger.php @@ -239,11 +239,6 @@ function zfinger_init(&$a) { if(($dirmode === false) || ($dirmode == DIRECTORY_MODE_NORMAL)) $ret['site']['directory_mode'] = 'normal'; - // downgrade mis-configured primaries - - if($dirmode == DIRECTORY_MODE_PRIMARY && z_root() != get_directory_primary()) - $dirmode = DIRECTORY_MODE_SECONDARY; - if($dirmode == DIRECTORY_MODE_PRIMARY) $ret['site']['directory_mode'] = 'primary'; elseif($dirmode == DIRECTORY_MODE_SECONDARY) diff --git a/mod/zotfeed.php b/mod/zotfeed.php index 7bf91d4db..78a667330 100644 --- a/mod/zotfeed.php +++ b/mod/zotfeed.php @@ -9,7 +9,7 @@ function zotfeed_init(&$a) { $mindate = (($_REQUEST['mindate']) ? datetime_convert('UTC','UTC',$_REQUEST['mindate']) : ''); if(! $mindate) - $mindate = datetime_convert('UTC','UTC', 'now - 1 month'); + $mindate = datetime_convert('UTC','UTC', 'now - 4 days'); if(get_config('system','block_public') && (! get_account_id()) && (! remote_channel())) { $result['message'] = 'Public access denied'; @@ -21,7 +21,7 @@ function zotfeed_init(&$a) { $channel_address = ((argc() > 1) ? argv(1) : ''); if($channel_address) { - $r = q("select channel_id, channel_name from channel where channel_address = '%s' and not (channel_pageflags & %d)>0 limit 1", + $r = q("select channel_id, channel_name from channel where channel_address = '%s' and not (channel_pageflags & %d) > 0 limit 1", dbesc(argv(1)), intval(PAGE_REMOVED) ); @@ -30,6 +30,7 @@ function zotfeed_init(&$a) { $x = get_sys_channel(); if($x) $r = array($x); + $mindate = datetime_convert('UTC','UTC', 'now - 2 days'); } if(! $r) { $result['message'] = 'Channel not found.'; |