diff options
Diffstat (limited to 'Zotlabs/Module')
115 files changed, 6439 insertions, 6793 deletions
diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php index fb95b0504..5b37f2707 100644 --- a/Zotlabs/Module/Acl.php +++ b/Zotlabs/Module/Acl.php @@ -3,9 +3,9 @@ namespace Zotlabs\Module; use Zotlabs\Lib\Libzotdir; +use Zotlabs\Lib\AccessList; require_once 'include/acl_selectors.php'; -require_once 'include/group.php'; /** * @brief ACL selector json backend. @@ -123,7 +123,7 @@ class Acl extends \Zotlabs\Web\Controller { "name" => t('Profile','acl') . ' ' . $rv['profile_name'], "id" => 'vp' . $rv['id'], "xid" => 'vp.' . $rv['profile_guid'], - "uids" => group_get_profile_members_xchan(local_channel(), $rv['id']), + "uids" => AccessList::profile_members_xchan(local_channel(), $rv['id']), "link" => '' ); } @@ -146,14 +146,14 @@ class Acl extends \Zotlabs\Web\Controller { if($r) { foreach($r as $g){ - // logger('acl: group: ' . $g['gname'] . ' members: ' . group_get_members_xchan($g['id'])); + // logger('acl: group: ' . $g['gname'] . ' members: ' . AccessList::members_xchan(local_channel(), $g['id'])); $groups[] = array( "type" => "g", "photo" => "images/twopeople.png", "name" => $g['gname'], "id" => $g['id'], "xid" => $g['hash'], - "uids" => group_get_members_xchan($g['id']), + "uids" => AccessList::members_xchan(local_channel(), $g['id']), "link" => '' ); } @@ -222,6 +222,7 @@ class Acl extends \Zotlabs\Web\Controller { WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" , intval(local_channel()) ); + if($r2) $r = array_merge($r2,$r); @@ -282,13 +283,12 @@ class Acl extends \Zotlabs\Web\Controller { } } elseif($type == 'm') { - $r = array(); $z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d and xchan_deleted = 0 - and xchan_network IN ('zot', 'diaspora', 'friendica-over-diaspora') + and not xchan_network IN ('rss', 'anon', 'unknown') $sql_extra3 ORDER BY xchan_name ASC ", intval(local_channel()) @@ -371,7 +371,7 @@ class Acl extends \Zotlabs\Web\Controller { ); } if($type !== 'f') { - if (! array_key_exists($x[$lkey], $contacts) || ($contacts[$x[$lkey]]['net'] !== 'zot6' && ($g['net'] == 'zot6' || $g['net'] == 'zot'))) { + if (! array_key_exists($x[$lkey], $contacts) || ($contacts[$x[$lkey]]['net'] !== 'zot6' && $g['net'] == 'zot6')) { $contacts[$x[$lkey]] = array( "type" => "c", "photo" => $g['micro'], @@ -438,7 +438,6 @@ class Acl extends \Zotlabs\Web\Controller { } if(! $url) { - require_once("include/dir_fns.php"); $directory = Libzotdir::find_upstream_directory($dirmode); $url = $directory['url'] . '/dirsearch'; } diff --git a/Zotlabs/Module/Admin.php b/Zotlabs/Module/Admin.php index 44c10b339..59a9e22b2 100644 --- a/Zotlabs/Module/Admin.php +++ b/Zotlabs/Module/Admin.php @@ -8,7 +8,6 @@ namespace Zotlabs\Module; -require_once('include/queue_fn.php'); require_once('include/account.php'); /** diff --git a/Zotlabs/Module/Admin/Queue.php b/Zotlabs/Module/Admin/Queue.php index 5a47413ee..8a843083b 100644 --- a/Zotlabs/Module/Admin/Queue.php +++ b/Zotlabs/Module/Admin/Queue.php @@ -2,52 +2,64 @@ namespace Zotlabs\Module\Admin; - +use Zotlabs\Lib\Queue as LibQueue; class Queue { - + function get() { $o = ''; - + $expert = ((array_key_exists('expert',$_REQUEST)) ? intval($_REQUEST['expert']) : 0); - + if($_REQUEST['drophub']) { hubloc_mark_as_down($_REQUEST['drophub']); - remove_queue_by_posturl($_REQUEST['drophub']); + LibQueue::remove_by_posturl($_REQUEST['drophub']); } - + if($_REQUEST['emptyhub']) { - remove_queue_by_posturl($_REQUEST['emptyhub']); + LibQueue::remove_by_posturl($_REQUEST['emptyhub']); + } + + if($_REQUEST['deliverhub']) { + + $hubq = q("SELECT * FROM outq WHERE outq_posturl = '%s'", + dbesc($_REQUEST['deliverhub']) + ); + + foreach ($hubq as $q) { + LibQueue::deliver($q, true); + } } - - $r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq + + $r = dbq("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'), + '$deliverhub' => t('Retry delivery to this hub'), '$empty' => t('Empty queue for this hub'), '$lastconn' => t('Last known contact'), '$hasentries' => ((count($r)) ? true : false), '$entries' => $r, '$expert' => $expert )); - + return $o; } - -}
\ No newline at end of file + +} diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index 3b2632411..f6e3ab12b 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -339,11 +339,14 @@ class Site { // now invert the logic for the setting. $discover_tab = (1 - $discover_tab); - $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); - $default_role = get_config('system','default_permissions_role','social'); + $perm_roles = \Zotlabs\Access\PermissionRoles::channel_roles(); + $default_role = get_config('system', 'default_permissions_role', 'personal'); - $role = array('permissions_role' , t('Default permission role for new accounts'), $default_role, t('This role will be used for the first channel created after registration.'),$perm_roles); + if (!in_array($default_role, array_keys($perm_roles))) { + $default_role = 'personal'; + } + $role = array('permissions_role' , t('Default permission role for new accounts'), $default_role, t('This role will be used for the first channel created after registration.'),$perm_roles); $homelogin = get_config('system','login_on_homepage'); $enable_context_help = get_config('system','enable_context_help'); @@ -480,12 +483,12 @@ class Site { '$invitation_only' => [ 'invitation_only', t("Require invite code"), - $invitation_only + get_config('system', 'invitation_only', 0) ], '$invitation_also' => [ 'invitation_also', t("Allow invite code"), - $invitation_also + get_config('system', 'invitation_also', 0) ], '$verify_email' => [ 'verify_email', diff --git a/Zotlabs/Module/Affinity.php b/Zotlabs/Module/Affinity.php index f0d99f1e7..0e163b89a 100644 --- a/Zotlabs/Module/Affinity.php +++ b/Zotlabs/Module/Affinity.php @@ -44,17 +44,14 @@ class Affinity extends \Zotlabs\Web\Controller { if(! local_channel()) return; - $desc = t('This app presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship (affinity) with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.'); - if(! Apps::system_app_installed(local_channel(),'Affinity Tool')) { + if(! Apps::system_app_installed(local_channel(), 'Affinity Tool')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Affinity Tool App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= $desc; - return $o; + $papp = Apps::get_papp('Affinity Tool'); + return Apps::app_render($papp, 'module'); } - $text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.'); + $text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.'); $content = '<div class="section-content-info-wrapper">' . $text . '</div>'; diff --git a/Zotlabs/Module/Album.php b/Zotlabs/Module/Album.php new file mode 100644 index 000000000..f80880184 --- /dev/null +++ b/Zotlabs/Module/Album.php @@ -0,0 +1,103 @@ +<?php + +namespace Zotlabs\Module; + +use App; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\Activity; +use Zotlabs\Lib\ActivityStreams; +use Zotlabs\Lib\Config; +use Zotlabs\Web\HTTPSig; + +require_once('include/security.php'); +require_once('include/attach.php'); +require_once('include/photo/photo_driver.php'); +require_once('include/photos.php'); + + +class Album extends Controller { + + function init() { + + if (ActivityStreams::is_as_request()) { + $sigdata = HTTPSig::verify(EMPTY_STR); + if ($sigdata['portable_id'] && $sigdata['header_valid']) { + $portable_id = $sigdata['portable_id']; + if (!check_channelallowed($portable_id)) { + http_status_exit(403, 'Permission denied'); + } + if (!check_siteallowed($sigdata['signer'])) { + http_status_exit(403, 'Permission denied'); + } + observer_auth($portable_id); + } + elseif (Config::get('system', 'require_authenticated_fetch', false)) { + http_status_exit(403, 'Permission denied'); + } + + $observer_xchan = get_observer_hash(); + $allowed = false; + + $bear = Activity::token_from_request(); + if ($bear) { + logger('bear: ' . $bear, LOGGER_DEBUG); + } + + $channel = null; + + if (argc() > 1) { + $channel = channelx_by_nick(argv(1)); + } + if (!$channel) { + http_status_exit(404, 'Not found.'); + } + + $sql_extra = permissions_sql($channel['channel_id'], $observer_xchan); + + if (argc() > 2) { + $folder = argv(2); + $r = q("select * from attach where is_dir = 1 and hash = '%s' and uid = %d $sql_extra limit 1", + dbesc($folder), + intval($channel['channel_id']) + ); + $allowed = (($r) ? attach_can_view($channel['channel_id'], $observer_xchan, $r[0]['hash'] /*,$bear */) : false); + } + else { + $folder = EMPTY_STR; + $allowed = perm_is_allowed($channel['channel_id'], $observer_xchan, 'view_storage'); + } + + if (!$allowed) { + http_status_exit(403, 'Permission denied.'); + } + + $x = q("select * from attach where folder = '%s' and uid = %d $sql_extra", + dbesc($folder), + intval($channel['channel_id']) + ); + + $contents = []; + + if ($x) { + foreach ($x as $xv) { + if (intval($xv['is_dir'])) { + continue; + } + if (!attach_can_view($channel['channel_id'], $observer_xchan, $xv['hash'] /*,$bear*/)) { + continue; + } + if (intval($xv['is_photo'])) { + $contents[] = z_root() . '/photo/' . $xv['hash']; + } + } + } + + $obj = Activity::encode_simple_collection($contents, App::$query_string, 'OrderedCollection', count($contents)); + as_return_and_die($obj, $channel); + + } + + } + +} + diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php index 39689665e..d287115d4 100644 --- a/Zotlabs/Module/Appman.php +++ b/Zotlabs/Module/Appman.php @@ -1,18 +1,18 @@ <?php /** @file */ -namespace Zotlabs\Module; +namespace Zotlabs\Module; -//require_once('include/apps.php'); - -use \Zotlabs\Lib as Zlib; +use App; +use Zotlabs\Lib\Apps; +use Zotlabs\Lib\Libsync; class Appman extends \Zotlabs\Web\Controller { function post() { - + if(! local_channel()) return; - + if($_POST['url']) { $arr = array( 'uid' => intval($_REQUEST['uid']), @@ -32,32 +32,70 @@ class Appman extends \Zotlabs\Web\Controller { 'sig' => escape_tags($_REQUEST['sig']), 'categories' => escape_tags($_REQUEST['categories']) ); - - $_REQUEST['appid'] = Zlib\Apps::app_install(local_channel(),$arr); - - if(Zlib\Apps::app_installed(local_channel(),$arr)) + + $_REQUEST['appid'] = Apps::app_install(local_channel(),$arr); + + if(Apps::app_installed(local_channel(),$arr)) info( t('App installed.') . EOL); goaway(z_root() . '/apps'); return; //not reached } - - - $papp = Zlib\Apps::app_decode($_POST['papp']); - + + + $papp = Apps::app_decode($_POST['papp']); + if(! is_array($papp)) { notice( t('Malformed app.') . EOL); return; } - + if($_POST['install']) { - Zlib\Apps::app_install(local_channel(),$papp); - if(Zlib\Apps::app_installed(local_channel(),$papp)) + Apps::app_install(local_channel(),$papp); + if(Apps::app_installed(local_channel(),$papp)) info( t('App installed.') . EOL); + + $sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1", + intval(local_channel()), + dbesc($papp['guid']) + ); + + if (!$sync) { + return; + } + + if (intval($sync[0]['app_system'])) { + Libsync::build_sync_packet($uid, ['sysapp' => $sync]); + } + else { + Libsync::build_sync_packet($uid, ['app' => $sync]); + } + } - + if($_POST['delete']) { - Zlib\Apps::app_destroy(local_channel(),$papp); + + // Fetch the app for sync before it is deleted (if it is deletable)) + $sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1", + intval(local_channel()), + dbesc($papp['guid']) + ); + + if (!$sync) { + return; + } + + Apps::app_destroy(local_channel(), $papp); + + // Now flag it deleted + $sync[0]['app_deleted'] = 1; + + if (intval($sync[0]['app_system'])) { + Libsync::build_sync_packet($uid, ['sysapp' => $sync]); + } + else { + Libsync::build_sync_packet($uid, ['app' => $sync]); + } } if($_POST['edit']) { @@ -65,37 +103,65 @@ class Appman extends \Zotlabs\Web\Controller { } if($_POST['feature']) { - Zlib\Apps::app_feature(local_channel(), $papp, $_POST['feature']); + Apps::app_feature(local_channel(), $papp, $_POST['feature']); + + $sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1", + intval(local_channel()), + dbesc($papp['guid']) + ); + + if (intval($sync[0]['app_system'])) { + Libsync::build_sync_packet($uid, ['sysapp' => $sync]); + } + else { + Libsync::build_sync_packet($uid, ['app' => $sync]); + } } if($_POST['pin']) { - Zlib\Apps::app_feature(local_channel(), $papp, $_POST['pin']); + Apps::app_feature(local_channel(), $papp, $_POST['pin']); + + $sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1", + intval(local_channel()), + dbesc($papp['guid']) + ); + + if (intval($sync[0]['app_system'])) { + Libsync::build_sync_packet($uid, ['sysapp' => $sync]); + } + else { + Libsync::build_sync_packet($uid, ['app' => $sync]); + } } - if($_SESSION['return_url']) + if($_POST['aj']) { + killme(); + } + + if($_SESSION['return_url']) goaway(z_root() . '/' . $_SESSION['return_url']); goaway(z_root() . '/apps'); - - + + } - - + + function get() { - + if(! local_channel()) { notice( t('Permission denied.') . EOL); return; } - $channel = \App::get_channel(); + $channel = App::get_channel(); if(argc() > 3) { if(argv(2) === 'moveup') { - Zlib\Apps::moveup(local_channel(),argv(1),argv(3)); + Apps::moveup(local_channel(),argv(1),argv(3)); } if(argv(2) === 'movedown') { - Zlib\Apps::movedown(local_channel(),argv(1),argv(3)); + Apps::movedown(local_channel(),argv(1),argv(3)); } goaway(z_root() . '/apporder'); } @@ -129,12 +195,12 @@ class Appman extends \Zotlabs\Web\Controller { } } - $embed = array('embed', t('Embed code'), Zlib\Apps::app_encode($app,true),'', 'onclick="this.select();"'); - + $embed = array('embed', t('Embed code'), Apps::app_encode($app,true),'', 'onclick="this.select();"'); + } - + return replace_macros(get_markup_template('app_create.tpl'), array( - + '$banner' => (($app) ? t('Edit App') : t('Create App')), '$app' => $app, '$guid' => (($app) ? $app['app_id'] : ''), @@ -154,7 +220,7 @@ class Appman extends \Zotlabs\Web\Controller { '$embed' => $embed, '$submit' => t('Submit') )); - + } - + } diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php index 05b4495fc..77d1f2aec 100644 --- a/Zotlabs/Module/Apps.php +++ b/Zotlabs/Module/Apps.php @@ -9,7 +9,7 @@ class Apps extends \Zotlabs\Web\Controller { function get() { nav_set_selected('Apps'); - + if(argc() == 2 && argv(1) == 'edit') $mode = 'edit'; else @@ -18,9 +18,9 @@ class Apps extends \Zotlabs\Web\Controller { $available = ((argc() == 2 && argv(1) === 'available') ? true : false); $_SESSION['return_url'] = \App::$query_string; - + $apps = array(); - + if(local_channel()) { Zlib\Apps::import_system_apps(); $syslist = array(); @@ -37,9 +37,9 @@ class Apps extends \Zotlabs\Web\Controller { $syslist = Zlib\Apps::get_system_apps(true); usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare'); - + // logger('apps: ' . print_r($syslist,true)); - + foreach($syslist as $app) { $apps[] = Zlib\Apps::app_render($app,(($available) ? 'install' : $mode)); } @@ -53,7 +53,7 @@ class Apps extends \Zotlabs\Web\Controller { '$manage' => (($available) ? '' : t('Manage Apps')), '$create' => (($mode == 'edit') ? t('Create Custom App') : '') )); - + } - + } diff --git a/Zotlabs/Module/Apschema.php b/Zotlabs/Module/Apschema.php index 6b0325d44..e8d45c522 100644 --- a/Zotlabs/Module/Apschema.php +++ b/Zotlabs/Module/Apschema.php @@ -14,7 +14,7 @@ class Apschema extends \Zotlabs\Web\Controller { 'zot' => z_root() . '/apschema#', 'id' => '@id', 'type' => '@type', - 'commentPolicy' => 'as:commentPolicy', + 'commentPolicy' => 'zot:commentPolicy', 'meData' => 'zot:meData', 'meDataType' => 'zot:meDataType', 'meEncoding' => 'zot:meEncoding', @@ -33,6 +33,9 @@ class Apschema extends \Zotlabs\Web\Controller { 'PropertyValue' => 'schema:PropertyValue', 'value' => 'schema:value', + 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', + + 'magicEnv' => [ '@id' => 'zot:magicEnv', '@type' => '@id' @@ -50,7 +53,7 @@ class Apschema extends \Zotlabs\Web\Controller { 'guid' => 'diaspora:guid', 'Hashtag' => 'as:Hashtag' - + ] ]; diff --git a/Zotlabs/Module/Article_edit.php b/Zotlabs/Module/Article_edit.php index efa02e1c1..97c87f2ba 100644 --- a/Zotlabs/Module/Article_edit.php +++ b/Zotlabs/Module/Article_edit.php @@ -85,7 +85,6 @@ class Article_edit extends \Zotlabs\Web\Controller { $mimetype = $itm[0]['mimetype']; - $summary = (($itm[0]['summary']) ? '[summary]' . $itm[0]['summary'] . '[/summary]' . "\r\n" : ''); $content = $itm[0]['body']; $rp = 'articles/' . $channel['channel_address']; @@ -109,7 +108,7 @@ class Article_edit extends \Zotlabs\Web\Controller { 'ptyp' => $itm[0]['type'], 'mimeselect' => false, 'mimetype' => $itm[0]['mimetype'], - 'body' => $summary . undo_post_tagging($content), + 'body' => undo_post_tagging($content), 'post_id' => $post_id, 'visitor' => true, 'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index 9152f0e0e..0db098a31 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -48,10 +48,8 @@ class Articles extends Controller { if(! Apps::system_app_installed(App::$profile_uid, 'Articles')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Articles App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Create interactive articles'); - return $o; + $papp = Apps::get_papp('Articles'); + return Apps::app_render($papp, 'module'); } nav_set_selected('Articles'); diff --git a/Zotlabs/Module/Authtest.php b/Zotlabs/Module/Authtest.php index 239ae3bdb..d85af09dc 100644 --- a/Zotlabs/Module/Authtest.php +++ b/Zotlabs/Module/Authtest.php @@ -1,41 +1,38 @@ <?php namespace Zotlabs\Module; -require_once('include/zot.php'); - - class Authtest extends \Zotlabs\Web\Controller { function get() { - - + + $auth_success = false; $o .= '<h3>Magic-Auth Diagnostic</h3>'; - + if(! local_channel()) { notice( t('Permission denied.') . EOL); return $o; } - + $o .= '<form action="authtest" method="get">'; $o .= 'Target URL: <input type="text" style="width: 250px;" name="dest" value="' . $_GET['dest'] .'" />'; - $o .= '<input type="submit" name="submit" value="Submit" /></form>'; - + $o .= '<input type="submit" name="submit" value="Submit" /></form>'; + $o .= '<br /><br />'; - + if(x($_GET,'dest')) { if(strpos($_GET['dest'],'@')) { $_GET['dest'] = $_REQUEST['dest'] = 'https://' . substr($_GET['dest'],strpos($_GET['dest'],'@')+1) . '/channel/' . substr($_GET['dest'],0,strpos($_GET['dest'],'@')); } - + $_REQUEST['test'] = 1; $mod = new Magic(); $x = $mod->init($a); $o .= 'Local Setup returns: ' . print_r($x,true); - - - + + + if($x['url']) { $z = z_fetch_url($x['url'] . '&test=1'); if($z['success']) { @@ -50,12 +47,12 @@ class Authtest extends \Zotlabs\Web\Controller { $o .= 'fetch url failure.' . print_r($z,true); } } - + if(! $auth_success) $o .= 'Authentication Failed!' . EOL; } - + return str_replace("\n",'<br />',$o); } - + } diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php index 822b18308..659884fed 100644 --- a/Zotlabs/Module/Bookmarks.php +++ b/Zotlabs/Module/Bookmarks.php @@ -18,31 +18,31 @@ class Bookmarks extends \Zotlabs\Web\Controller { $item_id = (isset($_REQUEST['item']) ? $_REQUEST['item'] : false); $burl = (isset($_REQUEST['burl']) ? trim($_REQUEST['burl']) : ''); - + if(! $item_id) return; - + $u = \App::get_channel(); - + $item_normal = item_normal(); - + $i = q("select * from item where id = %d and uid = %d $item_normal limit 1", intval($item_id), intval(local_channel()) ); - + if(! $i) return; - + $i = fetch_post_tags($i); - + $item = $i[0]; - + $terms = (x($item, 'term') ? get_terms_oftype($item['term'],TERM_BOOKMARK) : false); - + if($terms) { require_once('include/bookmarks.php'); - + $s = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($item['author_xchan']) ); @@ -58,13 +58,13 @@ class Bookmarks extends \Zotlabs\Web\Controller { } else bookmark_add($u,$s[0],$t,$item['item_private']); - + info( t('Bookmark added') . EOL); } } killme(); } - + function get() { if(! local_channel()) { notice( t('Permission denied.') . EOL); @@ -74,49 +74,47 @@ class Bookmarks extends \Zotlabs\Web\Controller { if(! Apps::system_app_installed(local_channel(), 'Bookmarks')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Bookmarks App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Bookmark links from posts and manage them'); - return $o; + $papp = Apps::get_papp('Bookmarks'); + return Apps::app_render($papp, 'module'); } - + require_once('include/menu.php'); require_once('include/conversation.php'); - + $channel = \App::get_channel(); - + $o = ''; - + $o .= '<div class="generic-content-wrapper-styled">'; - - $o .= '<h3>' . t('My Bookmarks') . '</h3>'; - + + $o .= '<h3>' . t('Bookmarks') . '</h3>'; + $x = menu_list(local_channel(),'',MENU_BOOKMARK); - + if($x) { foreach($x as $xx) { $y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash()); $o .= menu_render($y,'',true); } } - + $o .= '<h3>' . t('My Connections Bookmarks') . '</h3>'; - - + + $x = menu_list(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK); - + if($x) { foreach($x as $xx) { $y = menu_fetch($xx['menu_name'],local_channel(),get_observer_hash()); $o .= menu_render($y,'',true); } } - + $o .= '</div>'; - + return $o; - + } - - + + } diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 8f47208ce..b71af6044 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -47,10 +47,8 @@ class Cards extends Controller { if(! Apps::system_app_installed(App::$profile_uid, 'Cards')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Cards App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Create personal planning cards'); - return $o; + $papp = Apps::get_papp('Cards'); + return Apps::app_render($papp, 'module'); } nav_set_selected('Cards'); diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index e26cdd072..599552545 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -873,10 +873,8 @@ class Cdav extends Controller { if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('CardDAV App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('CalDAV capable addressbook'); - return $o; + $papp = Apps::get_papp('CardDAV'); + return Apps::app_render($papp, 'module'); } App::$profile_uid = local_channel(); @@ -1059,6 +1057,7 @@ class Cdav extends Controller { '$cancel' => t('Cancel'), '$create' => t('Create'), '$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.'), + '$disabled_warning' => t('Could not fetch calendar resource. The selected calendar might be disabled.'), '$channel_hash' => $channel['channel_hash'], '$acl' => $acl, diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index a7deb4f6b..aebc70c15 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -46,14 +46,15 @@ class Channel extends Controller { } $profile = 0; - $channel = App::get_channel(); if ((local_channel()) && (argc() > 2) && (argv(2) === 'view')) { + $channel = App::get_channel(); $which = $channel['channel_address']; $profile = argv(1); } - $channel = channelx_by_nick($which); + $channel = channelx_by_nick($which, true); + if (!$channel) { http_status_exit(404, 'Not found'); } @@ -65,8 +66,8 @@ class Channel extends Controller { $sigdata = HTTPSig::verify(file_get_contents('php://input'), EMPTY_STR, 'zot6'); if ($sigdata && $sigdata['signer'] && $sigdata['header_valid']) { - $data = json_encode(Libzot::zotinfo(['address' => $channel['channel_address'], 'target_url' => $sigdata['signer']])); - $s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", + $data = json_encode(Libzot::zotinfo(['guid_hash' => $channel['channel_hash'], 'target_url' => $sigdata['signer']])); + $s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($sigdata['signer']) ); @@ -83,24 +84,31 @@ class Channel extends Controller { 'Digest' => HTTPSig::generate_digest_header($data), '(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'] ]; - $h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel)); + + $h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel)); HTTPSig::set_headers($h); echo $data; killme(); } + if ($channel['channel_removed']) { + http_status_exit(410, 'Gone'); + } + + if (get_pconfig($channel['channel_id'], 'system', 'index_opt_out')) { + App::$meta->set('robots', 'noindex, noarchive'); + } + if (ActivityStreams::is_as_request($channel)) { // Somebody may attempt an ActivityStreams fetch on one of our message permalinks // Make it do the right thing. - $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : ''); - if ($mid && strpos($mid, 'b64.') === 0) { - $decoded = @base64url_decode(substr($mid, 4)); - if ($decoded) { - $mid = $decoded; - } + $mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : ''); + if ($mid === false) { + http_status_exit(404, 'Not found'); } + if ($mid) { $obj = null; if (strpos($mid, z_root() . '/item/') === 0) { @@ -145,15 +153,19 @@ class Channel extends Controller { profile_load($which, $profile); // Add Opengraph markup - $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : ''); - if (strpos($mid, 'b64.') === 0) - $mid = @base64url_decode(substr($mid, 4)); + $mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : ''); - if ($mid) + if ($mid === false) { + notice(t('Malformed message id.') . EOL); + return; + } + + if ($mid) { $r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1", dbesc($mid), intval($channel['channel_id']) ); + } opengraph_add_meta((isset($r) && count($r) ? $r[0] : []), $channel); } @@ -164,12 +176,11 @@ class Channel extends Controller { $category = $datequery = $datequery2 = ''; - $mid = ((x($_REQUEST, 'mid')) ? $_REQUEST['mid'] : ''); - - if (strpos($mid, 'b64.') === 0) - $decoded = @base64url_decode(substr($mid, 4)); - if (isset($decoded)) - $mid = $decoded; + $mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : ''); + if ($mid === false) { + notice(t('Malformed message id.') . EOL); + return; + } $datequery = ((x($_GET, 'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : ''); $datequery2 = ((x($_GET, 'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : ''); @@ -213,7 +224,7 @@ class Channel extends Controller { if (!$update) { - nav_set_selected('Channel Home'); + nav_set_selected('Channel'); // search terms header if ($search) { @@ -420,8 +431,8 @@ class Channel extends Controller { if ((!$update) && (!$load)) { - if (isset($decoded)) - $mid = 'b64.' . base64url_encode($mid); + //if we got a decoded hash we must encode it again before handing to javascript + $mid = gen_link_id($mid); // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, // because browser prefetching might change it on us. We have to deliver it with the page. diff --git a/Zotlabs/Module/Chanview.php b/Zotlabs/Module/Chanview.php index 8ae4841b4..fc1146023 100644 --- a/Zotlabs/Module/Chanview.php +++ b/Zotlabs/Module/Chanview.php @@ -10,49 +10,49 @@ use Zotlabs\Lib\Zotfinger; class Chanview extends \Zotlabs\Web\Controller { function get() { - + $observer = App::get_observer(); $xchan = null; - + $r = null; - + if($_REQUEST['hash']) { - $r = q("select * from xchan where xchan_hash = '%s'", + $r = q("select * from xchan where xchan_hash = '%s' and xchan_deleted = 0", dbesc($_REQUEST['hash']) ); } if($_REQUEST['address']) { - $r = q("select * from xchan where xchan_addr = '%s'", + $r = q("select * from xchan where xchan_addr = '%s' and xchan_deleted = 0", dbesc(punify($_REQUEST['address'])) ); } elseif(local_channel() && intval($_REQUEST['cid'])) { - $r = q("SELECT abook.*, xchan.* + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d and abook_id = %d", + WHERE abook_channel = %d and abook_id = %d and xchan_deleted = 0", intval(local_channel()), intval($_REQUEST['cid']) ); - } + } elseif($_REQUEST['url']) { - + // if somebody re-installed they will have more than one xchan, use the most recent name date as this is - // the most useful consistently ascending table item we have. - - $r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc", + // the most useful consistently ascending table item we have. + + $r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0 order by xchan_name_date desc", dbesc($_REQUEST['url']) ); } if($r) { App::$poi = Libzot::zot_record_preferred($r, 'xchan_network'); } - - + + // Here, let's see if we have an xchan. If we don't, how we proceed is determined by what - // info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or - // address, we can and should try to import it. If it's just a hash, we can't continue, but we + // info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or + // address, we can and should try to import it. If it's just a hash, we can't continue, but we // probably wouldn't have a hash if we don't already have an xchan for this channel. - + if(! App::$poi) { logger('mod_chanview: fallback'); @@ -71,7 +71,7 @@ class Chanview extends \Zotlabs\Web\Controller { if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $_REQUEST['url'] && intval($zf['signature']['header_valid'])) { Libzot::import_xchan($zf['data']); - $r = q("select * from xchan where xchan_url = '%s'", + $r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0", dbesc($_REQUEST['url']) ); if($r) { @@ -80,7 +80,7 @@ class Chanview extends \Zotlabs\Web\Controller { } if(! $r) { if(discover_by_webbie($_REQUEST['url'])) { - $r = q("select * from xchan where xchan_url = '%s'", + $r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0", dbesc($_REQUEST['url']) ); if($r) { @@ -90,7 +90,7 @@ class Chanview extends \Zotlabs\Web\Controller { } } } - + if(! App::$poi) { notice( t('Channel not found.') . EOL); return; @@ -98,9 +98,9 @@ class Chanview extends \Zotlabs\Web\Controller { $is_zot = false; $connected = false; - + $url = App::$poi['xchan_url']; - if(in_array(App::$poi['xchan_network'], ['zot', 'zot6'])) { + if(App::$poi['xchan_network'] === 'zot6') { $is_zot = true; } if(local_channel()) { @@ -111,29 +111,29 @@ class Chanview extends \Zotlabs\Web\Controller { if($c) $connected = true; } - - // We will load the chanview template if it's a foreign network, + + // We will load the chanview template if it's a foreign network, // just so that we can provide a connect button along with a profile // photo. Chances are we can't load the remote profile into an iframe // because of cross-domain security headers. So provide a link to - // the remote profile. + // the remote profile. // If we are already connected, just go to the profile. // Zot channels will usually have a connect link. - + if($is_zot || $connected) { if($is_zot && $observer) { $url = zid($url); } goaway($url); } - else { + else { $o = replace_macros(get_markup_template('chanview.tpl'),array( '$url' => $url, '$full' => t('toggle full screen mode') )); - + return $o; } } - + } diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index 28e775f9d..323471161 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -14,7 +14,7 @@ require_once('include/bookmarks.php'); class Chat extends Controller { function init() { - + $which = null; if(argc() > 1) $which = argv(1); @@ -29,79 +29,77 @@ class Chat extends Controller { notice( t('You must be logged in to see this page.') . EOL ); return; } - + $profile = 0; $channel = App::get_channel(); - + if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) { $which = $channel['channel_address']; - $profile = argv(1); + $profile = argv(1); } - + // Run profile_load() here to make sure the theme is set before // we start loading content - + profile_load($which,$profile); - + } - + function post() { - + if($_POST['room_name']) - $room = strip_tags(trim($_POST['room_name'])); - + $room = strip_tags(trim($_POST['room_name'])); + if((! $room) || (! local_channel())) return; - + $channel = App::get_channel(); - - + + if($_POST['action'] === 'drop') { logger('delete chatroom'); Chatroom::destroy($channel,array('cr_name' => $room)); goaway(z_root() . '/chat/' . $channel['channel_address']); } - + $acl = new AccessList($channel); $acl->set_from_array($_REQUEST); - + $arr = $acl->get(); $arr['name'] = $room; $arr['expire'] = intval($_POST['chat_expire']); if(intval($arr['expire']) < 0) $arr['expire'] = 0; - + Chatroom::create($channel,$arr); - + $x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1", dbesc($room), intval(local_channel()) ); - + Libsync::build_sync_packet(0, array('chatroom' => $x)); - + if($x) goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']); - + // that failed. Try again perhaps? - + goaway(z_root() . '/chat/' . $channel['channel_address'] . '/new'); - - + + } - - + + function get() { if(! Apps::system_app_installed(App::$profile_uid, 'Chatrooms')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Chatrooms App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Access Controlled Chatrooms'); - return $o; + $papp = Apps::get_papp('Chatrooms'); + return Apps::app_render($papp, 'module'); } - + if(local_channel()) { $channel = App::get_channel(); nav_set_selected('Chatrooms'); @@ -113,24 +111,24 @@ class Chat extends Controller { notice( t('Permission denied.') . EOL); return; } - + if(! perm_is_allowed(App::$profile['profile_uid'],$observer,'chat')) { notice( t('Permission denied.') . EOL); return; } - + if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) { Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']); goaway(z_root() . '/channel/' . argv(1)); } - - + + if((argc() > 3) && intval(argv(2)) && (argv(3) === 'status')) { $ret = array('success' => false); $room_id = intval(argv(2)); if(! $room_id || ! $observer) return; - + $r = q("select * from chatroom where cr_id = %d limit 1", intval($room_id) ); @@ -139,7 +137,7 @@ class Chat extends Controller { } require_once('include/security.php'); $sql_extra = permissions_sql($r[0]['cr_uid']); - + $x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1", intval($room_id), intval($r[0]['cr_uid']) @@ -155,9 +153,9 @@ class Chat extends Controller { $ret['chatroom'] = $r[0]['cr_name']; $ret['inroom'] = $y[0]['total']; } - + // figure out how to present a timestamp of the last activity, since we don't know the observer's timezone. - + $z = q("select created from chat where chat_room = %d order by created desc limit 1", intval($room_id) ); @@ -166,13 +164,13 @@ class Chat extends Controller { } json_return_and_die($ret); } - - + + if(argc() > 2 && intval(argv(2))) { - + $room_id = intval(argv(2)); $bookmark_link = get_bookmark_link($ob); - + $x = Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']); if(! $x) return; @@ -180,26 +178,26 @@ class Chat extends Controller { intval($room_id), intval(App::$profile['profile_uid']) ); - + if($x) { $acl = new AccessList(false); $acl->set($x[0]); - + $private = $acl->is_private(); $room_name = $x[0]['cr_name']; if($bookmark_link) - $bookmark_link .= '&url=' . z_root() . '/chat/' . argv(1) . '/' . argv(2) . '&title=' . urlencode($x[0]['cr_name']) . (($private) ? '&private=1' : '') . '&ischat=1'; + $bookmark_link .= '&url=' . z_root() . '/chat/' . argv(1) . '/' . argv(2) . '&title=' . urlencode($x[0]['cr_name']) . (($private) ? '&private=1' : '') . '&ischat=1'; } else { notice( t('Room not found') . EOL); return; } - + $cipher = get_pconfig(local_channel(),'system','default_cipher'); if(! $cipher) $cipher = 'AES-128-CCM'; - - + + $o = replace_macros(get_markup_template('chat.tpl'),array( '$is_owner' => ((local_channel() && local_channel() == $x[0]['cr_uid']) ? true : false), '$room_name' => $room_name, @@ -223,7 +221,7 @@ class Chat extends Controller { } require_once('include/conversation.php'); - + $o = ''; $acl = new AccessList($channel); @@ -246,12 +244,12 @@ class Chat extends Controller { '$deny_gid' => acl2json($channel_acl['deny_gid']), '$lockstate' => $lockstate, '$submit' => t('Submit') - + )); } $rooms = Chatroom::roomlist(App::$profile['profile_uid']); - + $o .= replace_macros(get_markup_template('chatrooms.tpl'), array( '$header' => sprintf( t('%1$s\'s Chatrooms'), App::$profile['fullname']), '$name' => t('Name'), @@ -259,15 +257,15 @@ class Chat extends Controller { '$nickname' => App::$profile['channel_address'], '$rooms' => $rooms, '$norooms' => t('No chatrooms available'), - '$newroom' => t('Create New'), + '$newroom' => t('Add Room'), '$is_owner' => ((local_channel() && local_channel() == App::$profile['profile_uid']) ? 1 : 0), '$chatroom_new' => $chatroom_new, '$expire' => t('Expiration'), '$expire_unit' => t('min') //minutes )); - + return $o; - + } - + } diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index 5025f4e22..0f674965d 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -2,32 +2,32 @@ namespace Zotlabs\Module; use App; +use Zotlabs\Lib\Permcat; require_once('include/socgraph.php'); require_once('include/selectors.php'); -require_once('include/group.php'); class Connections extends \Zotlabs\Web\Controller { function init() { - + if(! local_channel()) return; App::$profile_uid = local_channel(); - + $channel = App::get_channel(); if($channel) head_set_icon($channel['xchan_photo_s']); - + } - + function get() { - + $sort_type = 0; $o = ''; - - + + if(! local_channel()) { notice( t('Permission denied.') . EOL); return login(); @@ -44,13 +44,13 @@ class Connections extends \Zotlabs\Web\Controller { $pending = false; $unconnected = false; $all = false; - + if(! $_REQUEST['aj']) $_SESSION['return_url'] = App::$query_string; - + $search_flags = ""; $head = ''; - + if(argc() == 2) { switch(argv(1)) { case 'active': @@ -106,7 +106,7 @@ class Connections extends \Zotlabs\Web\Controller { // $head = t('Unconnected'); // $unconnected = true; // break; - + case 'all': $head = t('All'); break; @@ -115,19 +115,19 @@ class Connections extends \Zotlabs\Web\Controller { $active = true; $head = t('Active'); break; - + } - + $sql_extra = $search_flags; if(argv(1) === 'pending') $sql_extra .= " and abook_ignored = 0 "; - + } else { $sql_extra = " and abook_blocked = 0 "; $unblocked = true; } - + switch($_REQUEST['order']) { case 'name_desc': $sql_order = 'xchan_name DESC'; @@ -143,32 +143,32 @@ class Connections extends \Zotlabs\Web\Controller { } $search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : ''); - + $tabs = array( /* array( 'label' => t('Suggestions'), - 'url' => z_root() . '/suggest', + 'url' => z_root() . '/suggest', 'sel' => '', 'title' => t('Suggest new connections'), ), */ - + 'active' => array( 'label' => t('Active Connections'), - 'url' => z_root() . '/connections/active', + 'url' => z_root() . '/connections/active', 'sel' => ($active) ? 'active' : '', 'title' => t('Show active connections'), ), 'pending' => array( 'label' => t('New Connections'), - 'url' => z_root() . '/connections/pending', + 'url' => z_root() . '/connections/pending', 'sel' => ($pending) ? 'active' : '', 'title' => t('Show pending (new) connections'), ), - - + + /* array( 'label' => t('Unblocked'), @@ -177,55 +177,55 @@ class Connections extends \Zotlabs\Web\Controller { 'title' => t('Only show unblocked connections'), ), */ - + 'blocked' => array( 'label' => t('Blocked'), 'url' => z_root() . '/connections/blocked', 'sel' => ($blocked) ? 'active' : '', 'title' => t('Only show blocked connections'), ), - + 'ignored' => array( 'label' => t('Ignored'), 'url' => z_root() . '/connections/ignored', 'sel' => ($ignored) ? 'active' : '', 'title' => t('Only show ignored connections'), ), - + 'archived' => array( 'label' => t('Archived/Unreachable'), 'url' => z_root() . '/connections/archived', 'sel' => ($archived) ? 'active' : '', 'title' => t('Only show archived/unreachable connections'), ), - + 'hidden' => array( 'label' => t('Hidden'), 'url' => z_root() . '/connections/hidden', 'sel' => ($hidden) ? 'active' : '', 'title' => t('Only show hidden connections'), ), - + // array( // 'label' => t('Unconnected'), // 'url' => z_root() . '/connections/unconnected', // 'sel' => ($unconnected) ? 'active' : '', // 'title' => t('Only show one-way connections'), // ), - + 'all' => array( 'label' => t('All Connections'), - 'url' => z_root() . '/connections', + 'url' => z_root() . '/connections', 'sel' => ($all) ? 'active' : '', 'title' => t('Show all connections'), ), - + ); - + //$tab_tpl = get_markup_template('common_tabs.tpl'); //$t = replace_macros($tab_tpl, array('$tabs'=>$tabs)); - + $searching = false; if($search) { $search_hdr = $search; @@ -233,12 +233,12 @@ class Connections extends \Zotlabs\Web\Controller { $searching = true; } $sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : ""); - + if($_REQUEST['gid']) { $sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) "; } - - $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash + + $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ", intval(local_channel()) ); @@ -246,19 +246,27 @@ class Connections extends \Zotlabs\Web\Controller { App::set_pager_total($r[0]['total']); $total = $r[0]['total']; } - + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ORDER BY $sql_order LIMIT %d OFFSET %d ", intval(local_channel()), intval(App::$pager['itemspage']), intval(App::$pager['start']) ); - + + $roles = new Permcat(local_channel()); + $roles_list = $roles->listing(); + $roles_dict = []; + + foreach ($roles_list as $role) { + $roles_dict[$role['name']] = $role['localname']; + } + $contacts = array(); - + if($r) { - vcard_query($r); + //vcard_query($r); foreach($r as $rr) { @@ -268,7 +276,7 @@ class Connections extends \Zotlabs\Web\Controller { $phone = $rr['vcard']['tels'][0]['nr']; else $phone = ''; - + $status_str = ''; $status = array( ((intval($rr['abook_active'])) ? t('Active') : ''), @@ -306,7 +314,7 @@ class Connections extends \Zotlabs\Web\Controller { $perminfo['connperms'] .= t('Nothing'); } - + foreach($status as $str) { if(!$str) continue; @@ -314,19 +322,16 @@ class Connections extends \Zotlabs\Web\Controller { $status_str .= ', '; } $status_str = rtrim($status_str, ', '); - + $contacts[] = array( 'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']), 'edit_hover' => t('Edit connection'), 'edit' => t('Edit'), 'delete_hover' => t('Delete connection'), 'id' => $rr['abook_id'], - 'thumb' => $rr['xchan_photo_m'], + 'thumb' => $rr['xchan_photo_m'], 'name' => $rr['xchan_name'], 'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''), - 'link' => z_root() . '/connedit/' . $rr['abook_id'], - 'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop', - 'delete' => t('Delete'), 'url' => chanlink_hash($rr['xchan_hash']), 'webbie_label' => t('Channel address'), 'webbie' => $rr['xchan_addr'], @@ -337,6 +342,7 @@ class Connections extends \Zotlabs\Web\Controller { 'phone' => $phone, 'status_label' => t('Status'), 'status' => $status_str, + 'states' => $status, 'connected_label' => t('Connected'), 'connected' => datetime_convert('UTC',date_default_timezone_get(),$rr['abook_created'], 'c'), 'approve_hover' => t('Approve connection'), @@ -349,13 +355,22 @@ class Connections extends \Zotlabs\Web\Controller { 'perminfo' => $perminfo, 'connect' => (intval($rr['abook_not_here']) ? t('Connect') : ''), 'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=0', - 'connect_hover' => t('Connect at this location') + 'connect_hover' => t('Connect at this location'), + 'role' => $roles_dict[$rr['abook_role']], + 'pending' => intval($rr['abook_pending']) ); } } } - - + + $limit = service_class_fetch(local_channel(),'total_channels'); + if($limit !== false) { + $abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $$total, $limit); + } + else { + $abook_usage_message = ''; + } + if($_REQUEST['aj']) { if($contacts) { $o = replace_macros(get_markup_template('contactsajax.tpl'),array( @@ -371,27 +386,30 @@ class Connections extends \Zotlabs\Web\Controller { } else { $o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>"; - $o .= replace_macros(get_markup_template('connections.tpl'),array( + $o .= replace_macros(get_markup_template('connections.tpl'), [ '$header' => t('Connections') . (($head) ? ': ' . $head : ''), '$tabs' => $tabs, '$total' => $total, '$search' => $search_hdr, '$label' => t('Search'), + '$role_label' => t('Contact role'), '$desc' => t('Search your connections'), - '$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""), + '$finding' => (($searching) ? t('Contact search') . ": '" . $search . "'" : ""), '$submit' => t('Find'), '$edit' => t('Edit'), + '$approve' => t('Approve'), '$cmd' => App::$cmd, '$contacts' => $contacts, '$paginate' => paginate($a), - - )); + '$abook_usage_message' => $abook_usage_message, + '$group_label' => t('This is a group/forum channel') + ]); } - + if(! $contacts) $o .= '<div id="content-complete"></div>'; - + return $o; } - + } diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index 44211c8b9..6bebef026 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -1,4 +1,5 @@ <?php + namespace Zotlabs\Module; /* @file connedit.php @@ -8,8 +9,8 @@ namespace Zotlabs\Module; */ use App; +use Sabre\VObject\Reader; use Zotlabs\Lib\Apps; -use Zotlabs\Lib\Crypto; use Zotlabs\Lib\Libzot; use Zotlabs\Lib\Libsync; use Zotlabs\Daemon\Master; @@ -18,13 +19,12 @@ use Zotlabs\Access\Permissions; use Zotlabs\Access\PermissionLimits; use Zotlabs\Web\HTTPHeaders; use Zotlabs\Lib\Permcat; +use Zotlabs\Lib\AccessList; require_once('include/socgraph.php'); require_once('include/selectors.php'); -require_once('include/group.php'); require_once('include/photos.php'); - class Connedit extends Controller { /* @brief Initialize the connection-editor @@ -34,26 +34,25 @@ class Connedit extends Controller { function init() { - if(! local_channel()) + if (!local_channel()) return; - if((argc() >= 2) && intval(argv(1))) { + if ((argc() >= 2) && intval(argv(1))) { $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_channel = %d and abook_id = %d LIMIT 1", + WHERE abook_channel = %d and abook_id = %d and abook_self = 0 and xchan_deleted = 0 LIMIT 1", intval(local_channel()), intval(argv(1)) ); - if($r) { - App::$poi = array_shift($r); + if ($r) { + App::$poi = $r[0]; } } - $channel = App::get_channel(); - if($channel) + if ($channel) { head_set_icon($channel['xchan_photo_s']); - + } } @@ -63,191 +62,98 @@ class Connedit extends Controller { function post() { - if(! local_channel()) + if (!local_channel()) return; $contact_id = intval(argv(1)); - if(! $contact_id) + if (!$contact_id) return; $channel = App::get_channel(); - // TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the - // connection enable is toggled to a special autopost url and set permissions immediately, leaving - // the other form elements alone pending a manual submit of the form. The downside is that there - // will be a window of opportunity when the permissions have been set but before you've had a chance - // to review and possibly restrict them. The upside is we won't have to warn you that your connection - // can't do anything until you save the bloody form. - - $autopost = (((argc() > 2) && (argv(2) === 'auto')) ? true : false); - - $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1", + $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1", intval($contact_id), intval(local_channel()) ); - if(! $orig_record) { - notice( t('Could not access contact record.') . EOL); + if (!$orig_record) { + notice(t('Could not access contact record.') . EOL); goaway(z_root() . '/connections'); return; // NOTREACHED } call_hooks('contact_edit_post', $_POST); - $vc = get_abconfig(local_channel(),$orig_record['abook_xchan'],'system','vcard'); - $vcard = (($vc) ? \Sabre\VObject\Reader::read($vc) : null); - $serialised_vcard = update_vcard($_REQUEST,$vcard); - if($serialised_vcard) - set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$serialised_vcard); - - if(intval($orig_record[0]['abook_self'])) { - $autoperms = intval($_POST['autoperms']); - $is_self = true; - } - else { - $autoperms = null; - $is_self = false; - } + $vc = get_abconfig(local_channel(), $orig_record['abook_xchan'], 'system', 'vcard'); + $vcard = (($vc) ? Reader::read($vc) : null); + $serialised_vcard = update_vcard($_REQUEST, $vcard); + if ($serialised_vcard) + set_abconfig(local_channel(), $orig_record[0]['abook_xchan'], 'system', 'vcard', $serialised_vcard); + $profile_id = ((array_key_exists('profile_assign', $_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']); - $profile_id = ((array_key_exists('profile_assign',$_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']); - - if($profile_id) { + if ($profile_id) { $r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1", dbesc($profile_id), intval(local_channel()) ); - if(! count($r)) { - notice( t('Could not locate selected profile.') . EOL); + if (!count($r)) { + notice(t('Could not locate selected profile.') . EOL); return; } } - $abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']); - $abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']); - - - $hidden = intval($_POST['hidden']); + $abook_incl = ((array_key_exists('abook_incl', $_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']); + $abook_excl = ((array_key_exists('abook_excl', $_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']); + $abook_role = ((array_key_exists('permcat', $_POST)) ? escape_tags($_POST['permcat']) : $orig_record[0]['abook_role']); - $priority = intval($_POST['poll']); - if($priority > 5 || $priority < 0) - $priority = 0; - - if(! array_key_exists('closeness',$_POST)) { + if (!array_key_exists('closeness', $_POST)) { $_POST['closeness'] = 80; } $closeness = intval($_POST['closeness']); - if($closeness < 0 || $closeness > 99) { + if ($closeness < 0 || $closeness > 99) { $closeness = 80; } - $rating = intval($_POST['rating']); - if($rating < (-10)) - $rating = (-10); - if($rating > 10) - $rating = 10; - - $rating_text = trim(escape_tags($_REQUEST['rating_text'])); + $new_friend = ((intval($orig_record[0]['abook_pending'])) ? true : false); - $all_perms = Permissions::Perms(); +/* + $perms = []; + $permcats = new Permcat(local_channel()); + $role_perms = $permcats->fetch($abook_role); + $all_perms = Permissions::Perms(); - if($all_perms) { - foreach($all_perms as $perm => $desc) { - if(array_key_exists('perms_' . $perm, $_POST)) { - set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm, - intval($_POST['perms_' . $perm])); - if($autoperms) { - set_pconfig($channel['channel_id'],'autoperms',$perm,intval($_POST['perms_' . $perm])); - } - } - else { - set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,0); - if($autoperms) { - set_pconfig($channel['channel_id'],'autoperms',$perm,0); - } - } - } + // if we got a valid role use the role (default behaviour because a role is mandatory since version 7.0) + if (!isset($role_perms['error'])) { + $perms = $role_perms['raw_perms']; + if (intval($orig_record[0]['abook_pending'])) + $new_friend = true; } - if(! is_null($autoperms)) - set_pconfig($channel['channel_id'],'system','autoperms',$autoperms); - - $new_friend = false; - - // only store a record and notify the directory if the rating changed - - if(! $is_self) { - - $signed = $orig_record[0]['abook_xchan'] . '.' . $rating . '.' . $rating_text; - $sig = base64url_encode(Crypto::sign($signed,$channel['channel_prvkey'])); - - $rated = ((intval($rating) || strlen($rating_text)) ? true : false); - - $record = 0; - - $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", - dbesc($channel['channel_hash']), - dbesc($orig_record[0]['abook_xchan']) - ); - - if($z) { - if(($z[0]['xlink_rating'] != $rating) || ($z[0]['xlink_rating_text'] != $rating_text)) { - $record = $z[0]['xlink_id']; - $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s' - where xlink_id = %d", - intval($rating), - dbesc($rating_text), - dbesc($sig), - dbesc(datetime_convert()), - intval($record) - ); - } - } - elseif($rated) { - // only create a record if there's something to save - $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", - dbesc($channel['channel_hash']), - dbesc($orig_record[0]['abook_xchan']), - intval($rating), - dbesc($rating_text), - dbesc($sig), - dbesc(datetime_convert()) - ); - $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", - dbesc($channel['channel_hash']), - dbesc($orig_record[0]['abook_xchan']) - ); - if($z) - $record = $z[0]['xlink_id']; - } - if($record) { - Master::Summon(array('Ratenotif','rating',$record)); - } - } - - if(($_REQUEST['pending']) && intval($orig_record[0]['abook_pending'])) { - + // approve shortcut (no role provided) + if (!$perms && intval($orig_record[0]['abook_pending'])) { + $connect_perms = Permissions::connect_perms(local_channel()); + $perms = $connect_perms['perms']; + // set the role from $connect_perms + $abook_role = $connect_perms['role']; $new_friend = true; + } - // @fixme it won't be common, but when you accept a new connection request - // the permissions will now be that of your permissions role and ignore - // any you may have set manually on the form. We'll probably see a bug if somebody - // tries to set the permissions *and* approve the connection in the same - // request. The workaround is to approve the connection, then go back and - // adjust permissions as desired. - - $p = Permissions::connect_perms(local_channel()); - $my_perms = $p['perms']; - if($my_perms) { - foreach($my_perms as $k => $v) { - set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$k,$v); + if ($all_perms && $perms) { + foreach ($all_perms as $perm => $desc) { + if (array_key_exists($perm, $perms)) { + set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $perm, intval($perms[$perm])); + } + else { + set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $perm, 0); } } } +*/ - $abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']); - + \Zotlabs\Lib\Permcat::assign($channel, $abook_role, [$orig_record[0]['abook_xchan']]); + $abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']); $r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d, abook_incl = '%s', abook_excl = '%s' @@ -261,30 +167,29 @@ class Connedit extends Controller { intval(local_channel()) ); - if($r) - info( t('Connection updated.') . EOL); + if ($r) + info(t('Connection updated.') . EOL); else - notice( t('Failed to update connection record.') . EOL); + notice(t('Failed to update connection record.') . EOL); - if(! intval(App::$poi['abook_self'])) { - if($new_friend) { - Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] ); + if (!intval(App::$poi['abook_self'])) { + if ($new_friend) { + Master::Summon(['Notifier', 'permission_accept', $contact_id]); } - Master::Summon( [ + Master::Summon([ 'Notifier', (($new_friend) ? 'permission_create' : 'permission_update'), $contact_id ]); } - if($new_friend) { + if ($new_friend) { $default_group = $channel['channel_default_group']; - if($default_group) { - require_once('include/group.php'); - $g = group_rec_byhash(local_channel(),$default_group); - if($g) - group_add_member(local_channel(),'',App::$poi['abook_xchan'],$g['id']); + if ($default_group) { + $g = AccessList::by_hash(local_channel(), $default_group); + if ($g) + AccessList::member_add(local_channel(), '', App::$poi['abook_xchan'], $g['id']); } // Check if settings permit ("post new friend activity" is allowed, and @@ -294,18 +199,18 @@ class Connedit extends Controller { $pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0", intval($channel['channel_id']) ); - if(($pr) && (! intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'],'system','post_newfriend')))) { + if (($pr) && (!intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) { $xarr = []; - $xarr['item_wall'] = 1; - $xarr['item_origin'] = 1; + $xarr['item_wall'] = 1; + $xarr['item_origin'] = 1; $xarr['item_thread_top'] = 1; - $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash']; - $xarr['allow_cid'] = $channel['channel_allow_cid']; - $xarr['allow_gid'] = $channel['channel_allow_gid']; - $xarr['deny_cid'] = $channel['channel_deny_cid']; - $xarr['deny_gid'] = $channel['channel_deny_gid']; - $xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0); + $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash']; + $xarr['allow_cid'] = $channel['channel_allow_cid']; + $xarr['allow_gid'] = $channel['channel_allow_gid']; + $xarr['deny_cid'] = $channel['channel_deny_cid']; + $xarr['deny_gid'] = $channel['channel_deny_gid']; + $xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0); $xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . App::$poi['xchan_url'] . ']' . App::$poi['xchan_name'] . '[/zrl]'; @@ -315,9 +220,8 @@ class Connedit extends Controller { } - // pull in a bit of content if there is any to pull in - Master::Summon(array('Onepoll',$contact_id)); + Master::Summon(['Onepoll', $contact_id]); } @@ -329,18 +233,18 @@ class Connedit extends Controller { intval(local_channel()), intval($contact_id) ); - if($r) { + if ($r) { App::$poi = $r[0]; } - if($new_friend) { - $arr = array('channel_id' => local_channel(), 'abook' => App::$poi); + if ($new_friend) { + $arr = ['channel_id' => local_channel(), 'abook' => App::$poi]; call_hooks('accept_follow', $arr); } - $this->connedit_clone($a); + $this->connedit_clone(); - if(($_REQUEST['pending']) && (!$_REQUEST['done'])) + if (($_REQUEST['pending']) && (!$_REQUEST['done'])) goaway(z_root() . '/connections/ifpending'); return; @@ -352,35 +256,34 @@ class Connedit extends Controller { * */ - function connedit_clone(&$a) { - - if(! App::$poi) - return; + function connedit_clone() { + if (!App::$poi) + return; - $channel = App::get_channel(); + $channel = App::get_channel(); - $r = q("SELECT abook.*, xchan.* + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d and abook_id = %d LIMIT 1", - intval(local_channel()), - intval(App::$poi['abook_id']) - ); - if($r) { - App::$poi = array_shift($r); - } + intval(local_channel()), + intval(App::$poi['abook_id']) + ); + if ($r) { + App::$poi = $r[0]; + } - $clone = App::$poi; + $clone = App::$poi; - unset($clone['abook_id']); - unset($clone['abook_account']); - unset($clone['abook_channel']); + unset($clone['abook_id']); + unset($clone['abook_account']); + unset($clone['abook_channel']); - $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); - if($abconfig) - $clone['abconfig'] = $abconfig; + $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']); + if ($abconfig) + $clone['abconfig'] = $abconfig; - Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone))); + Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]); } /* @brief Generate content of connection edit page @@ -390,76 +293,58 @@ class Connedit extends Controller { function get() { - $sort_type = 0; $o = ''; - if(! local_channel()) { - notice( t('Permission denied.') . EOL); + if (!local_channel()) { + notice(t('Permission denied.') . EOL); return login(); } - $section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : ''); - $channel = App::get_channel(); - - $yes_no = array(t('No'),t('Yes')); - - $connect_perms = Permissions::connect_perms(local_channel()); - - $o .= "<script>function connectDefaultShare() { - \$('.abook-edit-me').each(function() { - if(! $(this).is(':disabled')) - $(this).prop('checked', false); - });\n\n"; - foreach($connect_perms['perms'] as $p => $v) { - if($v) { - $o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n"; - } - } - $o .= " }\n</script>\n"; + $section = ((array_key_exists('section', $_REQUEST)) ? $_REQUEST['section'] : ''); - if(argc() == 3) { + if (argc() == 3) { $contact_id = intval(argv(1)); - if(! $contact_id) + if (!$contact_id) return; $cmd = argv(2); $orig_record = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash - WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1", + WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 and xchan_deleted = 0 LIMIT 1", intval($contact_id), intval(local_channel()) ); - if(! count($orig_record)) { - notice( t('Could not access address book record.') . EOL); + if (!count($orig_record)) { + notice(t('Could not access address book record.') . EOL); goaway(z_root() . '/connections'); } - if($cmd === 'update') { + if ($cmd === 'update') { // pull feed and consume it, which should subscribe to the hub. - Master::Summon(array('Poller',$contact_id)); + Master::Summon(['Poller', $contact_id]); goaway(z_root() . '/connedit/' . $contact_id); } - if($cmd === 'fetchvc') { - $url = str_replace('/channel/','/profile/',$orig_record[0]['xchan_url']) . '/vcard'; + if ($cmd === 'fetchvc') { + $url = str_replace('/channel/', '/profile/', $orig_record[0]['xchan_url']) . '/vcard'; $recurse = 0; - $x = z_fetch_url(zid($url),false,$recurse,['session' => true]); - if($x['success']) { - $h = new HTTPHeaders($x['header']); + $x = z_fetch_url(zid($url), false, $recurse, ['session' => true]); + if ($x['success']) { + $h = new HTTPHeaders($x['header']); $fields = $h->fetch(); - if($fields) { - foreach($fields as $y) { - if(array_key_exists('content-type',$y)) { - $type = explode(';',trim($y['content-type'])); - if($type && $type[0] === 'text/vcard' && $x['body']) { - $vc = \Sabre\VObject\Reader::read($x['body']); + if ($fields) { + foreach ($fields as $y) { + if (array_key_exists('content-type', $y)) { + $type = explode(';', trim($y['content-type'])); + if ($type && $type[0] === 'text/vcard' && $x['body']) { + $vc = Reader::read($x['body']); $vcard = $vc->serialize(); - if($vcard) { - set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$vcard); - $this->connedit_clone($a); + if ($vcard) { + set_abconfig(local_channel(), $orig_record[0]['abook_xchan'], 'system', 'vcard', $vcard); + $this->connedit_clone(); } } } @@ -470,60 +355,55 @@ class Connedit extends Controller { } - if($cmd === 'resetphoto') { + if ($cmd === 'resetphoto') { q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'", dbesc($orig_record[0]['xchan_hash']) ); $cmd = 'refresh'; } - if($cmd === 'refresh') { - if($orig_record[0]['xchan_network'] === 'zot') { - if(! zot_refresh($orig_record[0],App::get_channel())) - notice( t('Refresh failed - channel is currently unavailable.') ); - } - elseif($orig_record[0]['xchan_network'] === 'zot6') { - if(! Libzot::refresh($orig_record[0],App::get_channel())) - notice( t('Refresh failed - channel is currently unavailable.') ); + if ($cmd === 'refresh') { + if ($orig_record[0]['xchan_network'] === 'zot6') { + if (!Libzot::refresh($orig_record[0], App::get_channel())) + notice(t('Refresh failed - channel is currently unavailable.')); } else { - // if you are on a different network we'll force a refresh of the connection basic info - Master::Summon(array('Notifier','permission_update',$contact_id)); + Master::Summon(['Notifier', 'permission_update', $contact_id]); } goaway(z_root() . '/connedit/' . $contact_id); } - if($cmd === 'block') { - if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_BLOCKED)) { - $this->connedit_clone($a); + if ($cmd === 'block') { + if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_BLOCKED)) { + $this->connedit_clone(); } else notice(t('Unable to set address book parameters.') . EOL); goaway(z_root() . '/connedit/' . $contact_id); } - if($cmd === 'ignore') { - if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_IGNORED)) { - $this->connedit_clone($a); + if ($cmd === 'ignore') { + if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_IGNORED)) { + $this->connedit_clone(); } else notice(t('Unable to set address book parameters.') . EOL); goaway(z_root() . '/connedit/' . $contact_id); } - if($cmd === 'archive') { - if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_ARCHIVED)) { - $this->connedit_clone($a); + if ($cmd === 'archive') { + if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_ARCHIVED)) { + $this->connedit_clone(); } else notice(t('Unable to set address book parameters.') . EOL); goaway(z_root() . '/connedit/' . $contact_id); } - if($cmd === 'hide') { - if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_HIDDEN)) { - $this->connedit_clone($a); + if ($cmd === 'hide') { + if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_HIDDEN)) { + $this->connedit_clone(); } else notice(t('Unable to set address book parameters.') . EOL); @@ -533,10 +413,10 @@ class Connedit extends Controller { // We'll prevent somebody from unapproving an already approved contact. // Though maybe somebody will want this eventually (??) - if($cmd === 'approve') { - if(intval($orig_record[0]['abook_pending'])) { - if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_PENDING)) { - $this->connedit_clone($a); + if ($cmd === 'approve') { + if (intval($orig_record[0]['abook_pending'])) { + if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_PENDING)) { + $this->connedit_clone(); } else notice(t('Unable to set address book parameters.') . EOL); @@ -545,132 +425,130 @@ class Connedit extends Controller { } - if($cmd === 'drop') { + if ($cmd === 'drop') { contact_remove(local_channel(), $orig_record[0]['abook_id']); - Master::Summon( [ 'Notifier', 'purge', local_channel(), $orig_record[0]['xchan_hash'] ] ); + Master::Summon(['Notifier', 'purge', local_channel(), $orig_record[0]['xchan_hash']]); Libsync::build_sync_packet(0 /* use the current local_channel */, - array('abook' => array(array( - 'abook_xchan' => $orig_record[0]['abook_xchan'], - 'entry_deleted' => true)) - ) + ['abook' => [[ + 'abook_xchan' => $orig_record[0]['abook_xchan'], + 'entry_deleted' => true]] + ] ); - info( t('Connection has been removed.') . EOL ); - if(x($_SESSION,'return_url')) + info(t('Connection has been removed.') . EOL); + if (x($_SESSION, 'return_url')) goaway(z_root() . '/' . $_SESSION['return_url']); goaway(z_root() . '/contacts'); } } - if(App::$poi) { + if (App::$poi) { $abook_prev = 0; $abook_next = 0; - $contact_id = App::$poi['abook_id']; - $contact = App::$poi; + $contact = App::$poi; $cn = q("SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 order by xchan_name", intval(local_channel()) ); - if($cn) { + if ($cn) { $pntotal = count($cn); - for($x = 0; $x < $pntotal; $x ++) { - if($cn[$x]['abook_id'] == $contact_id) { - if($x === 0) + for ($x = 0; $x < $pntotal; $x++) { + if ($cn[$x]['abook_id'] == $contact_id) { + if ($x === 0) $abook_prev = 0; else $abook_prev = $cn[$x - 1]['abook_id']; - if($x === $pntotal) + if ($x === $pntotal) $abook_next = 0; else - $abook_next = $cn[$x +1]['abook_id']; + $abook_next = $cn[$x + 1]['abook_id']; } } - } + } - $tools = array( + $tools = [ - 'view' => array( + 'view' => [ 'label' => t('View Profile'), 'url' => chanlink_cid($contact['abook_id']), 'sel' => '', - 'title' => sprintf( t('View %s\'s profile'), $contact['xchan_name']), - ), + 'title' => sprintf(t('View %s\'s profile'), $contact['xchan_name']), + ], - 'refresh' => array( + 'refresh' => [ 'label' => t('Refresh Permissions'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/refresh', 'sel' => '', 'title' => t('Fetch updated permissions'), - ), + ], - 'rephoto' => array( + 'rephoto' => [ 'label' => t('Refresh Photo'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/resetphoto', 'sel' => '', 'title' => t('Fetch updated photo'), - ), + ], - 'recent' => array( + 'recent' => [ 'label' => t('Recent Activity'), 'url' => z_root() . '/network/?f=&cid=' . $contact['abook_id'], 'sel' => '', 'title' => t('View recent posts and comments'), - ), + ], - 'block' => array( + 'block' => [ 'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block', 'sel' => (intval($contact['abook_blocked']) ? 'active' : ''), 'title' => t('Block (or Unblock) all communications with this connection'), - 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''), - ), + 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''), + ], - 'ignore' => array( + 'ignore' => [ 'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore', 'sel' => (intval($contact['abook_ignored']) ? 'active' : ''), 'title' => t('Ignore (or Unignore) all inbound communications from this connection'), - 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''), - ), + 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''), + ], - 'archive' => array( + 'archive' => [ 'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive', 'sel' => (intval($contact['abook_archived']) ? 'active' : ''), 'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'), - 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''), - ), + 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''), + ], - 'hide' => array( + 'hide' => [ 'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide', 'sel' => (intval($contact['abook_hidden']) ? 'active' : ''), 'title' => t('Hide or Unhide this connection from your other connections'), - 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''), - ), + 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''), + ], - 'delete' => array( + 'delete' => [ 'label' => t('Delete'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/drop', 'sel' => '', 'title' => t('Delete this connection'), - ), - - ); + ], + ]; - if(in_array($contact['xchan_network'], ['zot6', 'zot'])) { + if ($contact['xchan_network'] === 'zot6') { $tools['fetchvc'] = [ 'label' => t('Fetch Vcard'), - 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc', + 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc', 'sel' => '', 'title' => t('Fetch electronic calling card for this connection') ]; @@ -679,31 +557,16 @@ class Connedit extends Controller { $sections = []; - $sections['perms'] = [ - 'label' => t('Permissions'), - 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/?f=§ion=perms', - 'sel' => '', - 'title' => t('Open Individual Permissions section by default'), - ]; - - $self = false; - - if(intval($contact['abook_self'])) { - $self = true; - $abook_prev = $abook_next = 0; - } - - $vc = get_abconfig(local_channel(),$contact['abook_xchan'],'system','vcard'); + $vc = get_abconfig(local_channel(), $contact['abook_xchan'], 'system', 'vcard'); - $vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null); - $vcard = (($vctmp) ? get_vcard_array($vctmp,$contact['abook_id']) : [] ); - if(! $vcard) + $vctmp = (($vc) ? Reader::read($vc) : null); + $vcard = (($vctmp) ? get_vcard_array($vctmp, $contact['abook_id']) : []); + if (!$vcard['fn']) $vcard['fn'] = $contact['xchan_name']; - $tpl = get_markup_template("abook_edit.tpl"); - if(Apps::system_app_installed(local_channel(),'Affinity Tool')) { + if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) { $sections['affinity'] = [ 'label' => t('Affinity'), @@ -719,12 +582,12 @@ class Connedit extends Controller { t('Acquaintances'), t('All') ]; - call_hooks('affinity_labels',$labels); + call_hooks('affinity_labels', $labels); $label_str = ''; - if($labels) { - foreach($labels as $l) { - if($label_str) { + if ($labels) { + foreach ($labels as $l) { + if ($label_str) { $label_str .= ", '|'"; $label_str .= ", '" . $l . "'"; } @@ -737,14 +600,14 @@ class Connedit extends Controller { $slideval = intval($contact['abook_closeness']); - $slide = replace_macros($slider_tpl,array( - '$min' => 1, - '$val' => $slideval, + $slide = replace_macros($slider_tpl, [ + '$min' => 1, + '$val' => $slideval, '$labels' => $label_str, - )); + ]); } - if(feature_enabled(local_channel(),'connfilter')) { + if (feature_enabled(local_channel(), 'connfilter')) { $sections['filter'] = [ 'label' => t('Filter'), 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/?f=§ion=filter', @@ -753,195 +616,148 @@ class Connedit extends Controller { ]; } - $rating_val = 0; - $rating_text = ''; - - $xl = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1", - dbesc($channel['channel_hash']), - dbesc($contact['xchan_hash']) - ); - - if($xl) { - $rating_val = intval($xl[0]['xlink_rating']); - $rating_text = $xl[0]['xlink_rating_text']; - } - - $rating_enabled = get_config('system','rating_enabled'); - - if($rating_enabled) { - $rating = replace_macros(get_markup_template('rating_slider.tpl'),array( - '$min' => -10, - '$val' => $rating_val - )); - } - else { - $rating = false; - } - - - $perms = array(); - $channel = App::get_channel(); - + $perms = []; $global_perms = Permissions::Perms(); + $existing = get_all_perms(local_channel(), $contact['abook_xchan'], false); + $unapproved = ['pending', t('Approve this contact'), '', t('Accept contact to allow communication'), [t('No'), ('Yes')]]; + $multiprofs = ((feature_enabled(local_channel(), 'multi_profiles')) ? true : false); - $existing = get_all_perms(local_channel(),$contact['abook_xchan'],false); - - $unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes'))); - - $multiprofs = ((feature_enabled(local_channel(),'multi_profiles')) ? true : false); - - if($slide && !$multiprofs) + if ($slide && !$multiprofs) $affinity = t('Set Affinity'); - if(!$slide && $multiprofs) + if (!$slide && $multiprofs) $affinity = t('Set Profile'); - if($slide && $multiprofs) + if ($slide && $multiprofs) $affinity = t('Set Affinity & Profile'); $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", - intval(local_channel()), - dbesc($contact['abook_xchan']) + intval(local_channel()), + dbesc($contact['abook_xchan']) ); - $their_perms = array(); - if($theirs) { - foreach($theirs as $t) { + + $their_perms = []; + if ($theirs) { + foreach ($theirs as $t) { $their_perms[$t['k']] = $t['v']; } } - foreach($global_perms as $k => $v) { - $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k); -//fixme - - $checkinherited = PermissionLimits::Get(local_channel(),$k); - - // For auto permissions (when $self is true) we don't want to look at existing - // permissions because they are enabled for the channel owner - if((! $self) && ($existing[$k])) - $thisperm = "1"; - - + foreach ($global_perms as $k => $v) { + $thisperm = $existing[$k]; + $checkinherited = PermissionLimits::Get(local_channel(), $k); + $perms[] = ['perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '0' : '1'), '', $checkinherited]; + } + $pcat = new Permcat(local_channel()); + $pcatlist = $pcat->listing(); + $default_role = get_pconfig(local_channel(), 'system', 'default_permcat'); + $current_permcat = (($contact['abook_pending']) ? $default_role : $contact['abook_role']); - $perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited); + if (!$current_permcat) { + notice(t('Please select a role for this contact!') . EOL); + $permcats[] = ''; } - $pcat = new Permcat(local_channel()); - $pcatlist = $pcat->listing(); - $permcats = []; - if($pcatlist) { - foreach($pcatlist as $pc) { + if ($pcatlist) { + foreach ($pcatlist as $pc) { $permcats[$pc['name']] = $pc['localname']; } } $locstr = locations_by_netid($contact['xchan_hash']); - if(! $locstr) + if (!$locstr) { $locstr = unpunify($contact['xchan_url']); + } $clone_warn = ''; - $clonable = (in_array($contact['xchan_network'],['zot', 'zot6', 'rss']) ? true : false); - if(! $clonable) { + $clonable = in_array($contact['xchan_network'], ['zot6', 'rss']); + if (!$clonable) { $clone_warn = '<strong>'; $clone_warn .= ((intval($contact['abook_not_here'])) - ? t('This connection is unreachable from this location.') - : t('This connection may be unreachable from other channel locations.') + ? t('This contact is unreachable from this location.') + : t('This contact may be unreachable from other channel locations.') ); $clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.'); } - - - if(intval($contact['abook_not_here']) && $unclonable) - $not_here = t('This connection is unreachable from this location. Location independence is not supported by their network.'); - $o .= replace_macros($tpl, [ - '$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])), - '$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no), - '$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ], - '$permcat_new' => t('Add permission role'), - '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'), - '$addr' => unpunify($contact['xchan_addr']), - '$primeurl' => unpunify($contact['xchan_url']), - '$section' => $section, - '$sections' => $sections, - '$vcard' => $vcard, - '$addr_text' => t('This connection\'s primary address is'), - '$loc_text' => t('Available locations:'), - '$locstr' => $locstr, - '$unclonable' => $clone_warn, - '$notself' => (($self) ? '' : '1'), - '$self' => (($self) ? '1' : ''), - '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'), - '$tools_label' => t('Connection Tools'), - '$tools' => (($self) ? '' : $tools), - '$lbl_slider' => t('Slide to adjust your degree of friendship'), - '$lbl_rating' => t('Rating'), - '$lbl_rating_label' => t('Slide to adjust your rating'), - '$lbl_rating_txt' => t('Optionally explain your rating'), - '$connfilter' => feature_enabled(local_channel(),'connfilter'), + '$header' => sprintf(t('Contact: %s'), $contact['xchan_name']), + '$permcat' => ['permcat', t('Contact role'), $current_permcat, '', $permcats], + '$permcat_new' => t('Manage contact roles'), + '$permcat_value' => bin2hex($current_permcat), + '$addr' => unpunify($contact['xchan_addr']), + '$primeurl' => unpunify($contact['xchan_url']), + '$section' => $section, + '$sections' => $sections, + '$vcard' => $vcard, + '$addr_text' => t('This contacts\'s primary address is'), + '$loc_text' => t('Available locations:'), + '$locstr' => $locstr, + '$unclonable' => $clone_warn, + '$notself' => '1', + '$self' => '', + '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'), + '$tools_label' => t('Contact Tools'), + '$tools' => $tools, + '$lbl_slider' => t('Slide to adjust your degree of friendship'), + '$connfilter' => feature_enabled(local_channel(), 'connfilter'), '$connfilter_label' => t('Custom Filter'), - '$incl' => array('abook_incl',t('Only import posts with this text'), $contact['abook_incl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')), - '$excl' => array('abook_excl',t('Do not import posts with this text'), $contact['abook_excl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')), - '$rating_text' => array('rating_text', t('Optionally explain your rating'),$rating_text,''), - '$rating_info' => t('This information is public!'), - '$rating' => $rating, - '$rating_val' => $rating_val, - '$slide' => $slide, - '$affinity' => $affinity, - '$pending_label' => t('Connection Pending Approval'), - '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''), - '$unapproved' => $unapproved, - '$inherited' => t('inherited'), - '$submit' => t('Submit'), - '$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']), - '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80), - '$them' => t('Their Settings'), - '$me' => t('My Settings'), - '$perms' => $perms, - '$permlbl' => t('Individual Permissions'), - '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'), - '$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'), - '$lastupdtext' => t('Last update:'), - '$last_update' => relative_date($contact['abook_connected']), - '$profile_select' => contact_profile_assign($contact['abook_profile']), - '$multiprofs' => $multiprofs, - '$contact_id' => $contact['abook_id'], - '$name' => $contact['xchan_name'], - '$abook_prev' => $abook_prev, - '$abook_next' => $abook_next, - '$vcard_label' => t('Details'), - '$displayname' => $displayname, - '$name_label' => t('Name'), - '$org_label' => t('Organisation'), - '$title_label' => t('Title'), - '$tel_label' => t('Phone'), - '$email_label' => t('Email'), - '$impp_label' => t('Instant messenger'), - '$url_label' => t('Website'), - '$adr_label' => t('Address'), - '$note_label' => t('Note'), - '$mobile' => t('Mobile'), - '$home' => t('Home'), - '$work' => t('Work'), - '$other' => t('Other'), - '$add_card' => t('Add Contact'), - '$add_field' => t('Add Field'), - '$create' => t('Create'), - '$update' => t('Update'), - '$delete' => t('Delete'), - '$cancel' => t('Cancel'), - '$po_box' => t('P.O. Box'), - '$extra' => t('Additional'), - '$street' => t('Street'), - '$locality' => t('Locality'), - '$region' => t('Region'), - '$zip_code' => t('ZIP Code'), - '$country' => t('Country') + '$incl' => ['abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')], + '$excl' => ['abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')], + '$slide' => $slide, + '$affinity' => $affinity, + '$pending_label' => t('Contact Pending Approval'), + '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''), + '$unapproved' => $unapproved, + '$inherited' => t('inherited'), + '$submit' => ((intval($contact['abook_pending'])) ? t('Approve contact') : t('Submit')), + '$lbl_vis2' => sprintf(t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']), + '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80), + '$them' => t('Their'), + '$me' => t('My'), + '$perms' => $perms, + '$permlbl' => t('Individual Permissions'), + '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'), + '$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'), + '$lastupdtext' => t('Last update:'), + '$last_update' => relative_date($contact['abook_connected']), + '$profile_select' => contact_profile_assign($contact['abook_profile']), + '$multiprofs' => $multiprofs, + '$contact_id' => $contact['abook_id'], + '$name' => $contact['xchan_name'], + '$abook_prev' => $abook_prev, + '$abook_next' => $abook_next, + '$vcard_label' => t('Details'), + '$name_label' => t('Name'), + '$org_label' => t('Organisation'), + '$title_label' => t('Title'), + '$tel_label' => t('Phone'), + '$email_label' => t('Email'), + '$impp_label' => t('Instant messenger'), + '$url_label' => t('Website'), + '$adr_label' => t('Address'), + '$note_label' => t('Note'), + '$mobile' => t('Mobile'), + '$home' => t('Home'), + '$work' => t('Work'), + '$other' => t('Other'), + '$add_card' => t('Add Contact'), + '$add_field' => t('Add Field'), + '$create' => t('Create'), + '$update' => t('Update'), + '$delete' => t('Delete'), + '$cancel' => t('Cancel'), + '$po_box' => t('P.O. Box'), + '$extra' => t('Additional'), + '$street' => t('Street'), + '$locality' => t('Locality'), + '$region' => t('Region'), + '$zip_code' => t('ZIP Code'), + '$country' => t('Country') ]); - $arr = array('contact' => $contact,'output' => $o); + $arr = ['contact' => $contact, 'output' => $o]; call_hooks('contact_edit', $arr); diff --git a/Zotlabs/Module/Contactedit.php b/Zotlabs/Module/Contactedit.php new file mode 100644 index 000000000..d306039d2 --- /dev/null +++ b/Zotlabs/Module/Contactedit.php @@ -0,0 +1,675 @@ +<?php + +namespace Zotlabs\Module; + +/* @file Cobtactedit.php + * @brief In this file the connection-editor form is generated and evaluated. + * + * + */ + +use App; +use Sabre\VObject\Reader; +use Zotlabs\Lib\Apps; +use Zotlabs\Lib\Libzot; +use Zotlabs\Lib\Libsync; +use Zotlabs\Daemon\Master; +use Zotlabs\Web\Controller; +use Zotlabs\Access\Permissions; +use Zotlabs\Access\PermissionLimits; +use Zotlabs\Web\HTTPHeaders; +use Zotlabs\Lib\Permcat; +use Zotlabs\Lib\AccessList; + +require_once('include/socgraph.php'); +require_once('include/selectors.php'); +require_once('include/group.php'); +require_once('include/photos.php'); + +class Contactedit extends Controller { + + /* @brief Initialize the connection-editor + * + * + */ + + function init() { + + if (!local_channel()) + return; + + if ((argc() >= 2) && intval(argv(1))) { + $r = q("SELECT abook.*, xchan.* FROM abook LEFT JOIN xchan ON abook_xchan = xchan_hash + WHERE abook_channel = %d AND abook_id = %d AND abook_self = 0 AND xchan_deleted = 0", + intval(local_channel()), + intval(argv(1)) + ); + if (!$r) { + json_return_and_die([ + 'success' => false, + 'message' => t('Invalid abook_id') + ]); + } + + App::$poi = $r[0]; + + } + } + + + /* @brief Evaluate posted values and set changes + * + */ + + function post() { + + if (!local_channel()) + return; + + $contact_id = intval(argv(1)); + if (!$contact_id) + return; + + $channel = App::get_channel(); + + $contact = App::$poi; + + if (!$contact) { + notice(t('Could not access contact record.') . EOL); + killme(); + } + + call_hooks('contact_edit_post', $_REQUEST); + + if (Apps::system_app_installed(local_channel(), 'Privacy Groups')) { + $pgrp_ids = q("SELECT id FROM pgrp WHERE deleted = 0 AND uid = %d", + intval(local_channel()) + ); + + foreach($pgrp_ids as $pgrp) { + if (array_key_exists('pgrp_id_' . $pgrp['id'], $_REQUEST)) { + AccessList::member_add(local_channel(), '', $contact['abook_xchan'], $pgrp['id']); + } + else { + AccessList::member_remove(local_channel(), '', $contact['abook_xchan'], $pgrp['id']); + } + } + } + + $profile_id = ((array_key_exists('profile_assign', $_REQUEST)) ? $_REQUEST['profile_assign'] : $contact['abook_profile']); + + if ($profile_id) { + $r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1", + dbesc($profile_id), + intval(local_channel()) + ); + if (!count($r)) { + notice(t('Could not locate selected profile.') . EOL); + return; + } + } + + $abook_incl = ((array_key_exists('abook_incl', $_REQUEST)) ? escape_tags($_REQUEST['abook_incl']) : $contact['abook_incl']); + $abook_excl = ((array_key_exists('abook_excl', $_REQUEST)) ? escape_tags($_REQUEST['abook_excl']) : $contact['abook_excl']); + $abook_role = ((array_key_exists('permcat', $_REQUEST)) ? escape_tags($_REQUEST['permcat']) : $contact['abook_role']); + + if (!array_key_exists('closeness', $_REQUEST)) { + $_REQUEST['closeness'] = 80; + } + + $closeness = intval($_REQUEST['closeness']); + + if ($closeness < 0 || $closeness > 99) { + $closeness = 80; + } + + $new_friend = ((intval($contact['abook_pending'])) ? true : false); + + \Zotlabs\Lib\Permcat::assign($channel, $abook_role, [$contact['abook_xchan']]); + + $abook_pending = (($new_friend) ? 0 : $contact['abook_pending']); + + $r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d, + abook_incl = '%s', abook_excl = '%s' + where abook_id = %d AND abook_channel = %d", + dbesc($profile_id), + intval($closeness), + intval($abook_pending), + dbesc($abook_incl), + dbesc($abook_excl), + intval($contact_id), + intval(local_channel()) + ); + + $_REQUEST['success'] = false; + + if ($r) { + $_REQUEST['success'] = true; + } + + + if (!intval($contact['abook_self'])) { + if ($new_friend) { + Master::Summon(['Notifier', 'permission_accept', $contact_id]); + } + + Master::Summon([ + 'Notifier', + (($new_friend) ? 'permission_create' : 'permission_update'), + $contact_id + ]); + } + + if ($new_friend) { + $default_group = $channel['channel_default_group']; + if ($default_group) { + $g = AccessList::by_hash(local_channel(), $default_group); + if ($g) { + AccessList::member_add(local_channel(), '', $contact['abook_xchan'], $g['id']); + } + } + + // Check if settings permit ("post new friend activity" is allowed, and + // friends in general or this friend in particular aren't hidden) + // and send out a new friend activity + + $pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0", + intval($channel['channel_id']) + ); + if (($pr) && (!intval($contact['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) { + $xarr = []; + + $xarr['item_wall'] = 1; + $xarr['item_origin'] = 1; + $xarr['item_thread_top'] = 1; + $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash']; + $xarr['allow_cid'] = $channel['channel_allow_cid']; + $xarr['allow_gid'] = $channel['channel_allow_gid']; + $xarr['deny_cid'] = $channel['channel_deny_cid']; + $xarr['deny_gid'] = $channel['channel_deny_gid']; + $xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0); + + $xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . $contact['xchan_url'] . ']' . $contact['xchan_name'] . '[/zrl]'; + + $xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=80x80]' . $contact['xchan_photo_m'] . '[/zmg][/zrl]'; + + post_activity_item($xarr); + + } + + // pull in a bit of content if there is any to pull in + Master::Summon(['Onepoll', $contact_id]); + + } + + // Refresh the structure in memory with the new data + $this->init(); + + if ($new_friend) { + $arr = ['channel_id' => local_channel(), 'abook' => App::$poi]; + call_hooks('accept_follow', $arr); + } + + $this->contactedit_clone(); + $this->get(); + + killme(); + + return; + + } + + + /* @brief Generate content of contact edit page + * + * + */ + + function get() { + + if (!local_channel()) { + killme(); + } + + if (!App::$poi) { + killme(); + } + + + $channel = App::get_channel(); + $contact_id = App::$poi['abook_id']; + $contact = App::$poi; + $section = ((array_key_exists('section', $_REQUEST)) ? $_REQUEST['section'] : 'roles'); + $sub_section = ((array_key_exists('sub_section', $_REQUEST)) ? $_REQUEST['sub_section'] : ''); + + + if (argc() == 3) { + $cmd = argv(2); + $ret = $this->do_action($contact, $cmd); + $contact = App::$poi; + + $tools_html = replace_macros(get_markup_template("contact_edit_tools.tpl"), [ + '$tools_label' => t('Contact Tools'), + '$tools' => $this->get_tools($contact), + ]); + + $ret['tools'] = $tools_html; + + json_return_and_die($ret); + } + + $groups = []; + + if (Apps::system_app_installed(local_channel(), 'Privacy Groups')) { + + $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", + intval(local_channel()) + ); + + $member_of = AccessList::containing(local_channel(), $contact['xchan_hash']); + + if ($r) { + foreach ($r as $rr) { + $default_group = false; + if ($rr['hash'] === $channel['channel_default_group']) { + $default_group = true; + } + + $groups[] = [ + 'pgrp_id_' . $rr['id'], + $rr['gname'], + // if it's a new contact preset the default group if we have one + (($default_group && $contact['abook_pending']) ? 1 : in_array($rr['id'], $member_of)), + '', + [t('No'), t('Yes')] + ]; + } + } + } + + $slide = ''; + + if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) { + + $labels = [ + 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'); + + $slideval = intval($contact['abook_closeness']); + + $slide = replace_macros($slider_tpl, [ + '$min' => 1, + '$val' => $slideval, + '$labels' => $label_str, + ]); + } + + $perms = []; + $global_perms = Permissions::Perms(); + $existing = get_all_perms(local_channel(), $contact['abook_xchan'], false); + $unapproved = ['pending', t('Approve this contact'), '', t('Accept contact to allow communication'), [t('No'), ('Yes')]]; + $multiprofs = ((feature_enabled(local_channel(), 'multi_profiles')) ? true : false); + + $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", + intval(local_channel()), + dbesc($contact['abook_xchan']) + ); + + $their_perms = []; + if ($theirs) { + foreach ($theirs as $t) { + $their_perms[$t['k']] = $t['v']; + } + } + + foreach ($global_perms as $k => $v) { + $thisperm = $existing[$k]; + $checkinherited = PermissionLimits::Get(local_channel(), $k); + $perms[] = ['perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '0' : '1'), '', $checkinherited]; + } + + $pcat = new Permcat(local_channel()); + $pcatlist = $pcat->listing(); + $default_role = get_pconfig(local_channel(), 'system', 'default_permcat'); + $current_permcat = (($contact['abook_pending']) ? $default_role : $contact['abook_role']); + + $roles_dict = []; + foreach ($pcatlist as $role) { + $roles_dict[$role['name']] = $role['localname']; + } + + + if (!$current_permcat) { + notice(t('Please select a role for this contact!') . EOL); + $permcats[] = ''; + } + + if ($pcatlist) { + foreach ($pcatlist as $pc) { + $permcats[$pc['name']] = $pc['localname']; + } + } + + $locstr = locations_by_netid($contact['xchan_hash']); + if (!$locstr) { + $locstr = unpunify($contact['xchan_url']); + } + + $clone_warn = ''; + $clonable = in_array($contact['xchan_network'], ['zot6', 'rss']); + if (!$clonable) { + $clone_warn = '<strong>'; + $clone_warn .= ((intval($contact['abook_not_here'])) + ? t('This contact is unreachable from this location.') + : t('This contact may be unreachable from other channel locations.') + ); + $clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.'); + } + + $header_card = '<img src="' . $contact['xchan_photo_s'] . '" class="rounded" style="width: 3rem; height: 3rem;"> ' . $contact['xchan_name']; + + $header_html = replace_macros(get_markup_template("contact_edit_header.tpl"), [ + '$img_src' => $contact['xchan_photo_s'], + '$name' => $contact['xchan_name'], + '$addr' => (($contact['xchan_addr']) ? $contact['xchan_addr'] : $contact['xchan_url']), + '$href' => ((is_matrix_url($contact['xchan_url'])) ? zid($contact['xchan_url']) : $contact['xchan_url']), + '$link_label' => t('View profile'), + '$is_group' => $contact['xchan_pubforum'], + '$group_label' => t('This is a group/forum channel') + ]); + + $tools_html = replace_macros(get_markup_template("contact_edit_tools.tpl"), [ + '$tools_label' => t('Contact Tools'), + '$tools' => $this->get_tools($contact), + ]); + + $tpl = get_markup_template("contact_edit.tpl"); + + $o = replace_macros($tpl, [ + '$permcat' => ['permcat', t('Select a role for this contact'), $current_permcat, '', $permcats], + '$permcat_new' => t('Contact roles'), + '$permcat_value' => bin2hex($current_permcat), +// '$addr' => unpunify($contact['xchan_addr']), +// '$primeurl' => unpunify($contact['xchan_url']), + '$section' => $section, + '$sub_section' => $sub_section, + '$groups' => $groups, +// '$addr_text' => t('This contacts\'s primary address is'), +// '$loc_text' => t('Available locations:'), +// '$locstr' => $locstr, +// '$unclonable' => $clone_warn, + '$lbl_slider' => t('Slide to adjust your degree of friendship'), + '$connfilter' => feature_enabled(local_channel(), 'connfilter'), + '$connfilter_label' => t('Custom Filter'), + '$incl' => ['abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')], + '$excl' => ['abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')], + '$slide' => $slide, +// '$pending_label' => t('Contact Pending Approval'), +// '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''), +// '$unapproved' => $unapproved, + '$submit' => ((intval($contact['abook_pending'])) ? t('Approve contact') : t('Submit')), + '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80), + '$them' => t('Their'), + '$me' => t('My'), + '$perms' => $perms, +// '$lastupdtext' => t('Last update:'), +// '$last_update' => relative_date($contact['abook_connected']), + '$profile_select' => contact_profile_assign($contact['abook_profile']), + '$multiprofs' => $multiprofs, + '$contact_id' => $contact['abook_id'], +// '$name' => $contact['xchan_name'], + '$roles_label' => t('Roles'), + '$compare_label' => t('Compare permissions'), + '$permission_label' => t('Permission'), + '$pgroups_label' => t('Privacy groups'), + '$profiles_label' => t('Profiles'), + '$affinity_label' => t('Affinity'), + '$filter_label' => t('Content filter') + ]); + + $arr = ['contact' => $contact, 'output' => $o]; + + call_hooks('contact_edit', $arr); + + if (is_ajax()) { + json_return_and_die([ + 'success' => ((intval($_REQUEST['success'])) ? intval($_REQUEST['success']) : 1), + 'message' => (($_REQUEST['success']) ? t('Contact updated') : t('Contact update failed')), + 'id' => $contact_id, + 'title' => $header_html, + 'role' => ((intval($contact['abook_pending'])) ? '' : $roles_dict[$current_permcat]), + 'body' => $arr['output'], + 'tools' => $tools_html, + 'submit' => ((intval($contact['abook_pending'])) ? t('Approve connection') : t('Submit')), + 'pending' => intval($contact['abook_pending']) + ]); + } + + return $arr['output']; + + } + + function contactedit_clone() { + + if (!App::$poi) + return; + + $channel = App::get_channel(); + + $clone = App::$poi; + + unset($clone['abook_id']); + unset($clone['abook_account']); + unset($clone['abook_channel']); + + $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']); + if ($abconfig) + $clone['abconfig'] = $abconfig; + + Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]); + } + + function do_action($contact, $cmd) { + $ret = [ + 'sucess' => false, + 'message' => '' + ]; + + if ($cmd === 'resetphoto') { + q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'", + dbesc($contact['xchan_hash']) + ); + $cmd = 'refresh'; + } + + if ($cmd === 'refresh') { + if ($contact['xchan_network'] === 'zot6') { + if (Libzot::refresh($contact, App::get_channel())) { + $ret['success'] = true; + $ret['message'] = t('Refresh succeeded'); + } + else { + $ret['message'] = t('Refresh failed - channel is currently unavailable'); + } + } + else { + // if you are on a different network we'll force a refresh of the connection basic info + Master::Summon(['Notifier', 'permission_update', $contact['abook_id']]); + $ret['success'] = true; + $ret['message'] = t('Refresh succeeded'); + } + + return $ret; + } + + if ($cmd === 'block') { + if (abook_toggle_flag($contact, ABOOK_FLAG_BLOCKED)) { + $this->init(); // refresh data + + $this->contactedit_clone(); + $ret['success'] = true; + $ret['message'] = t('Block status updated'); + } + else { + $ret['success'] = false; + $ret['message'] = t('Block failed'); + } + return $ret; + } + + if ($cmd === 'ignore') { + if (abook_toggle_flag($contact, ABOOK_FLAG_IGNORED)) { + $this->init(); // refresh data + + $this->contactedit_clone(); + $ret['success'] = true; + $ret['message'] = t('Ignore status updated'); + } + else { + $ret['success'] = false; + $ret['message'] = t('Ignore failed'); + } + return $ret; + } + + if ($cmd === 'archive') { + if (abook_toggle_flag($contact, ABOOK_FLAG_ARCHIVED)) { + $this->init(); // refresh data + + $this->contactedit_clone(); + $ret['success'] = true; + $ret['message'] = t('Archive status updated'); + } + else { + $ret['success'] = false; + $ret['message'] = t('Archive failed'); + } + return $ret; + } + + if ($cmd === 'hide') { + if (abook_toggle_flag($contact, ABOOK_FLAG_HIDDEN)) { + $this->init(); // refresh data + + $this->contactedit_clone(); + $ret['success'] = true; + $ret['message'] = t('Hide status updated'); + } + else { + $ret['success'] = false; + $ret['message'] = t('Hide failed'); + } + return $ret; + } + + // We'll prevent somebody from unapproving an already approved contact. + // Though maybe somebody will want this eventually (??) + + //if ($cmd === 'approve') { + //if (intval($contact['abook_pending'])) { + //if (abook_toggle_flag($contact, ABOOK_FLAG_PENDING)) { + //$this->contactedit_clone(); + //} + //else + //notice(t('Unable to set address book parameters.') . EOL); + //} + //goaway(z_root() . '/connedit/' . $contact_id); + //} + + + if ($cmd === 'drop') { + + if (contact_remove(local_channel(), $contact['abook_id'])) { + + Master::Summon(['Notifier', 'purge', local_channel(), $contact['xchan_hash']]); + Libsync::build_sync_packet(0 /* use the current local_channel */, + ['abook' => [ + [ + 'abook_xchan' => $contact['abook_xchan'], + 'entry_deleted' => true + ] + ] + ]); + + $ret['success'] = true; + $ret['message'] = t('Contact removed'); + } + else { + $ret['success'] = false; + $ret['message'] = t('Delete failed'); + } + return $ret; + } + } + + function get_tools($contact) { + return [ + + 'refresh' => [ + 'label' => t('Refresh Permissions'), + 'title' => t('Fetch updated permissions'), + ], + + 'rephoto' => [ + 'label' => t('Refresh Photo'), + 'title' => t('Fetch updated photo'), + ], + + + 'block' => [ + 'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')), + 'sel' => (intval($contact['abook_blocked']) ? 'active' : ''), + 'title' => t('Block (or Unblock) all communications with this connection'), + 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''), + ], + + 'ignore' => [ + 'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')), + 'sel' => (intval($contact['abook_ignored']) ? 'active' : ''), + 'title' => t('Ignore (or Unignore) all inbound communications from this connection'), + 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''), + ], + + 'archive' => [ + 'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')), + 'sel' => (intval($contact['abook_archived']) ? 'active' : ''), + 'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'), + 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''), + ], + + 'hide' => [ + 'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')), + 'sel' => (intval($contact['abook_hidden']) ? 'active' : ''), + 'title' => t('Hide or Unhide this connection from your other connections'), + 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''), + ], + + 'delete' => [ + 'label' => t('Delete'), + 'sel' => '', + 'title' => t('Delete this connection'), + ], + + ]; + } + +} diff --git a/Zotlabs/Module/Contactgroup.php b/Zotlabs/Module/Contactgroup.php index 36aaf7da0..3e88179fb 100644 --- a/Zotlabs/Module/Contactgroup.php +++ b/Zotlabs/Module/Contactgroup.php @@ -1,17 +1,17 @@ <?php namespace Zotlabs\Module; -require_once('include/group.php'); +use Zotlabs\Lib\AccessList; +use Zotlabs\Web\Controller; - -class Contactgroup extends \Zotlabs\Web\Controller { +class Contactgroup extends Controller { function get() { - + if(! local_channel()) { killme(); } - + if((argc() > 2) && (intval(argv(1))) && (argv(2))) { $r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", dbesc(base64url_decode(argv(2))), @@ -20,9 +20,9 @@ class Contactgroup extends \Zotlabs\Web\Controller { if($r) $change = $r[0]['abook_xchan']; } - + if((argc() > 1) && (intval(argv(1)))) { - + $r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1", intval(argv(1)), intval(local_channel()) @@ -30,25 +30,25 @@ class Contactgroup extends \Zotlabs\Web\Controller { if(! $r) { killme(); } - + $group = $r[0]; - $members = group_get_members($group['id']); + $members = AccessList::members(local_channel(), $group['id']); $preselected = array(); if(count($members)) { foreach($members as $member) $preselected[] = $member['xchan_hash']; } - + if($change) { if(in_array($change,$preselected)) { - group_rmv_member(local_channel(),$group['gname'],$change); + AccessList::member_remove(local_channel(),$group['gname'],$change); } else { - group_add_member(local_channel(),$group['gname'],$change); + AccessList::member_add(local_channel(),$group['gname'],$change); } } } - + killme(); } } diff --git a/Zotlabs/Module/Defperms.php b/Zotlabs/Module/Defperms.php index f2f7c10e5..70270d36b 100644 --- a/Zotlabs/Module/Defperms.php +++ b/Zotlabs/Module/Defperms.php @@ -8,7 +8,6 @@ use Zotlabs\Lib\Libsync; require_once('include/socgraph.php'); require_once('include/selectors.php'); -require_once('include/group.php'); require_once('include/photos.php'); class Defperms extends Controller { @@ -19,13 +18,13 @@ class Defperms extends Controller { */ function init() { - + if(! local_channel()) return; - if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) - return; - + //if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) + // return; + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_self = 1 and abook_channel = %d LIMIT 1", @@ -37,39 +36,39 @@ class Defperms extends Controller { $channel = App::get_channel(); if($channel) - head_set_icon($channel['xchan_photo_s']); + head_set_icon($channel['xchan_photo_s']); } - + /* @brief Evaluate posted values and set changes * */ - + function post() { - + if(! local_channel()) return; - if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) - return; - + //if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) + // return; + $contact_id = intval(argv(1)); if(! $contact_id) return; - + $channel = App::get_channel(); - + $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1", intval($contact_id), intval(local_channel()) ); - + if(! $orig_record) { notice( t('Could not access contact record.') . EOL); goaway(z_root() . '/connections'); return; // NOTREACHED } - + if(intval($orig_record[0]['abook_self'])) { $autoperms = intval($_POST['autoperms']); @@ -79,8 +78,8 @@ class Defperms extends Controller { $autoperms = null; $is_self = false; } - - + + $all_perms = \Zotlabs\Access\Permissions::Perms(); if($all_perms) { @@ -105,15 +104,15 @@ class Defperms extends Controller { } } - if(! is_null($autoperms)) + if(! is_null($autoperms)) set_pconfig($channel['channel_id'],'system','autoperms',$autoperms); - - + + notice( t('Settings updated.') . EOL); - + // Refresh the structure in memory with the new data - + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d and abook_id = %d LIMIT 1", @@ -123,28 +122,28 @@ class Defperms extends Controller { if($r) { App::$poi = $r[0]; } - - + + $this->defperms_clone($a); - + goaway(z_root() . '/defperms'); - + return; - + } - + /* @brief Clone connection * * */ - + function defperms_clone(&$a) { - + if(! App::$poi) return; - + $channel = App::get_channel(); - + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d and abook_id = %d LIMIT 1", @@ -154,49 +153,47 @@ class Defperms extends Controller { if($r) { App::$poi = array_shift($r); } - + $clone = App::$poi; - + unset($clone['abook_id']); unset($clone['abook_account']); unset($clone['abook_channel']); - + $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); if($abconfig) $clone['abconfig'] = $abconfig; - + Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone))); } - + /* @brief Generate content of connection default permissions page * * */ - + function get() { - + $sort_type = 0; $o = ''; - + if(! local_channel()) { notice( t('Permission denied.') . EOL); return login(); } - if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) { - //Do not display any associated widgets at this point - App::$pdl = ''; + //~ if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) { + //~ //Do not display any associated widgets at this point + //~ App::$pdl = ''; + //~ $papp = Apps::get_papp('Default Permissions'); + //~ return Apps::app_render($papp, 'module'); + //~ } - $o = '<b>' . t('Default Permissions App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Set custom default permissions for new connections'); - return $o; - } - $section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : ''); $channel = App::get_channel(); - + $yes_no = array(t('No'),t('Yes')); - + $connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel()); $o .= "<script>function connectDefaultShare() { @@ -210,28 +207,28 @@ class Defperms extends Controller { } } $o .= " }\n</script>\n"; - + if(App::$poi) { - + $sections = []; $self = false; - + $tpl = get_markup_template('defperms.tpl'); - - + + $perms = array(); $channel = App::get_channel(); $contact = App::$poi; - + $global_perms = \Zotlabs\Access\Permissions::Perms(); $hidden_perms = []; - + foreach($global_perms as $k => $v) { $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k); - + $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k); $inherited = (($checkinherited & PERMS_SPECIFIC) ? false : true); @@ -241,7 +238,7 @@ class Defperms extends Controller { $hidden_perms[] = [ 'perms_' . $k, intval($thisperm) ]; } } - + $pcat = new \Zotlabs\Lib\Permcat(local_channel()); $pcatlist = $pcat->listing(); $permcats = []; @@ -272,13 +269,13 @@ class Defperms extends Controller { '$contact_id' => $contact['abook_id'], '$name' => $contact['xchan_name'], ]); - + $arr = array('contact' => $contact,'output' => $o); - + call_hooks('contact_edit', $arr); - + return $arr['output']; - - } + + } } } diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php index e1555fc2d..da37c582f 100644 --- a/Zotlabs/Module/Directory.php +++ b/Zotlabs/Module/Directory.php @@ -8,7 +8,6 @@ use Zotlabs\Lib\Libzotdir; require_once('include/socgraph.php'); -require_once('include/dir_fns.php'); require_once('include/bbcode.php'); require_once('include/html2plain.php'); @@ -255,21 +254,21 @@ class Directory extends Controller { $connect_link = ''; $location = ''; - if(strlen($rr['locale'])) + if(isset($rr['locale'])) $location .= $rr['locale']; - if(strlen($rr['region'])) { - if(strlen($rr['locale'])) + if(isset($rr['region'])) { + if($location) $location .= ', '; $location .= $rr['region']; } - if(strlen($rr['country'])) { - if(strlen($location)) + if(isset($rr['country'])) { + if($location) $location .= ', '; $location .= $rr['country']; } $age = ''; - if(strlen($rr['birthday'])) { + if(isset($rr['birthday'])) { if(($years = age($rr['birthday'],'UTC','')) > 0) $age = $years; } diff --git a/Zotlabs/Module/Dirsearch.php b/Zotlabs/Module/Dirsearch.php index 804d7af5c..78205a9fc 100644 --- a/Zotlabs/Module/Dirsearch.php +++ b/Zotlabs/Module/Dirsearch.php @@ -4,26 +4,22 @@ namespace Zotlabs\Module; use App; use Zotlabs\Web\Controller; -require_once('include/dir_fns.php'); - - - class Dirsearch extends Controller { function init() { App::set_pager_itemspage(30); - + } - + function get() { - + $ret = array('success' => false); - + // logger('request: ' . print_r($_REQUEST,true)); - - + + $dirmode = intval(get_config('system','directory_mode')); - + if($dirmode == DIRECTORY_MODE_NORMAL) { $ret['message'] = t('This site is not a directory server'); json_return_and_die($ret); @@ -31,24 +27,24 @@ class Dirsearch extends Controller { $access_token = $_REQUEST['t']; - + $token = get_config('system','realm_token'); if($token && $access_token != $token) { $ret['message'] = t('This directory server requires an access token'); json_return_and_die($ret); } - - + + if(argc() > 1 && argv(1) === 'sites') { $ret = $this->list_public_sites(); json_return_and_die($ret); } - + $sql_extra = ''; - - + + $tables = array('name','address','locale','region','postcode','country','gender','marital','sexual','keywords'); - + if($_REQUEST['query']) { $advanced = $this->dir_parse_query($_REQUEST['query']); if($advanced) { @@ -64,9 +60,9 @@ class Dirsearch extends Controller { } } } - + $hash = ((x($_REQUEST['hash'])) ? $_REQUEST['hash'] : ''); - + $name = ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''); $hub = ((x($_REQUEST,'hub')) ? $_REQUEST['hub'] : ''); $address = ((x($_REQUEST,'address')) ? $_REQUEST['address'] : ''); @@ -82,16 +78,16 @@ class Dirsearch extends Controller { $agele = ((x($_REQUEST,'agele')) ? intval($_REQUEST['agele']) : 0 ); $kw = ((x($_REQUEST,'kw')) ? intval($_REQUEST['kw']) : 0 ); $forums = ((array_key_exists('pubforums',$_REQUEST)) ? intval($_REQUEST['pubforums']) : 0); - + if(get_config('system','disable_directory_keywords')) $kw = 0; - - + + // by default use a safe search $safe = ((x($_REQUEST,'safe'))); // ? intval($_REQUEST['safe']) : 1 ); if ($safe === false) $safe = 1; - + if(array_key_exists('sync',$_REQUEST)) { if($_REQUEST['sync']) $sync = datetime_convert('UTC','UTC',$_REQUEST['sync']); @@ -100,7 +96,7 @@ class Dirsearch extends Controller { } else $sync = false; - + if(($dirmode == DIRECTORY_MODE_STANDALONE) && (! $hub)) { $hub = \App::get_hostname(); } @@ -109,13 +105,13 @@ class Dirsearch extends Controller { $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 '; if($_REQUEST['and']) $joiner = ' AND '; - + if($name) $sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name); if($address) @@ -136,58 +132,58 @@ class Dirsearch extends Controller { $sql_extra .= $this->dir_query_build($joiner,'xprof_sexual',$sexual); if($keywords) $sql_extra .= $this->dir_query_build($joiner,'xprof_keywords',$keywords); - - - // we only support an age range currently. You must set both agege - // (greater than or equal) and agele (less than or equal) - + + + // we only support an age range currently. You must set both agege + // (greater than or equal) and agele (less than or equal) + if($agele && $agege) { $sql_extra .= " $joiner ( xprof_age <= " . intval($agele) . " "; $sql_extra .= " AND xprof_age >= " . intval($agege) . ") "; } - - + + if($hash) { $sql_extra = " AND xchan_hash like '" . dbesc($hash) . protect_sprintf('%') . "' "; } - - + + $perpage = (($_REQUEST['n']) ? $_REQUEST['n'] : 60); $page = (($_REQUEST['p']) ? intval($_REQUEST['p'] - 1) : 0); $startrec = (($page+1) * $perpage) - $perpage; $limit = (($_REQUEST['limit']) ? intval($_REQUEST['limit']) : 0); $return_total = ((x($_REQUEST,'return_total')) ? intval($_REQUEST['return_total']) : 0); - + // mtime is not currently working - + $mtime = ((x($_REQUEST,'mtime')) ? datetime_convert('UTC','UTC',$_REQUEST['mtime']) : ''); - - // ok a separate tag table won't work. + + // ok a separate tag table won't work. // merge them into xprof - + $ret['success'] = true; - + // If &limit=n, return at most n entries // If &return_total=1, we count matching entries and return that as 'total_items' for use in pagination. // By default we return one page (default 80 items maximum) and do not count total entries - + $logic = ((strlen($sql_extra)) ? 'false' : 'true'); - + if($hash) $logic = 'true'; - + if($dirmode == DIRECTORY_MODE_STANDALONE) { $sql_extra .= " and xchan_addr like '%%" . \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 ) "; - + if($forums) $safesql .= " and xchan_pubforum = " . ((intval($forums)) ? '1 ' : '0 '); - - if($limit) + + if($limit) $qlimit = " LIMIT $limit "; else { $qlimit = " LIMIT " . intval($perpage) . " OFFSET " . intval($startrec); @@ -198,27 +194,27 @@ class Dirsearch extends Controller { } } } - + if($sort_order == 'normal') { $order = " order by xchan_name asc "; - - // Start the alphabetic search at 'A' + + // 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') $order = " order by xchan_name_date asc "; - else + else $order = " order by xchan_name_date desc "; - - + + if($sync) { $spkt = array('transactions' => array()); - $r = q("select * from updates where ud_date >= '%s' and ud_guid != '' order by ud_date desc", + $r = q("select * from updates where ud_date >= '%s' and ud_guid != '' and ud_addr != '' order by ud_date desc", dbesc($sync) ); if($r) { @@ -228,7 +224,7 @@ class Dirsearch extends Controller { $flags[] = 'deleted'; if($rr['ud_flags'] & UPDATE_FLAGS_FORCED) $flags[] = 'forced'; - + $spkt['transactions'][] = array( 'hash' => $rr['ud_hash'], 'address' => $rr['ud_addr'], @@ -238,87 +234,48 @@ class Dirsearch extends Controller { ); } } - $r = q("select * from xlink where xlink_static = 1 and xlink_updated >= '%s' ", - dbesc($sync) - ); - if($r) { - $spkt['ratings'] = array(); - foreach($r as $rr) { - $spkt['ratings'][] = array( - 'type' => 'rating', - 'encoding' => 'zot', - 'channel' => $rr['xlink_xchan'], - 'target' => $rr['xlink_link'], - 'rating' => intval($rr['xlink_rating']), - 'rating_text' => $rr['xlink_rating_text'], - 'signature' => $rr['xlink_sig'], - 'edited' => $rr['xlink_updated'] - ); - } - } 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 ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 - $safesql $order $qlimit " + + $r = q("SELECT + xchan.xchan_name as name, + xchan.xchan_hash as hash, + xchan.xchan_censored as censored, + xchan.xchan_selfcensored as selfcensored, + xchan.xchan_pubforum as public_forum, + xchan.xchan_url as url, + xchan.xchan_photo_l as photo_l, + xchan.xchan_photo_m as photo, + xchan.xchan_addr as address, + xprof.xprof_desc as description, + xprof.xprof_locale as locale, + xprof.xprof_region as region, + xprof.xprof_postcode as postcode, + xprof.xprof_country as country, + xprof.xprof_dob as birthday, + xprof.xprof_age as age, + xprof.xprof_gender as gender, + xprof.xprof_marital as marital, + xprof.xprof_sexual as sexual, + xprof.xprof_about as about, + xprof.xprof_homepage as homepage, + xprof.xprof_hometown as hometown, + xprof.xprof_keywords as keywords + from xchan left join xprof on xchan_hash = xprof_hash left join hubloc on hubloc_hash = xchan_hash + where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 + $safesql $order $qlimit", + db_utcnow(), + db_quoteinterval('30 DAY') ); - - - - $ret['page'] = $page + 1; - $ret['records'] = count($r); + } - - - + if($r) { - - $entries = array(); - - foreach($r as $rr) { - - $entry = array(); - - $pc = q("select count(xlink_rating) as total_ratings from xlink where xlink_link = '%s' and xlink_rating != 0 and xlink_static = 1 group by xlink_rating", - dbesc($rr['xchan_hash']) - ); - - if($pc) - $entry['total_ratings'] = intval($pc[0]['total_ratings']); - else - $entry['total_ratings'] = 0; - - $entry['name'] = $rr['xchan_name']; - $entry['hash'] = $rr['xchan_hash']; - $entry['censored'] = $rr['xchan_censored']; - $entry['selfcensored'] = $rr['xchan_selfcensored']; - $entry['public_forum'] = (intval($rr['xchan_pubforum']) ? true : false); - $entry['url'] = $rr['xchan_url']; - $entry['photo_l'] = $rr['xchan_photo_l']; - $entry['photo'] = $rr['xchan_photo_m']; - $entry['address'] = $rr['xchan_addr']; - $entry['description'] = $rr['xprof_desc']; - $entry['locale'] = $rr['xprof_locale']; - $entry['region'] = $rr['xprof_region']; - $entry['postcode'] = $rr['xprof_postcode']; - $entry['country'] = $rr['xprof_country']; - $entry['birthday'] = $rr['xprof_dob']; - $entry['age'] = $rr['xprof_age']; - $entry['gender'] = $rr['xprof_gender']; - $entry['marital'] = $rr['xprof_marital']; - $entry['sexual'] = $rr['xprof_sexual']; - $entry['about'] = $rr['xprof_about']; - $entry['homepage'] = $rr['xprof_homepage']; - $entry['hometown'] = $rr['xprof_hometown']; - $entry['keywords'] = $rr['xprof_keywords']; - - $entries[] = $entry; - - } - - $ret['results'] = $entries; + $ret['results'] = $r; + $ret['page'] = $page + 1; + $ret['records'] = count($r); + if($kw) { $k = dir_tagadelic($kw, $hub); if($k) { @@ -328,30 +285,30 @@ class Dirsearch extends Controller { } } } - } - + } + json_return_and_die($ret); } - + function dir_query_build($joiner,$field,$s) { $ret = ''; if(trim($s)) $ret .= dbesc($joiner) . " " . dbesc($field) . " like '" . protect_sprintf( '%' . dbesc($s) . '%' ) . "' "; return $ret; } - + function dir_flag_build($joiner,$field,$bit,$s) { return dbesc($joiner) . " ( " . dbesc($field) . " & " . intval($bit) . " ) " . ((intval($s)) ? '>' : '=' ) . " 0 "; } - - + + function dir_parse_query($s) { - + $ret = array(); $curr = array(); $all = explode(' ',$s); $quoted_string = false; - + if($all) { foreach($all as $q) { if($quoted_string === false) { @@ -382,7 +339,7 @@ class Dirsearch extends Controller { $ret[] = $curr; $curr = array(); continue; - } + } else { $ret[] = $curr; $curr = array(); @@ -405,15 +362,15 @@ class Dirsearch extends Controller { logger('dir_parse_query:' . print_r($ret,true),LOGGER_DATA); return $ret; } - - - - - - - + + + + + + + function list_public_sites() { - + $rand = db_getfunc('rand'); $realm = get_directory_realm(); if($realm == DIRECTORY_REALM) { @@ -428,16 +385,16 @@ class Dirsearch extends Controller { intval(SITE_TYPE_ZOT) ); } - + $ret = array('success' => false); - + if($r) { $ret['success'] = true; $ret['sites'] = array(); $insecure = array(); - + foreach($r as $rr) { - + if($rr['site_access'] == ACCESS_FREE) $access = 'free'; elseif($rr['site_access'] == ACCESS_PAID) @@ -446,14 +403,14 @@ class Dirsearch extends Controller { $access = 'tiered'; else $access = 'private'; - + if($rr['site_register'] == REGISTER_OPEN) $register = 'open'; elseif($rr['site_register'] == REGISTER_APPROVE) $register = 'approve'; else $register = 'closed'; - + if(strpos($rr['site_url'],'https://') !== false) $ret['sites'][] = array('url' => $rr['site_url'], 'access' => $access, 'register' => $register, 'sellpage' => $rr['site_sellpage'], 'location' => $rr['site_location'], 'project' => $rr['site_project'], 'version' => $rr['site_version']); else diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index e6caa9906..02a79f854 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use App; + require_once("include/bbcode.php"); require_once('include/security.php'); require_once('include/conversation.php'); @@ -34,11 +36,20 @@ class Display extends \Zotlabs\Web\Controller { } } - if($_REQUEST['mid']) + if($_REQUEST['mid']) { $item_hash = $_REQUEST['mid']; + } - if(! $item_hash) { - \App::$error = 404; + $item_hash = unpack_link_id($item_hash); + + if ($item_hash === false) { + App::$error = 400; + notice(t('Malformed message id.') . EOL); + return; + } + + if(!$item_hash) { + App::$error = 404; notice( t('Item not found.') . EOL); return; } @@ -47,7 +58,7 @@ class Display extends \Zotlabs\Web\Controller { if(local_channel() && (! $update)) { - $channel = \App::get_channel(); + $channel = App::get_channel(); $channel_acl = array( 'allow_cid' => $channel['channel_allow_cid'], @@ -92,11 +103,6 @@ class Display extends \Zotlabs\Web\Controller { $target_item = null; - if(strpos($item_hash,'b64.') === 0) - $decoded = @base64url_decode(substr($item_hash,4)); - if($decoded) - $item_hash = $decoded; - $r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid = '%s' limit 1", dbesc($item_hash) ); @@ -110,7 +116,7 @@ class Display extends \Zotlabs\Web\Controller { ); if($x) { // not yet ready for prime time -// \App::$poi = $x[0]; +// App::$poi = $x[0]; } //if the item is to be moderated redirect to /moderate @@ -189,17 +195,15 @@ class Display extends \Zotlabs\Web\Controller { // if the target item is not a post (eg a like) we want to address its thread parent //$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']); - $mid = $target_item['mid']; // if we got a decoded hash we must encode it again before handing to javascript - if($decoded) - $mid = 'b64.' . base64url_encode($mid); + $mid = gen_link_id($target_item['mid']); $o .= '<div id="live-display"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1)) - . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n"; + . "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . "; </script>\r\n"; - \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( + App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( '$baseurl' => z_root(), '$pgtype' => 'display', '$uid' => '0', @@ -215,7 +219,7 @@ class Display extends \Zotlabs\Web\Controller { '$dm' => '0', '$nouveau' => '0', '$wall' => '0', - '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), + '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$search' => '', '$xchan' => '', @@ -233,7 +237,7 @@ class Display extends \Zotlabs\Web\Controller { head_add_link([ 'rel' => 'alternate', 'type' => 'application/json+oembed', - 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string), 'title' => 'oembed' ]); @@ -355,7 +359,7 @@ class Display extends \Zotlabs\Web\Controller { } $o .= '</noscript>'; - \App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . \App::$page['title'] : \App::$page['title']); + App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . App::$page['title'] : App::$page['title']); $o .= conversation($items, 'display', $update, 'client'); } @@ -368,12 +372,12 @@ class Display extends \Zotlabs\Web\Controller { '$version' => xmlify(\Zotlabs\Lib\System::get_project_version()), '$generator' => xmlify(\Zotlabs\Lib\System::get_platform_name()), '$generator_uri' => 'https://hubzilla.org', - '$feed_id' => xmlify(\App::$cmd), + '$feed_id' => xmlify(App::$cmd), '$feed_title' => xmlify(t('Article')), '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now', ATOM_TIME)), '$author' => '', '$owner' => '', - '$profile_page' => xmlify(z_root() . '/display/' . $target_item['mid']), + '$profile_page' => xmlify(z_root() . '/display/' . gen_link_id($target_item['mid'])), )); $x = [ 'xml' => $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ]; diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php index 0fc36dc29..d6f4e5979 100644 --- a/Zotlabs/Module/Dreport.php +++ b/Zotlabs/Module/Dreport.php @@ -5,33 +5,21 @@ namespace Zotlabs\Module; class Dreport extends \Zotlabs\Web\Controller { function get() { - + if(! local_channel()) { notice( t('Permission denied') . EOL); return; } - + $table = 'item'; - $channel = \App::get_channel(); - - $mid = ((argc() > 1) ? argv(1) : ''); - $encoded_mid = ''; + $mid = ((argc() > 1) ? unpack_link_id(argv(1)) : ''); - if(strpos($mid,'b64.') === 0) { - $encoded_mid = $mid; - $mid = @base64url_decode(substr($mid,4)); - } if($mid === 'push') { $table = 'push'; - $mid = ((argc() > 2) ? argv(2) : ''); - - if(strpos($mid,'b64.') === 0) { - $encoded_mid = $mid; - $mid = @base64url_decode(substr($mid,4)); - } + $mid = ((argc() > 2) ? unpack_link_id(argv(2)) : ''); - if($mid) { + if($mid) { $i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ", dbesc($mid), intval($channel['channel_id']), @@ -43,23 +31,14 @@ class Dreport extends \Zotlabs\Web\Controller { } } sleep(3); - goaway(z_root() . '/dreport/' . (($encoded_mid) ? $encoded_mid : $mid)); + goaway(z_root() . '/dreport/' . gen_link_id($mid)); } - if($mid === 'mail') { - $table = 'mail'; - $mid = ((argc() > 2) ? argv(2) : ''); - if(strpos($mid,'b64.') === 0) - $mid = @base64url_decode(substr($mid,4)); - - } - - if(! $mid) { notice( t('Invalid message') . EOL); return; } - + switch($table) { case 'item': $i = q("select id from item where mid = '%s' and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ", @@ -68,39 +47,33 @@ class Dreport extends \Zotlabs\Web\Controller { dbesc($channel['channel_hash']) ); break; - case 'mail': - $i = q("select id from mail where mid = '%s' and from_xchan = '%s'", - dbesc($mid), - dbesc($channel['channel_hash']) - ); - break; default: break; } - + if(! $i) { notice( t('Permission denied') . EOL); return; } - - $r = q("select * from dreport where (dreport_xchan = '%s' or dreport_xchan = '%s') and dreport_mid = '%s'", + + $r = q("select * from dreport where dreport_xchan = '%s' and (dreport_mid = '%s' or dreport_mid = '%s')", dbesc($channel['channel_hash']), - dbesc($channel['channel_portable_id']), - dbesc($mid) + dbesc($mid), + dbesc(str_replace('/item/', '/activity/', $mid)) ); - + if(! $r) { notice( t('no results') . EOL); // return; } - + for($x = 0; $x < count($r); $x++ ) { - + // This has two purposes: 1. make the delivery report strings translateable, and // 2. assign an ordering to item delivery results so we can group them and provide // a readable report with more interesting events listed toward the top and lesser // interesting items towards the bottom - + switch($r[$x]['dreport_result']) { case 'channel sync processed': $r[$x]['gravity'] = 0; @@ -132,27 +105,18 @@ class Dreport extends \Zotlabs\Web\Controller { case 'recipient not found': $r[$x]['dreport_result'] = t('recipient not found'); break; - case 'mail recalled': - $r[$x]['dreport_result'] = t('mail recalled'); - break; - case 'duplicate mail received': - $r[$x]['dreport_result'] = t('duplicate mail received'); - break; - case 'mail delivered': - $r[$x]['dreport_result'] = t('mail delivered'); - break; default: $r[$x]['gravity'] = 1; break; } } - + usort($r,'self::dreport_gravity_sort'); $entries = array(); foreach($r as $rr) { - $entries[] = [ - 'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']), + $entries[] = [ + 'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']), 'result' => escape_tags($rr['dreport_result']), 'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time'])) ]; @@ -167,14 +131,14 @@ class Dreport extends \Zotlabs\Web\Controller { '$push' => t('Redeliver'), '$entries' => $entries )); - - + + return $o; - - - + + + } - + private static function dreport_gravity_sort($a,$b) { if($a['gravity'] == $b['gravity']) { if($a['dreport_name'] === $b['dreport_name']) @@ -183,5 +147,5 @@ class Dreport extends \Zotlabs\Web\Controller { } return (($a['gravity'] > $b['gravity']) ? 1 : (-1)); } - + } diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php deleted file mode 100644 index 681d6887d..000000000 --- a/Zotlabs/Module/Events.php +++ /dev/null @@ -1,750 +0,0 @@ -<?php -namespace Zotlabs\Module; - -require_once('include/conversation.php'); -require_once('include/bbcode.php'); -require_once('include/datetime.php'); -require_once('include/event.php'); -require_once('include/items.php'); -require_once('include/html2plain.php'); - -class Events extends \Zotlabs\Web\Controller { - - function post() { - - // this module is deprecated - return; - - logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA); - - if(! local_channel()) - return; - - if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size'])) { - $src = $_FILES['userfile']['tmp_name']; - if($src) { - $result = parse_ical_file($src,local_channel()); - if($result) - info( t('Calendar entries imported.') . EOL); - else - notice( t('No calendar entries found.') . EOL); - @unlink($src); - } - goaway(z_root() . '/events'); - } - - - $event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0); - $event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : ''); - - $xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : ''); - $uid = local_channel(); - - $start_text = escape_tags($_REQUEST['start_text']); - $finish_text = escape_tags($_REQUEST['finish_text']); - - $adjust = intval($_POST['adjust']); - $nofinish = intval($_POST['nofinish']); - - $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : ''); - - $tz = (($timezone) ? $timezone : date_default_timezone_get()); - - $categories = escape_tags(trim($_POST['category'])); - - // only allow editing your own events. - - if(($xchan) && ($xchan !== get_observer_hash())) - return; - - if($start_text) { - $start = $start_text; - } - else { - $start = sprintf('%d-%d-%d %d:%d:0',$startyear,$startmonth,$startday,$starthour,$startminute); - } - - - if($finish_text) { - $finish = $finish_text; - } - else { - $finish = sprintf('%d-%d-%d %d:%d:0',$finishyear,$finishmonth,$finishday,$finishhour,$finishminute); - } - - if($nofinish) { - $finish = NULL_DATE; - } - - - if($adjust) { - $start = datetime_convert($tz,'UTC',$start); - if(! $nofinish) - $finish = datetime_convert($tz,'UTC',$finish); - } - else { - $start = datetime_convert('UTC','UTC',$start); - if(! $nofinish) - $finish = datetime_convert('UTC','UTC',$finish); - } - - // Don't allow the event to finish before it begins. - // It won't hurt anything, but somebody will file a bug report - // and we'll waste a bunch of time responding to it. Time that - // could've been spent doing something else. - - - $summary = escape_tags(trim($_POST['summary'])); - $desc = escape_tags(trim($_POST['desc'])); - $location = escape_tags(trim($_POST['location'])); - $type = escape_tags(trim($_POST['type'])); - - require_once('include/text.php'); - linkify_tags($desc, local_channel()); - linkify_tags($location, local_channel()); - - //$action = ($event_hash == '') ? 'new' : "event/" . $event_hash; - - //fixme: this url gives a wsod if there is a linebreak detected in one of the variables ($desc or $location) - //$onerror_url = z_root() . "/events/" . $action . "?summary=$summary&description=$desc&location=$location&start=$start_text&finish=$finish_text&adjust=$adjust&nofinish=$nofinish&type=$type"; - $onerror_url = z_root() . "/events"; - - if(strcmp($finish,$start) < 0 && !$nofinish) { - notice( t('Event can not end before it has started.') . EOL); - if(intval($_REQUEST['preview'])) { - echo( t('Unable to generate preview.')); - killme(); - } - goaway($onerror_url); - } - - if((! $summary) || (! $start)) { - notice( t('Event title and start time are required.') . EOL); - if(intval($_REQUEST['preview'])) { - echo( t('Unable to generate preview.')); - killme(); - } - goaway($onerror_url); - } - - // $share = ((intval($_POST['distr'])) ? intval($_POST['distr']) : 0); - - $share = 1; - - $channel = \App::get_channel(); - - $acl = new \Zotlabs\Access\AccessList(false); - - if($event_id) { - $x = q("select * from event where id = %d and uid = %d limit 1", - intval($event_id), - intval(local_channel()) - ); - if(! $x) { - notice( t('Event not found.') . EOL); - if(intval($_REQUEST['preview'])) { - echo( t('Unable to generate preview.')); - killme(); - } - return; - } - - $acl->set($x[0]); - - $created = $x[0]['created']; - $edited = datetime_convert(); - - if($x[0]['allow_cid'] === '<' . $channel['channel_hash'] . '>' - && $x[0]['allow_gid'] === '' && $x[0]['deny_cid'] === '' && $x[0]['deny_gid'] === '') { - $share = false; - } - else { - $share = true; - } - } - else { - $created = $edited = datetime_convert(); - if($share) { - $acl->set_from_array($_POST); - } - else { - $acl->set(array('allow_cid' => '<' . $channel['channel_hash'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '')); - } - } - - $post_tags = array(); - $channel = \App::get_channel(); - $ac = $acl->get(); - - if(strlen($categories)) { - $cats = explode(',',$categories); - foreach($cats as $cat) { - $post_tags[] = array( - 'uid' => $profile_uid, - 'ttype' => TERM_CATEGORY, - 'otype' => TERM_OBJ_POST, - 'term' => trim($cat), - 'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat)) - ); - } - } - - $datarray = array(); - $datarray['dtstart'] = $start; - $datarray['dtend'] = $finish; - $datarray['summary'] = $summary; - $datarray['description'] = $desc; - $datarray['location'] = $location; - $datarray['etype'] = $type; - $datarray['adjust'] = $adjust; - $datarray['nofinish'] = $nofinish; - $datarray['uid'] = local_channel(); - $datarray['account'] = get_account_id(); - $datarray['event_xchan'] = $channel['channel_hash']; - $datarray['allow_cid'] = $ac['allow_cid']; - $datarray['allow_gid'] = $ac['allow_gid']; - $datarray['deny_cid'] = $ac['deny_cid']; - $datarray['deny_gid'] = $ac['deny_gid']; - $datarray['private'] = (($acl->is_private()) ? 1 : 0); - $datarray['id'] = $event_id; - $datarray['created'] = $created; - $datarray['edited'] = $edited; - - if(intval($_REQUEST['preview'])) { - $html = format_event_html($datarray); - echo $html; - killme(); - } - - $event = event_store_event($datarray); - - if($post_tags) - $datarray['term'] = $post_tags; - - $item_id = event_store_item($datarray,$event); - - if($item_id) { - $r = q("select * from item where id = %d", - intval($item_id) - ); - if($r) { - xchan_query($r); - $sync_item = fetch_post_tags($r); - $z = q("select * from event where event_hash = '%s' and uid = %d limit 1", - dbesc($r[0]['resource_id']), - intval($channel['channel_id']) - ); - if($z) { - build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z)); - } - } - } - - if($share) - \Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id)); - - } - - - - function get() { - - // this module is deprecated - return; - - if(argc() > 2 && argv(1) == 'ical') { - $event_id = argv(2); - - require_once('include/security.php'); - $sql_extra = permissions_sql(local_channel()); - - $r = q("select * from event where event_hash = '%s' $sql_extra limit 1", - dbesc($event_id) - ); - if($r) { - header('Content-type: text/calendar'); - header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"' ); - echo ical_wrapper($r); - killme(); - } - else { - notice( t('Event not found.') . EOL ); - return; - } - } - - if(! local_channel()) { - notice( t('Permission denied.') . EOL); - return; - } - - \App::$profile_uid = local_channel(); - nav_set_selected('Events'); - - - if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) { - $r = q("update event set dismissed = 1 where id = %d and uid = %d", - intval(argv(2)), - intval(local_channel()) - ); - } - - if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) { - $r = q("update event set dismissed = 0 where id = %d and uid = %d", - intval(argv(2)), - intval(local_channel()) - ); - } - - $first_day = feature_enabled(local_channel(), 'events_cal_first_day'); - $first_day = (($first_day) ? $first_day : 0); - - $htpl = get_markup_template('event_head.tpl'); - \App::$page['htmlhead'] .= replace_macros($htpl,array( - '$baseurl' => z_root(), - '$module_url' => '/events', - '$modparams' => 1, - '$lang' => \App::$language, - '$first_day' => $first_day - )); - - $o = ''; - - $channel = \App::get_channel(); - - $mode = 'view'; - $y = 0; - $m = 0; - $ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : ''); - - - // logger('args: ' . print_r(\App::$argv,true)); - - - - if(argc() > 1) { - if(argc() > 2 && argv(1) === 'add') { - $mode = 'add'; - $item_id = intval(argv(2)); - } - if(argc() > 2 && argv(1) === 'drop') { - $mode = 'drop'; - $event_id = argv(2); - } - if(argc() > 2 && intval(argv(1)) && intval(argv(2))) { - $mode = 'view'; - $y = intval(argv(1)); - $m = intval(argv(2)); - } - if(argc() <= 2) { - $mode = 'view'; - $event_id = argv(1); - } - } - - if($mode === 'add') { - event_addtocal($item_id,local_channel()); - killme(); - } - - if($mode == 'view') { - - /* edit/create form */ - if($event_id) { - $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1", - dbesc($event_id), - intval(local_channel()) - ); - if(count($r)) - $orig_event = $r[0]; - } - - $channel = \App::get_channel(); - - // Passed parameters overrides anything found in the DB - if(!x($orig_event)) - $orig_event = array(); - - // In case of an error the browser is redirected back here, with these parameters filled in with the previous values - /* - if(x($_REQUEST,'nofinish')) $orig_event['nofinish'] = $_REQUEST['nofinish']; - if(x($_REQUEST,'adjust')) $orig_event['adjust'] = $_REQUEST['adjust']; - if(x($_REQUEST,'summary')) $orig_event['summary'] = $_REQUEST['summary']; - if(x($_REQUEST,'description')) $orig_event['description'] = $_REQUEST['description']; - if(x($_REQUEST,'location')) $orig_event['location'] = $_REQUEST['location']; - if(x($_REQUEST,'start')) $orig_event['dtstart'] = $_REQUEST['start']; - if(x($_REQUEST,'finish')) $orig_event['dtend'] = $_REQUEST['finish']; - if(x($_REQUEST,'type')) $orig_event['etype'] = $_REQUEST['type']; - */ - - $n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : ''); - $a_checked = ((x($orig_event) && $orig_event['adjust']) ? ' checked="checked" ' : ''); - $t_orig = ((x($orig_event)) ? $orig_event['summary'] : ''); - $d_orig = ((x($orig_event)) ? $orig_event['description'] : ''); - $l_orig = ((x($orig_event)) ? $orig_event['location'] : ''); - $eid = ((x($orig_event)) ? $orig_event['id'] : 0); - $event_xchan = ((x($orig_event)) ? $orig_event['event_xchan'] : $channel['channel_hash']); - $mid = ((x($orig_event)) ? $orig_event['mid'] : ''); - - if(! x($orig_event)) { - $sh_checked = ''; - $a_checked = ' checked="checked" '; - } - else { - $sh_checked = ((($orig_event['allow_cid'] === '<' . $channel['channel_hash'] . '>' || (! $orig_event['allow_cid'])) && (! $orig_event['allow_gid']) && (! $orig_event['deny_cid']) && (! $orig_event['deny_gid'])) ? '' : ' checked="checked" ' ); - } - - if($orig_event['event_xchan']) - $sh_checked .= ' disabled="disabled" '; - - $sdt = ((x($orig_event)) ? $orig_event['dtstart'] : 'now'); - - $fdt = ((x($orig_event)) ? $orig_event['dtend'] : '+1 hour'); - - $tz = date_default_timezone_get(); - if(x($orig_event)) - $tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC'); - - $syear = datetime_convert('UTC', $tz, $sdt, 'Y'); - $smonth = datetime_convert('UTC', $tz, $sdt, 'm'); - $sday = datetime_convert('UTC', $tz, $sdt, 'd'); - $shour = datetime_convert('UTC', $tz, $sdt, 'H'); - $sminute = datetime_convert('UTC', $tz, $sdt, 'i'); - - $stext = datetime_convert('UTC',$tz,$sdt); - $stext = substr($stext,0,14) . "00:00"; - - $fyear = datetime_convert('UTC', $tz, $fdt, 'Y'); - $fmonth = datetime_convert('UTC', $tz, $fdt, 'm'); - $fday = datetime_convert('UTC', $tz, $fdt, 'd'); - $fhour = datetime_convert('UTC', $tz, $fdt, 'H'); - $fminute = datetime_convert('UTC', $tz, $fdt, 'i'); - - $ftext = datetime_convert('UTC',$tz,$fdt); - $ftext = substr($ftext,0,14) . "00:00"; - - $type = ((x($orig_event)) ? $orig_event['etype'] : 'event'); - - $f = get_config('system','event_input_format'); - if(! $f) - $f = 'ymd'; - - $catsenabled = feature_enabled(local_channel(),'categories'); - - $category = ''; - - if($catsenabled && x($orig_event)){ - $itm = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d limit 1", - dbesc($orig_event['event_hash']), - intval(local_channel()) - ); - $itm = fetch_post_tags($itm); - if($itm) { - $cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY); - foreach ($cats as $cat) { - if(strlen($category)) - $category .= ', '; - $category .= $cat['term']; - } - } - } - - require_once('include/acl_selectors.php'); - - $acl = new \Zotlabs\Access\AccessList($channel); - $perm_defaults = $acl->get(); - - $permissions = ((x($orig_event)) ? $orig_event : $perm_defaults); - - $tpl = get_markup_template('event_form.tpl'); - - $form = replace_macros($tpl,array( - '$post' => z_root() . '/events', - '$eid' => $eid, - '$type' => $type, - '$xchan' => $event_xchan, - '$mid' => $mid, - '$event_hash' => $event_id, - '$summary' => array('summary', (($event_id) ? t('Edit event title') : t('Event title')), $t_orig, t('Required'), '*'), - '$catsenabled' => $catsenabled, - '$placeholdercategory' => t('Categories (comma-separated list)'), - '$c_text' => (($event_id) ? t('Edit Category') : t('Category')), - '$category' => $category, - '$required' => '<span class="required" title="' . t('Required') . '">*</span>', - '$s_dsel' => datetimesel($f,new \DateTime(),\DateTime::createFromFormat('Y',$syear+5),\DateTime::createFromFormat('Y-m-d H:i',"$syear-$smonth-$sday $shour:$sminute"), (($event_id) ? t('Edit start date and time') : t('Start date and time')), 'start_text',true,true,'','',true,$first_day), - '$n_text' => t('Finish date and time are not known or not relevant'), - '$n_checked' => $n_checked, - '$f_dsel' => datetimesel($f,new \DateTime(),\DateTime::createFromFormat('Y',$fyear+5),\DateTime::createFromFormat('Y-m-d H:i',"$fyear-$fmonth-$fday $fhour:$fminute"), (($event_id) ? t('Edit finish date and time') : t('Finish date and time')),'finish_text',true,true,'start_text','',false,$first_day), - '$nofinish' => array('nofinish', t('Finish date and time are not known or not relevant'), $n_checked, '', array(t('No'),t('Yes')), 'onclick="enableDisableFinishDate();"'), - '$adjust' => array('adjust', t('Adjust for viewer timezone'), $a_checked, t('Important for events that happen in a particular place. Not practical for global holidays.'), array(t('No'),t('Yes'))), - '$a_text' => t('Adjust for viewer timezone'), - '$d_text' => (($event_id) ? t('Edit Description') : t('Description')), - '$d_orig' => $d_orig, - '$l_text' => (($event_id) ? t('Edit Location') : t('Location')), - '$l_orig' => $l_orig, - '$t_orig' => $t_orig, - '$preview' => t('Preview'), - '$perms_label' => t('Permission settings'), - // populating the acl dialog was a permission description from view_stream because Cal.php, which - // displays events, says "since we don't currently have an event permission - use the stream permission" - '$acl' => (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults), false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'))), - - '$allow_cid' => acl2json($permissions['allow_cid']), - '$allow_gid' => acl2json($permissions['allow_gid']), - '$deny_cid' => acl2json($permissions['deny_cid']), - '$deny_gid' => acl2json($permissions['deny_gid']), - '$tz_choose' => feature_enabled(local_channel(),'event_tz_select'), - '$timezone' => array('timezone_select' , t('Timezone:'), date_default_timezone_get(), '', get_timezones()), - - '$lockstate' => (($acl->is_private()) ? 'lock' : 'unlock'), - - '$submit' => t('Submit'), - '$advanced' => t('Advanced Options') - - )); - /* end edit/create form */ - - $thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); - $thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m'); - if(! $y) - $y = intval($thisyear); - if(! $m) - $m = intval($thismonth); - - $export = false; - if(argc() === 4 && argv(3) === 'export') - $export = true; - - // Put some limits on dates. The PHP date functions don't seem to do so well before 1900. - // An upper limit was chosen to keep search engines from exploring links millions of years in the future. - - if($y < 1901) - $y = 1900; - if($y > 2099) - $y = 2100; - - $nextyear = $y; - $nextmonth = $m + 1; - if($nextmonth > 12) { - $nextmonth = 1; - $nextyear ++; - } - - $prevyear = $y; - if($m > 1) - $prevmonth = $m - 1; - else { - $prevmonth = 12; - $prevyear --; - } - - $dim = get_dim($y,$m); - $start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0); - $finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59); - - - if (argv(1) === 'json'){ - if (x($_GET,'start')) $start = $_GET['start']; - if (x($_GET,'end')) $finish = $_GET['end']; - } - - $start = datetime_convert('UTC','UTC',$start); - $finish = datetime_convert('UTC','UTC',$finish); - - $adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start); - $adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish); - - if (x($_GET,'id')){ - $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan - from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d limit 1", - intval(local_channel()), - intval($_GET['id']) - ); - } elseif($export) { - $r = q("SELECT * from event where uid = %d - AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' ) - OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) ", - intval(local_channel()), - dbesc($start), - dbesc($finish), - dbesc($adjust_start), - dbesc($adjust_finish) - ); - } - else { - // fixed an issue with "nofinish" events not showing up in the calendar. - // There's still an issue if the finish date crosses the end of month. - // Noting this for now - it will need to be fixed here and in Friendica. - // Ultimately the finish date shouldn't be involved in the query. - - $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan - from event left join item on event_hash = resource_id - where resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored - AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' ) - OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) ", - intval(local_channel()), - dbesc($start), - dbesc($finish), - dbesc($adjust_start), - dbesc($adjust_finish) - ); - } - - $links = array(); - - if($r && ! $export) { - xchan_query($r); - $r = fetch_post_tags($r,true); - - $r = sort_by_date($r); - } - - if($r) { - foreach($r as $rr) { - $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j')); - if(! x($links,$j)) - $links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j; - } - } - - $events=array(); - - $last_date = ''; - $fmt = t('l, F j'); - - if($r) { - - foreach($r as $rr) { - - $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j')); - $d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], $fmt) : datetime_convert('UTC','UTC',$rr['dtstart'],$fmt)); - $d = day_translate($d); - - $start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c')); - if ($rr['nofinish']){ - $end = null; - } else { - $end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c')); - - // give a fake end to birthdays so they get crammed into a - // single day on the calendar - - if($rr['etype'] === 'birthday') - $end = null; - } - - - $is_first = ($d !== $last_date); - - $last_date = $d; - - $edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root().'/events/'.$rr['event_hash'].'?expandform=1',t('Edit event'),'','') : false); - - $drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'',''); - - $title = strip_tags(html_entity_decode(zidify_links(bbcode($rr['summary'])),ENT_QUOTES,'UTF-8')); - if(! $title) { - list($title, $_trash) = explode("<br",bbcode($rr['desc']),2); - $title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8')); - } - $html = format_event_html($rr); - $rr['desc'] = zidify_links(smilies(bbcode($rr['desc']))); - $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8',false); - $rr['location'] = zidify_links(smilies(bbcode($rr['location']))); - $events[] = array( - 'id'=>$rr['id'], - 'hash' => $rr['event_hash'], - 'start'=> $start, - 'end' => $end, - 'drop' => $drop, - 'allDay' => false, - 'title' => $title, - - 'j' => $j, - 'd' => $d, - 'edit' => $edit, - 'is_first'=>$is_first, - 'item'=>$rr, - 'html'=>$html, - 'plink' => array($rr['plink'],t('Link to Source'),'',''), - ); - - } - } - - if($export) { - header('Content-type: text/calendar'); - header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' ); - echo ical_wrapper($r); - killme(); - } - - if (\App::$argv[1] === 'json'){ - echo json_encode($events); killme(); - } - - // links: array('href', 'text', 'extra css classes', 'title') - if (x($_GET,'id')){ - $tpl = get_markup_template("event.tpl"); - } - else { - $tpl = get_markup_template("events-js.tpl"); - } - - $o = replace_macros($tpl, array( - '$baseurl' => z_root(), - '$new_event' => array(z_root().'/events',(($event_id) ? t('Edit Event') : t('Create Event')),'',''), - '$previus' => array(z_root()."/events/$prevyear/$prevmonth",t('Previous'),'',''), - '$next' => array(z_root()."/events/$nextyear/$nextmonth",t('Next'),'',''), - '$export' => array(z_root()."/events/$y/$m/export",t('Export'),'',''), - '$calendar' => cal($y,$m,$links, ' eventcal'), - '$events' => $events, - '$view_label' => t('View'), - '$month' => t('Month'), - '$week' => t('Week'), - '$day' => t('Day'), - '$prev' => t('Previous'), - '$next' => t('Next'), - '$today' => t('Today'), - '$form' => $form, - '$expandform' => ((x($_GET,'expandform')) ? true : false), - )); - - if (x($_GET,'id')){ echo $o; killme(); } - - return $o; - } - - if($mode === 'drop' && $event_id) { - $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1", - dbesc($event_id), - intval(local_channel()) - ); - - $sync_event = $r[0]; - - if($r) { - $r = q("delete from event where event_hash = '%s' and uid = %d", - dbesc($event_id), - intval(local_channel()) - ); - if($r) { - $r = q("update item set resource_type = '', resource_id = '' where resource_type = 'event' and resource_id = '%s' and uid = %d", - dbesc($event_id), - intval(local_channel()) - ); - $sync_event['event_deleted'] = 1; - build_sync_packet(0,array('event' => array($sync_event))); - - info( t('Event removed') . EOL); - } - else { - notice( t('Failed to remove event' ) . EOL); - } - goaway(z_root() . '/events'); - } - } - - } - -} diff --git a/Zotlabs/Module/Fhublocs.php b/Zotlabs/Module/Fhublocs.php index 42dac5b12..9dcece715 100644 --- a/Zotlabs/Module/Fhublocs.php +++ b/Zotlabs/Module/Fhublocs.php @@ -3,7 +3,6 @@ namespace Zotlabs\Module; use Zotlabs\Lib\Libzot; -require_once('include/zot.php'); require_once('include/crypto.php'); /* fix missing or damaged hublocs */ @@ -59,23 +58,6 @@ class Fhublocs extends \Zotlabs\Web\Controller { // Create a verified hub location pointing to this site. -/* - $h = hubloc_store_lowlevel( - [ - 'hubloc_guid' => $rr['channel_guid'], - 'hubloc_guid_sig' => $rr['channel_guid_sig'], - 'hubloc_hash' => $rr['channel_hash'], - 'hubloc_addr' => channel_reddress($rr), - 'hubloc_network' => 'zot', - 'hubloc_primary' => $primary, - 'hubloc_url' => z_root(), - 'hubloc_url_sig' => base64url_encode(Crypto::sign(z_root(),$rr['channel_prvkey'])), - 'hubloc_host' => \App::get_hostname(), - 'hubloc_callback' => z_root() . '/post', - 'hubloc_sitekey' => $sitekey - ] - ); -*/ $h = hubloc_store_lowlevel( [ 'hubloc_guid' => $rr['channel_guid'], diff --git a/Zotlabs/Module/File_upload.php b/Zotlabs/Module/File_upload.php index e18067e20..d4c9ad59a 100644 --- a/Zotlabs/Module/File_upload.php +++ b/Zotlabs/Module/File_upload.php @@ -99,6 +99,9 @@ class File_upload extends \Zotlabs\Web\Controller { } } + if(is_ajax()) + killme(); + goaway(z_root() . '/' . $_REQUEST['return_url']); } diff --git a/Zotlabs/Module/Follow.php b/Zotlabs/Module/Follow.php index 4fe20f56b..94daa4c70 100644 --- a/Zotlabs/Module/Follow.php +++ b/Zotlabs/Module/Follow.php @@ -108,7 +108,7 @@ class Follow extends Controller { } Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true); - $can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream'); + $can_view_stream = intval(get_abconfig($channel['channel_id'], $clone['abook_xchan'], 'their_perms', 'view_stream')); // If we can view their stream, pull in some posts @@ -117,7 +117,7 @@ class Follow extends Controller { } if ($interactive) { - goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1'); + goaway(z_root() . '/connections#' . $result['abook']['abook_id']); } else { json_return_and_die([ 'success' => true ]); diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index 993d428f5..1dce08757 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -5,8 +5,7 @@ use App; use Zotlabs\Web\Controller; use Zotlabs\Lib\Apps; use Zotlabs\Lib\Libsync; - -require_once('include/group.php'); +use Zotlabs\Lib\AccessList; class Group extends Controller { @@ -26,7 +25,7 @@ class Group extends Controller { } function post() { - + if(! local_channel()) { notice( t('Permission denied.') . EOL); return; @@ -35,25 +34,26 @@ class Group extends Controller { if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) { return; } - + if((argc() == 2) && (argv(1) === 'new')) { check_form_security_token_redirectOnErr('/group/new', 'group_edit'); - + $name = notags(trim($_POST['groupname'])); $public = intval($_POST['public']); - $r = group_add(local_channel(),$name,$public); + $r = AccessList::add(local_channel(),$name,$public); + $group_hash = $r; + if($r) { info( t('Privacy group created.') . EOL ); } else { notice( t('Could not create privacy group.') . EOL ); } - goaway(z_root() . '/group'); - } + if((argc() == 2) && (intval(argv(1)))) { check_form_security_token_redirectOnErr('/group', 'group_edit'); - + $r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1", intval(argv(1)), intval(local_channel()) @@ -61,14 +61,15 @@ class Group extends Controller { if(! $r) { notice( t('Privacy group not found.') . EOL ); goaway(z_root() . '/connections'); - + } $group = $r[0]; $groupname = notags(trim($_POST['groupname'])); + $group_hash = $group['hash']; $public = intval($_POST['public']); - + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ]; - call_hooks ('privacygroup_extras_post',$hookinfo); + call_hooks('privacygroup_extras_post',$hookinfo); if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) { $r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d", @@ -79,22 +80,30 @@ class Group extends Controller { ); if($r) info( t('Privacy group updated.') . EOL ); - - - Libsync::build_sync_packet(local_channel(),null,true); } - - goaway(z_root() . '/group/' . argv(1) . '/' . argv(2)); } - return; + + $channel = App::get_channel(); + + $default_group = ((isset($_POST['set_default_group'])) ? $group_hash : (($channel['channel_default_group'] === $group_hash) ? '' : $channel['channel_default_group'])); + $default_acl = ((isset($_POST['set_default_acl'])) ? '<' . $group_hash . '>' : (($channel['channel_allow_gid'] === '<' . $group_hash . '>') ? '' : $channel['channel_allow_gid'])); + + q("update channel set channel_default_group = '%s', channel_allow_gid = '%s' + where channel_id = %d", + dbesc($default_group), + dbesc($default_acl), + intval(local_channel()) + ); + + Libsync::build_sync_packet(local_channel(),null,true); + + goaway(z_root() . '/group/' . argv(1) . ((argv(2)) ? '/' . argv(2) : '')); + + return; } - + function get() { - $change = false; - - logger('mod_group: ' . App::$cmd,LOGGER_DEBUG); - if(! local_channel()) { notice( t('Permission denied') . EOL); return; @@ -103,12 +112,14 @@ class Group extends Controller { if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Privacy Groups App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Management of privacy groups'); - return $o; + $papp = Apps::get_papp('Privacy Groups'); + return Apps::app_render($papp, 'module'); } + logger('mod_group: ' . App::$cmd,LOGGER_DEBUG); + + $change = false; + // Switch to text mode interface if we have more than 'n' contacts or group members $switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit'); if($switchtotext === false) @@ -119,64 +130,45 @@ class Group extends Controller { if((argc() == 1) || ((argc() == 2) && (argv(1) === 'new'))) { - $new = (((argc() == 2) && (argv(1) === 'new')) ? true : false); - - $groups = q("SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", - intval(local_channel()) - ); - - $i = 0; - foreach($groups as $group) { - $entries[$i]['name'] = $group['gname']; - $entries[$i]['id'] = $group['id']; - $entries[$i]['count'] = count(group_get_members($group['id'])); - $i++; - } - $hookinfo = [ 'pgrp_extras' => '', 'group'=>argv(1) ]; call_hooks ('privacygroup_extras',$hookinfo); $pgrp_extras = $hookinfo['pgrp_extras']; + $is_default_acl = ['set_default_acl', t('Post to this group by default'), 0, '', [t('No'), t('Yes')]]; + $is_default_group = ['set_default_group', t('Add new contacts to this group by default'), 0, '', [t('No'), t('Yes')]]; + + $tpl = get_markup_template('privacy_groups.tpl'); $o = replace_macros($tpl, [ '$title' => t('Privacy Groups'), - '$add_new_label' => t('Add Group'), - '$new' => $new, // new group form '$gname' => array('groupname',t('Privacy group name')), - '$public' => array('public',t('Members are visible to other channels'), false), + '$public' => array('public',t('Members are visible to other channels'), 0, '', [t('No'), t('Yes')]), '$pgrp_extras' => $pgrp_extras, '$form_security_token' => get_form_security_token("group_edit"), '$submit' => t('Submit'), - - // groups list - '$title' => t('Privacy Groups'), - '$name_label' => t('Name'), - '$count_label' => t('Members'), - '$entries' => $entries + '$is_default_acl' => $is_default_acl, + '$is_default_group' => $is_default_group, ]); return $o; } - - - $context = array('$submit' => t('Submit')); $tpl = get_markup_template('group_edit.tpl'); - + if((argc() == 3) && (argv(1) === 'drop')) { check_form_security_token_redirectOnErr('/group', 'group_drop', 't'); - + if(intval(argv(2))) { $r = q("SELECT gname FROM pgrp WHERE id = %d AND uid = %d LIMIT 1", intval(argv(2)), intval(local_channel()) ); - if($r) - $result = group_rmv(local_channel(),$r[0]['gname']); + if($r) + $result = AccessList::remove(local_channel(),$r[0]['gname']); if($result) { $hookinfo = [ 'pgrp_extras' => '', 'group' => argv(2) ]; call_hooks ('privacygroup_extras_drop',$hookinfo); @@ -188,23 +180,23 @@ class Group extends Controller { goaway(z_root() . '/group'); // NOTREACHED } - - + + if((argc() > 2) && intval(argv(1)) && argv(2)) { - + check_form_security_token_ForbiddenOnErr('group_member_change', 't'); - + $r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1", dbesc(base64url_decode(argv(2))), intval(local_channel()) ); if(count($r)) $change = base64url_decode(argv(2)); - + } - + if((argc() > 1) && (intval(argv(1)))) { - + require_once('include/acl_selectors.php'); $r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1", intval(argv(1)), @@ -215,28 +207,28 @@ class Group extends Controller { goaway(z_root() . '/connections'); } $group = $r[0]; - - - $members = group_get_members($group['id']); - + + + $members = AccessList::members(local_channel(), $group['id']); + $preselected = array(); if(count($members)) { foreach($members as $member) if(! in_array($member['xchan_hash'],$preselected)) $preselected[] = $member['xchan_hash']; } - + if($change) { - + if(in_array($change,$preselected)) { - group_rmv_member(local_channel(),$group['gname'],$change); + AccessList::member_remove(local_channel(),$group['gname'],$change); } else { - group_add_member(local_channel(),$group['gname'],$change); + AccessList::member_add(local_channel(),$group['gname'],$change); } - - $members = group_get_members($group['id']); - + + $members = AccessList::members(local_channel(), $group['id']); + $preselected = array(); if(count($members)) { foreach($members as $member) @@ -254,25 +246,25 @@ class Group extends Controller { '$gname' => array('groupname',t('Privacy group name: '),$group['gname'], ''), '$gid' => $group['id'], '$drop' => $drop_txt, - '$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''), + '$public' => array('public',t('Members are visible to other channels'), $group['visible'], '', [t('No'), t('Yes')]), '$form_security_token_edit' => get_form_security_token('group_edit'), - '$delete' => t('Delete Group'), + '$delete' => t('Delete'), '$form_security_token_drop' => get_form_security_token("group_drop"), '$pgrp_extras' => $pgrp_extras, ); - + } - + if(! isset($group)) return; - + $groupeditor = array( 'label_members' => t('Group members'), 'members' => array(), 'label_contacts' => t('Not in this group'), 'contacts' => array(), ); - + $sec_token = addslashes(get_form_security_token('group_member_change')); $textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : 'card'); foreach($members as $member) { @@ -282,13 +274,13 @@ class Group extends Controller { $groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode); } else - group_rmv_member(local_channel(),$group['gname'],$member['xchan_hash']); + AccessList::member_remove(local_channel(),$group['gname'],$member['xchan_hash']); } - + $r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc", intval(local_channel()) ); - + if(count($r)) { $textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : 'card'); foreach($r as $member) { @@ -299,20 +291,26 @@ class Group extends Controller { } } } - + $context['$groupeditor'] = $groupeditor; $context['$desc'] = t('Click a channel to toggle membership'); $context['$pgrp_extras'] = $pgrp_extras; - + + $channel = App::get_channel(); + + $context['$is_default_acl'] = ['set_default_acl', t('Post to this group by default'), intval($group['hash'] === trim($channel['channel_allow_gid'], '<>')), '', [t('No'), t('Yes')]]; + $context['$is_default_group'] = ['set_default_group', t('Add new contacts to this group by default'), intval($group['hash'] === $channel['channel_default_group']), '', [t('No'), t('Yes')]]; + + if($change) { $tpl = get_markup_template('groupeditor.tpl'); echo replace_macros($tpl, $context); killme(); } - + return replace_macros($tpl, $context); - + } - - + + } diff --git a/Zotlabs/Module/Hcard.php b/Zotlabs/Module/Hcard.php index 912c84fd2..1cc26c199 100644 --- a/Zotlabs/Module/Hcard.php +++ b/Zotlabs/Module/Hcard.php @@ -5,7 +5,7 @@ namespace Zotlabs\Module; class Hcard extends \Zotlabs\Web\Controller { function init() { - + if(argc() > 1) $which = argv(1); else { @@ -13,12 +13,12 @@ class Hcard extends \Zotlabs\Web\Controller { \App::$error = 404; return; } - + logger('hcard_request: ' . $which, LOGGER_DEBUG); $profile = ''; $channel = \App::get_channel(); - + if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) { $which = $channel['channel_address']; $profile = argv(1); @@ -30,22 +30,22 @@ class Hcard extends \Zotlabs\Web\Controller { $profile = ''; $profile = $r[0]['profile_guid']; } - - head_add_link( [ - 'rel' => 'alternate', + + head_add_link( [ + 'rel' => 'alternate', 'type' => 'application/atom+xml', 'title' => t('Posts and comments'), 'href' => z_root() . '/feed/' . $which ]); - head_add_link( [ - 'rel' => 'alternate', + head_add_link( [ + 'rel' => 'alternate', 'type' => 'application/atom+xml', 'title' => t('Only posts'), 'href' => z_root() . '/feed/' . $which . '?f=&top=1' ]); - + if(! $profile) { $x = q("select channel_id as profile_uid from channel where channel_address = '%s' limit 1", dbesc(argv(1)) @@ -54,20 +54,20 @@ class Hcard extends \Zotlabs\Web\Controller { \App::$profile = $x[0]; } } - + profile_load($which,$profile); - - + + } - - + + function get() { - $x = new \Zotlabs\Widget\Profile(); + $x = new \Zotlabs\Widget\Fullprofile(); return $x->widget(array()); - + } - - - + + + } diff --git a/Zotlabs/Module/Home.php b/Zotlabs/Module/Home.php index 2bfab986f..315d05af6 100644 --- a/Zotlabs/Module/Home.php +++ b/Zotlabs/Module/Home.php @@ -40,7 +40,7 @@ class Home extends Controller { if (!$dest) $dest = get_config('system', 'startpage'); if (!$dest) - $dest = z_root() . '/network'; + $dest = z_root() . '/hq'; goaway($dest); } diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index a2c4100ad..5001bbe62 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -1,6 +1,10 @@ <?php namespace Zotlabs\Module; +use App; +use Zotlabs\Widget\Messages; + + require_once("include/bbcode.php"); require_once('include/security.php'); require_once('include/conversation.php'); @@ -14,61 +18,51 @@ class Hq extends \Zotlabs\Web\Controller { if(! local_channel()) return; - \App::$profile_uid = local_channel(); + App::$profile_uid = local_channel(); } - function post() { + function get($update = 0, $load = false) { - if(!local_channel()) + if(!local_channel()) { return; - - if($_REQUEST['notify_id']) { - q("update notify set seen = 1 where id = %d and uid = %d", - intval($_REQUEST['notify_id']), - intval(local_channel()) - ); } - killme(); + $item_hash = ''; - } + if(argc() > 1 && argv(1) !== 'load') { + $item_hash = unpack_link_id(argv(1)); + } - function get($update = 0, $load = false) { + if(isset($_REQUEST['mid'])) { + $item_hash = unpack_link_id($_REQUEST['mid']); + } - if(!local_channel()) + if($item_hash === false) { + notice(t('Malformed message id.') . EOL); return; - - if(argc() > 1 && argv(1) !== 'load') { - $item_hash = argv(1); } - if($_REQUEST['mid']) - $item_hash = $_REQUEST['mid']; - $item_normal = item_normal(); $item_normal_update = item_normal_update(); + $sys = get_sys_channel(); + $sys_item = false; + $sql_extra = ''; if(! $item_hash) { $r = q("SELECT mid FROM item WHERE uid = %d $item_normal AND mid = parent_mid + AND item_private IN (0, 1) ORDER BY created DESC LIMIT 1", intval(local_channel()) ); - if($r[0]['mid']) { - $item_hash = 'b64.' . base64url_encode($r[0]['mid']); + $item_hash = $r[0]['mid']; } } if($item_hash) { - if(strpos($item_hash,'b64.') === 0) - $decoded = @base64url_decode(substr($item_hash,4)); - - if($decoded) - $item_hash = $decoded; - $target_item = null; $r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid = '%s' limit 1", @@ -88,15 +82,10 @@ class Hq extends \Zotlabs\Web\Controller { 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']) . "' ) "; - $sys = get_sys_channel(); - $sql_extra = item_permissions_sql($sys['channel_id']); - - $sys_item = false; - } if(! $update) { - $channel = \App::get_channel(); + $channel = App::get_channel(); $channel_acl = [ 'allow_cid' => $channel['channel_allow_cid'], @@ -110,7 +99,7 @@ class Hq extends \Zotlabs\Web\Controller { 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), 'default_location' => $channel['channel_location'], 'nickname' => $channel['channel_address'], - 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), 'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'permissions' => $channel_acl, 'bang' => '', @@ -125,13 +114,8 @@ class Hq extends \Zotlabs\Web\Controller { 'reset' => t('Reset form') ]; - $o = replace_macros(get_markup_template("hq.tpl"), - [ - '$no_messages' => (($target_item) ? false : true), - '$no_messages_label' => [ t('Welcome to Hubzilla!'), t('You have got no unseen posts...') ], - '$editor' => status_editor($a,$x,false,'Hq') - ] - ); + $a = ''; + $o = status_editor($a, $x, true); } @@ -142,10 +126,9 @@ class Hq extends \Zotlabs\Web\Controller { if($target_item) { // if the target item is not a post (eg a like) we want to address its thread parent //$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']); - $mid = $target_item['mid']; + // if we got a decoded hash we must encode it again before handing to javascript - if($decoded) - $mid = 'b64.' . base64url_encode($mid); + $mid = gen_link_id($target_item['mid']); } else { $mid = ''; @@ -153,9 +136,9 @@ class Hq extends \Zotlabs\Web\Controller { $o .= '<div id="live-hq"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . local_channel() - . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . ";</script>\r\n"; + . "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . ";</script>\r\n"; - \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[ + App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[ '$baseurl' => z_root(), '$pgtype' => 'hq', '$uid' => local_channel(), @@ -201,6 +184,7 @@ class Hq extends \Zotlabs\Web\Controller { if(!$r) { $sys_item = true; + $sql_extra = item_permissions_sql($sys['channel_id']); $r = q("SELECT item.id AS item_id FROM item LEFT JOIN abook ON item.author_xchan = abook.abook_xchan @@ -227,6 +211,7 @@ class Hq extends \Zotlabs\Web\Controller { if(!$r) { $sys_item = true; + $sql_extra = item_permissions_sql($sys['channel_id']); $r = q("SELECT item.parent AS item_id FROM item LEFT JOIN abook ON item.author_xchan = abook.abook_xchan @@ -245,7 +230,7 @@ class Hq extends \Zotlabs\Web\Controller { if($r) { $items = q("SELECT item.*, item.id AS item_id FROM item - WHERE parent = '%s' $item_normal ", + WHERE parent = '%s' $item_normal $sql_extra", dbesc($r[0]['item_id']) ); @@ -267,4 +252,16 @@ class Hq extends \Zotlabs\Web\Controller { } + function post() { + if (!local_channel()) + return; + + $options['offset'] = $_REQUEST['offset']; + $options['type'] = $_REQUEST['type']; + + $ret = Messages::get_messages_page($options); + + json_return_and_die($ret); + } + } diff --git a/Zotlabs/Module/Impel.php b/Zotlabs/Module/Impel.php index e05027d9f..869de2669 100644 --- a/Zotlabs/Module/Impel.php +++ b/Zotlabs/Module/Impel.php @@ -1,5 +1,9 @@ <?php -namespace Zotlabs\Module; /** @file */ +namespace Zotlabs\Module; + +use URLify; + +/** @file */ // import page design element @@ -9,33 +13,33 @@ require_once('include/menu.php'); class Impel extends \Zotlabs\Web\Controller { function init() { - + $ret = array('success' => false); - + if(! local_channel()) json_return_and_die($ret); - + logger('impel: ' . print_r($_REQUEST,true), LOGGER_DATA); - + $elm = $_REQUEST['element']; $x = base64url_decode($elm); if(! $x) json_return_and_die($ret); - + $j = json_decode($x,true); if(! $j) json_return_and_die($ret); - + // logger('element: ' . print_r($j,true)); $channel = \App::get_channel(); - + $arr = array(); $is_menu = false; - + // a portable menu has its links rewritten with the local baseurl $portable_menu = false; - + switch($j['type']) { case 'webpage': $arr['item_type'] = ITEM_TYPE_WEBPAGE; @@ -58,12 +62,12 @@ class Impel extends \Zotlabs\Web\Controller { case 'menu': $is_menu = true; $installed_type = t('menu'); - break; + break; default: logger('mod_impel: unrecognised element type' . print_r($j,true)); break; } - + if($is_menu) { $m = array(); $m['menu_channel_id'] = local_channel(); @@ -73,23 +77,23 @@ class Impel extends \Zotlabs\Web\Controller { $m['menu_created'] = datetime_convert($j['created']); if($j['edited']) $m['menu_edited'] = datetime_convert($j['edited']); - + $m['menu_flags'] = 0; if($j['flags']) { if(in_array('bookmark',$j['flags'])) $m['menu_flags'] |= MENU_BOOKMARK; if(in_array('system',$j['flags'])) $m['menu_flags'] |= MENU_SYSTEM; - + } - + $menu_id = menu_create($m); - + if($menu_id) { if(is_array($j['items'])) { foreach($j['items'] as $it) { $mitem = array(); - + $mitem['mitem_link'] = str_replace('[channelurl]',z_root() . '/channel/' . $channel['channel_address'],$it['link']); $mitem['mitem_link'] = str_replace('[pageurl]',z_root() . '/page/' . $channel['channel_address'],$it['link']); $mitem['mitem_link'] = str_replace('[cloudurl]',z_root() . '/cloud/' . $channel['channel_address'],$it['link']); @@ -115,7 +119,7 @@ class Impel extends \Zotlabs\Web\Controller { intval(local_channel()) ); } - } + } $ret['success'] = true; } $x = $ret; @@ -132,22 +136,21 @@ class Impel extends \Zotlabs\Web\Controller { $arr['owner_xchan'] = get_observer_hash(); $arr['author_xchan'] = (($j['author_xchan']) ? $j['author_xchan'] : get_observer_hash()); $arr['mimetype'] = (($j['mimetype']) ? $j['mimetype'] : 'text/bbcode'); - + if(! $j['mid']) { $j['uuid'] = item_message_id(); $j['mid'] = z_root() . '/item/' . $j['uuid']; } $arr['uuid'] = $j['uuid']; $arr['mid'] = $arr['parent_mid'] = $j['mid']; - - + + if($j['pagetitle']) { - require_once('library/urlify/URLify.php'); - $pagetitle = strtolower(\URLify::transliterate($j['pagetitle'])); + $pagetitle = strtolower(URLify::transliterate($j['pagetitle'])); } - + // Verify ability to use html or php!!! - + $execflag = ((intval($channel['channel_id']) == intval(local_channel()) && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false); $i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1", @@ -156,7 +159,7 @@ class Impel extends \Zotlabs\Web\Controller { ); \Zotlabs\Lib\IConfig::Set($arr,'system',$namespace,(($pagetitle) ? $pagetitle : substr($arr['mid'],0,16)),true); - + if($i) { $arr['id'] = $i[0]['id']; // don't update if it has the same timestamp as the original @@ -174,24 +177,24 @@ class Impel extends \Zotlabs\Web\Controller { else $x = item_store($arr,$execflag); } - + if($x && $x['success']) { $item_id = $x['item_id']; } } - + if($x['success']) { $ret['success'] = true; - info( sprintf( t('%s element installed'), $installed_type)); + info( sprintf( t('%s element installed'), $installed_type)); } else { - notice( sprintf( t('%s element installation failed'), $installed_type)); + notice( sprintf( t('%s element installation failed'), $installed_type)); } - - //??? should perhaps return ret? + + //??? should perhaps return ret? json_return_and_die(true); - + } - + } diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php index 4622a588d..ec47e370b 100644 --- a/Zotlabs/Module/Import.php +++ b/Zotlabs/Module/Import.php @@ -2,14 +2,15 @@ namespace Zotlabs\Module; -require_once('include/zot.php'); require_once('include/channel.php'); require_once('include/import.php'); require_once('include/perm_upgrade.php'); -require_once('library/urlify/URLify.php'); -use Zotlabs\Lib\Crypto; +use App; +use URLify; +use Zotlabs\Daemon\Master; use Zotlabs\Lib\Libzot; +use Zotlabs\Web\Controller; /** @@ -18,7 +19,7 @@ use Zotlabs\Lib\Libzot; * Import a channel, either by direct file upload or via * connection to another server. */ -class Import extends \Zotlabs\Web\Controller { +class Import extends Controller { /** * @brief Import channel into account. @@ -27,95 +28,94 @@ class Import extends \Zotlabs\Web\Controller { */ function import_account($account_id) { - if(! $account_id){ + if (!$account_id) { logger('No account ID supplied'); return; } - $max_friends = account_service_class_fetch($account_id,'total_channels'); - $max_feeds = account_service_class_fetch($account_id,'total_feeds'); - $data = null; - $seize = ((x($_REQUEST,'make_primary')) ? intval($_REQUEST['make_primary']) : 0); - $import_posts = ((x($_REQUEST,'import_posts')) ? intval($_REQUEST['import_posts']) : 0); - $moving = intval($_REQUEST['moving']); - $src = $_FILES['filename']['tmp_name']; - $filename = basename($_FILES['filename']['name']); - $filesize = intval($_FILES['filename']['size']); - $filetype = $_FILES['filename']['type']; - $newname = trim(strtolower($_REQUEST['newname'])); + $max_friends = account_service_class_fetch($account_id, 'total_channels'); + $max_feeds = account_service_class_fetch($account_id, 'total_feeds'); + $data = null; + $seize = ((x($_REQUEST, 'make_primary')) ? intval($_REQUEST['make_primary']) : 0); + $import_posts = ((x($_REQUEST, 'import_posts')) ? intval($_REQUEST['import_posts']) : 0); + $moving = false; //intval($_REQUEST['moving']); + $src = $_FILES['filename']['tmp_name']; + $filename = basename($_FILES['filename']['name']); + $filesize = intval($_FILES['filename']['size']); + $filetype = $_FILES['filename']['type']; + $newname = trim(strtolower($_REQUEST['newname'])); // import channel from file - if($src) { + if ($src) { // This is OS specific and could also fail if your tmpdir isn't very // large mostly used for Diaspora which exports gzipped files. - if(strpos($filename,'.gz')){ - @rename($src,$src . '.gz'); + if (strpos($filename, '.gz')) { + @rename($src, $src . '.gz'); @system('gunzip ' . escapeshellarg($src . '.gz')); } - if($filesize) { + if ($filesize) { $data = @file_get_contents($src); } unlink($src); } // import channel from another server - if(! $src) { - $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : ''); - if(! $old_address) { + if (!$src) { + $old_address = ((x($_REQUEST, 'old_address')) ? $_REQUEST['old_address'] : ''); + if (!$old_address) { logger('Nothing to import.'); - notice( t('Nothing to import.') . EOL); + notice(t('Nothing to import.') . EOL); return; - } else if(strpos($old_address, 'ï¼ ')) { + } + else if (strpos($old_address, 'ï¼ ')) { // if you copy the identity address from your profile page, make it work for convenience - WARNING: this is a utf-8 variant and NOT an ASCII ampersand. Please do not edit. $old_address = str_replace('ï¼ ', '@', $old_address); } - $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : ''); - $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : ''); + $email = ((x($_REQUEST, 'email')) ? $_REQUEST['email'] : ''); + $password = ((x($_REQUEST, 'password')) ? $_REQUEST['password'] : ''); - $channelname = substr($old_address,0,strpos($old_address,'@')); - $servername = substr($old_address,strpos($old_address,'@')+1); + $channelname = substr($old_address, 0, strpos($old_address, '@')); + $servername = substr($old_address, strpos($old_address, '@') + 1); $api_path = probe_api_path($servername); - if(! $api_path) { - notice( t('Unable to download data from old server') . EOL); + if (!$api_path) { + notice(t('Unable to download data from old server') . EOL); return; } $api_path .= 'channel/export/basic?f=&channel=' . $channelname; - if($import_posts) - $api_path .= '&posts=1'; - $binary = false; + $binary = false; $redirects = 0; - $opts = array('http_auth' => $email . ':' . $password); - $ret = z_fetch_url($api_path, $binary, $redirects, $opts); - if($ret['success']) { + $opts = ['http_auth' => $email . ':' . $password]; + $ret = z_fetch_url($api_path, $binary, $redirects, $opts); + if ($ret['success']) { $data = $ret['body']; } else { - notice( t('Unable to download data from old server') . EOL); + notice(t('Unable to download data from old server') . EOL); return; } } - if(! $data) { + if (!$data) { logger('Empty import file.'); - notice( t('Imported file is empty.') . EOL); + notice(t('Imported file is empty.') . EOL); return; } - $data = json_decode($data,true); + $data = json_decode($data, true); //logger('import: data: ' . print_r($data,true)); //print_r($data); - if(! array_key_exists('compatibility',$data)) { - call_hooks('import_foreign_channel_data',$data); - if($data['handled']) + if (!array_key_exists('compatibility', $data)) { + call_hooks('import_foreign_channel_data', $data); + if ($data['handled']) return; } @@ -133,47 +133,47 @@ class Import extends \Zotlabs\Web\Controller { // prevent incompatible osada or zap data from horking your database - if(array_path_exists('compatibility/codebase',$data)) { + if (array_path_exists('compatibility/codebase', $data)) { notice('Data export format is not compatible with this software'); return; } - if(version_compare($data['compatibility']['version'], '4.7.3', '<=')) { + if (version_compare($data['compatibility']['version'], '4.7.3', '<=')) { // zot6 transition: cloning is not compatible with older versions notice('Data export format is not compatible with this software (not a zot6 channel)'); return; } - if($moving) + if ($moving) $seize = 1; // import channel - $relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null); + $relocate = ((array_key_exists('relocate', $data)) ? $data['relocate'] : null); - if(array_key_exists('channel',$data)) { + if (array_key_exists('channel', $data)) { - $max_identities = account_service_class_fetch($account_id,'total_identities'); + $max_identities = account_service_class_fetch($account_id, 'total_identities'); - if($max_identities !== false) { - $r = q("select channel_id from channel where channel_account_id = %d", + if ($max_identities !== false) { + $r = q("select channel_id from channel where channel_account_id = %d and channel_removed = 0", intval($account_id) ); - if($r && count($r) > $max_identities) { - notice( sprintf( t('Your service plan only allows %d channels.'), $max_identities) . EOL); + if ($r && count($r) > $max_identities) { + notice(sprintf(t('Your service plan only allows %d channels.'), $max_identities) . EOL); return; } } - if($newname) { - $x = false; + if ($newname) { + $x = false; - if(get_config('system','unicode_usernames')) { - $x = punify(mb_strtolower($newname)); - } + if (get_config('system', 'unicode_usernames')) { + $x = punify(mb_strtolower($newname)); + } - if((! $x) || strlen($x) > 64) { - $x = strtolower(\URLify::transliterate($newname)); + if ((!$x) || strlen($x) > 64) { + $x = strtolower(URLify::transliterate($newname)); } $newname = $x; } @@ -182,65 +182,38 @@ class Import extends \Zotlabs\Web\Controller { } else { $moving = false; - $channel = \App::get_channel(); + $channel = App::get_channel(); } - if(! $channel) { - logger('Channel not found. ', print_r($channel,true)); - notice( t('No channel. Import failed.') . EOL); + if (!$channel) { + logger('Channel not found. ', print_r($channel, true)); + notice(t('No channel. Import failed.') . EOL); return; } - if(is_array($data['config'])) { - import_config($channel,$data['config']); + if (is_array($data['config'])) { + import_config($channel, $data['config']); } logger('import step 2'); - if(array_key_exists('channel',$data)) { - if($data['photo']) { + if (array_key_exists('channel', $data)) { + if ($data['photo']) { require_once('include/photo/photo_driver.php'); - import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']); + import_channel_photo(base64url_decode($data['photo']['data']), $data['photo']['type'], $account_id, $channel['channel_id']); } - if(is_array($data['profile'])) - import_profiles($channel,$data['profile']); + if (is_array($data['profile'])) + import_profiles($channel, $data['profile']); } logger('import step 3'); // create new hubloc for the new channel at this site - if(array_key_exists('channel',$data)) { - if($channel['channel_portable_id']) { - $r = hubloc_store_lowlevel( - [ - 'hubloc_guid' => $channel['channel_guid'], - 'hubloc_guid_sig' => $channel['channel_guid_sig'], - 'hubloc_hash' => $channel['channel_portable_id'], - 'hubloc_addr' => channel_reddress($channel), - 'hubloc_network' => 'zot', - 'hubloc_primary' => (($seize) ? 1 : 0), - 'hubloc_url' => z_root(), - 'hubloc_url_sig' => base64url_encode(Crypto::sign(z_root(),$channel['channel_prvkey'])), - 'hubloc_host' => \App::get_hostname(), - 'hubloc_callback' => z_root() . '/post', - 'hubloc_sitekey' => get_config('system','pubkey'), - 'hubloc_updated' => datetime_convert(), - 'hubloc_id_url' => channel_url($channel) - ] - ); - - // reset the original primary hubloc if it is being seized - if($seize) { - $r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ", - dbesc($channel['channel_portable_id']), - dbesc(z_root()) - ); - } - } + if (array_key_exists('channel', $data)) { - // create a new zot6 hubloc if we have got a channel_portable_id + // create a new zot6 hubloc $r = hubloc_store_lowlevel( [ @@ -251,18 +224,18 @@ class Import extends \Zotlabs\Web\Controller { 'hubloc_network' => 'zot6', 'hubloc_primary' => (($seize) ? 1 : 0), 'hubloc_url' => z_root(), - 'hubloc_url_sig' => 'sha256.' . base64url_encode(Crypto::sign(z_root(),$channel['channel_prvkey'])), - 'hubloc_host' => \App::get_hostname(), + 'hubloc_url_sig' => Libzot::sign(z_root(), $channel['channel_prvkey']), + 'hubloc_host' => App::get_hostname(), 'hubloc_callback' => z_root() . '/zot', - 'hubloc_sitekey' => get_config('system','pubkey'), + 'hubloc_sitekey' => get_config('system', 'pubkey'), 'hubloc_updated' => datetime_convert(), 'hubloc_id_url' => channel_url($channel), - 'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey')) + 'hubloc_site_id' => Libzot::make_xchan_hash(z_root(), get_config('system', 'pubkey')) ] ); // reset the original primary hubloc if it is being seized - if($seize) { + if ($seize) { $r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ", dbesc($channel['channel_hash']), dbesc(z_root()) @@ -273,57 +246,33 @@ class Import extends \Zotlabs\Web\Controller { logger('import step 4'); - // import xchans and contact photos - if(array_key_exists('channel',$data) && $seize) { + if (array_key_exists('channel', $data) && $seize) { // replace any existing xchan we may have on this site if we're seizing control - $r = q("delete from xchan where ( xchan_hash = '%s' or xchan_hash = '%s' ) ", - dbesc($channel['channel_hash']), - dbesc($channel['channel_portable_id']) + $r = q("delete from xchan where xchan_hash = '%s'", + dbesc($channel['channel_hash']) ); - if($channel['channel_portable_id']) { - $r = xchan_store_lowlevel( - [ - 'xchan_hash' => $channel['channel_portable_id'], - 'xchan_guid' => $channel['channel_guid'], - 'xchan_guid_sig' => $channel['channel_guid_sig'], - 'xchan_pubkey' => $channel['channel_pubkey'], - 'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'], - 'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'], - 'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'], - 'xchan_addr' => channel_reddress($channel), - 'xchan_url' => z_root() . '/channel/' . $channel['channel_address'], - 'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'], - 'xchan_follow' => z_root() . '/follow?f=&url=%s', - 'xchan_name' => $channel['channel_name'], - 'xchan_network' => 'zot', - 'xchan_photo_date' => datetime_convert(), - 'xchan_name_date' => datetime_convert() - ] - ); - } - $r = xchan_store_lowlevel( [ - 'xchan_hash' => $channel['channel_hash'], - 'xchan_guid' => $channel['channel_guid'], - 'xchan_guid_sig' => $channel['channel_guid_sig'], - 'xchan_pubkey' => $channel['channel_pubkey'], - 'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'], - 'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'], - 'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'], - 'xchan_addr' => channel_reddress($channel), - 'xchan_url' => z_root() . '/channel/' . $channel['channel_address'], - 'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'], - 'xchan_follow' => z_root() . '/follow?f=&url=%s', - 'xchan_name' => $channel['channel_name'], - 'xchan_network' => 'zot6', - 'xchan_photo_date' => datetime_convert(), - 'xchan_name_date' => datetime_convert() + 'xchan_hash' => $channel['channel_hash'], + 'xchan_guid' => $channel['channel_guid'], + 'xchan_guid_sig' => $channel['channel_guid_sig'], + 'xchan_pubkey' => $channel['channel_pubkey'], + 'xchan_photo_l' => z_root() . "/photo/profile/l/" . $channel['channel_id'], + 'xchan_photo_m' => z_root() . "/photo/profile/m/" . $channel['channel_id'], + 'xchan_photo_s' => z_root() . "/photo/profile/s/" . $channel['channel_id'], + 'xchan_addr' => channel_reddress($channel), + 'xchan_url' => z_root() . '/channel/' . $channel['channel_address'], + 'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'], + 'xchan_follow' => z_root() . '/follow?f=&url=%s', + 'xchan_name' => $channel['channel_name'], + 'xchan_network' => 'zot6', + 'xchan_photo_date' => datetime_convert(), + 'xchan_name_date' => datetime_convert() ] ); @@ -333,26 +282,18 @@ class Import extends \Zotlabs\Web\Controller { // import xchans $xchans = $data['xchan']; - if($xchans) { - foreach($xchans as $xchan) { - - if($xchan['xchan_network'] === 'zot') { - $hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']); - if($hash !== $xchan['xchan_hash']) { - logger('forged xchan: ' . print_r($xchan,true)); - continue; - } - } + if ($xchans) { + foreach ($xchans as $xchan) { - if($xchan['xchan_network'] === 'zot6') { - $zhash = Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']); - if($zhash !== $xchan['xchan_hash']) { - logger('forged xchan: ' . print_r($xchan,true)); + if ($xchan['xchan_network'] === 'zot6') { + $zhash = Libzot::make_xchan_hash($xchan['xchan_guid'], $xchan['xchan_pubkey']); + if ($zhash !== $xchan['xchan_hash']) { + logger('forged xchan: ' . print_r($xchan, true)); continue; } } - if(! array_key_exists('xchan_hidden',$xchan)) { + if (!array_key_exists('xchan_hidden', $xchan)) { $xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0); $xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0); $xchan['xchan_censored'] = (($xchan['xchan_flags'] & 0x0004) ? 1 : 0); @@ -365,14 +306,14 @@ class Import extends \Zotlabs\Web\Controller { $r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1", dbesc($xchan['xchan_hash']) ); - if($r) + if ($r) continue; - create_table_from_array('xchan',$xchan); + create_table_from_array('xchan', $xchan); require_once('include/photo/photo_driver.php'); - if($xchan['xchan_hash'] === $channel['channel_hash']) { + if ($xchan['xchan_hash'] === $channel['channel_hash']) { $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'", dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']), dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']), @@ -381,13 +322,13 @@ class Import extends \Zotlabs\Web\Controller { ); } else { - $photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']); - if($photos[4]) + $photos = import_xchan_photo($xchan['xchan_photo_l'], $xchan['xchan_hash']); + if ($photos[4]) $photodate = NULL_DATE; else $photodate = $xchan['xchan_photo_date']; - $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'", + q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), @@ -404,22 +345,22 @@ class Import extends \Zotlabs\Web\Controller { logger('import step 7'); // this must happen after xchans got imported! - if(is_array($data['hubloc'])) { - import_hublocs($channel,$data['hubloc'],$seize,$moving); + if (is_array($data['hubloc'])) { + import_hublocs($channel, $data['hubloc'], $seize, $moving); } $friends = 0; - $feeds = 0; + $feeds = 0; // import contacts $abooks = $data['abook']; - if($abooks) { - foreach($abooks as $abook) { + if ($abooks) { + foreach ($abooks as $abook) { $abook_copy = $abook; $abconfig = null; - if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig'])) + if (array_key_exists('abconfig', $abook) && is_array($abook['abconfig']) && count($abook['abconfig'])) $abconfig = $abook['abconfig']; unset($abook['abook_id']); @@ -432,33 +373,33 @@ class Import extends \Zotlabs\Web\Controller { $abook['abook_account'] = $account_id; $abook['abook_channel'] = $channel['channel_id']; - if(! array_key_exists('abook_blocked',$abook)) { - $abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001 ) ? 1 : 0); - $abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002 ) ? 1 : 0); - $abook['abook_hidden'] = (($abook['abook_flags'] & 0x0004 ) ? 1 : 0); - $abook['abook_archived'] = (($abook['abook_flags'] & 0x0008 ) ? 1 : 0); - $abook['abook_pending'] = (($abook['abook_flags'] & 0x0010 ) ? 1 : 0); - $abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020 ) ? 1 : 0); - $abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0); - $abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0); + if (!array_key_exists('abook_blocked', $abook)) { + $abook['abook_blocked'] = (($abook['abook_flags'] & 0x0001) ? 1 : 0); + $abook['abook_ignored'] = (($abook['abook_flags'] & 0x0002) ? 1 : 0); + $abook['abook_hidden'] = (($abook['abook_flags'] & 0x0004) ? 1 : 0); + $abook['abook_archived'] = (($abook['abook_flags'] & 0x0008) ? 1 : 0); + $abook['abook_pending'] = (($abook['abook_flags'] & 0x0010) ? 1 : 0); + $abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020) ? 1 : 0); + $abook['abook_self'] = (($abook['abook_flags'] & 0x0080) ? 1 : 0); + $abook['abook_feed'] = (($abook['abook_flags'] & 0x0100) ? 1 : 0); } - if(array_key_exists('abook_instance',$abook) && $abook['abook_instance'] && strpos($abook['abook_instance'],z_root()) === false) { + if (array_key_exists('abook_instance', $abook) && $abook['abook_instance'] && strpos($abook['abook_instance'], z_root()) === false) { $abook['abook_not_here'] = 1; } - if($abook['abook_self']) { - $role = get_pconfig($channel['channel_id'],'system','permissions_role'); - if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) { + if ($abook['abook_self']) { + $role = get_pconfig($channel['channel_id'], 'system', 'permissions_role'); + if (($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) { q("update xchan set xchan_pubforum = 1 where xchan_hash = '%s' ", dbesc($abook['abook_xchan']) ); } } else { - if($max_friends !== false && $friends > $max_friends) + if ($max_friends !== false && $friends > $max_friends) continue; - if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds)) + if ($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds)) continue; } @@ -466,9 +407,9 @@ class Import extends \Zotlabs\Web\Controller { dbesc($abook['abook_xchan']), intval($channel['channel_id']) ); - if($r) { - foreach($abook as $k => $v) { - $r = q("UPDATE abook SET " . TQUOT . "%s" . TQUOT . " = '%s' WHERE abook_xchan = '%s' AND abook_channel = %d", + if ($r) { + foreach ($abook as $k => $v) { + q("UPDATE abook SET " . TQUOT . "%s" . TQUOT . " = '%s' WHERE abook_xchan = '%s' AND abook_channel = %d", dbesc($k), dbesc($v), dbesc($abook['abook_xchan']), @@ -479,17 +420,17 @@ class Import extends \Zotlabs\Web\Controller { else { abook_store_lowlevel($abook); - $friends ++; - if(intval($abook['abook_feed'])) - $feeds ++; + $friends++; + if (intval($abook['abook_feed'])) + $feeds++; } - translate_abook_perms_inbound($channel,$abook_copy); + translate_abook_perms_inbound($channel, $abook_copy); - if($abconfig) { + if ($abconfig) { /// @FIXME does not handle sync of del_abconfig - foreach($abconfig as $abc) { - set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']); + foreach ($abconfig as $abc) { + set_abconfig($channel['channel_id'], $abc['xchan'], $abc['cat'], $abc['k'], $abc['v']); } } } @@ -497,13 +438,14 @@ class Import extends \Zotlabs\Web\Controller { logger('import step 8'); } + // import groups $groups = $data['group']; - if($groups) { - $saved = array(); - foreach($groups as $group) { - $saved[$group['hash']] = array('old' => $group['id']); - if(array_key_exists('name', $group)) { + if ($groups) { + $saved = []; + foreach ($groups as $group) { + $saved[$group['hash']] = ['old' => $group['id']]; + if (array_key_exists('name', $group)) { $group['gname'] = $group['name']; unset($group['name']); } @@ -515,8 +457,8 @@ class Import extends \Zotlabs\Web\Controller { $r = q("select * from pgrp where uid = %d", intval($channel['channel_id']) ); - if($r) { - foreach($r as $rr) { + if ($r) { + foreach ($r as $rr) { $saved[$rr['hash']]['new'] = $rr['id']; } } @@ -524,12 +466,12 @@ class Import extends \Zotlabs\Web\Controller { // import group members $group_members = $data['group_member']; - if($group_members) { - foreach($group_members as $group_member) { + if ($group_members) { + foreach ($group_members as $group_member) { unset($group_member['id']); $group_member['uid'] = $channel['channel_id']; - foreach($saved as $x) { - if($x['old'] == $group_member['gid']) + foreach ($saved as $x) { + if ($x['old'] == $group_member['gid']) $group_member['gid'] = $x['new']; } create_table_from_array('pgrp_member', $group_member); @@ -538,65 +480,85 @@ class Import extends \Zotlabs\Web\Controller { logger('import step 9'); - if(is_array($data['obj'])) - import_objs($channel,$data['obj']); - if(is_array($data['likes'])) - import_likes($channel,$data['likes']); + if (is_array($data['obj'])) + import_objs($channel, $data['obj']); - if(is_array($data['app'])) - import_apps($channel,$data['app']); + if (is_array($data['likes'])) + import_likes($channel, $data['likes']); - if(is_array($data['sysapp'])) - import_sysapps($channel,$data['sysapp']); + if (is_array($data['app'])) + import_apps($channel, $data['app']); - if(is_array($data['chatroom'])) - import_chatrooms($channel,$data['chatroom']); + if (is_array($data['sysapp'])) + import_sysapps($channel, $data['sysapp']); - if(is_array($data['conv'])) - import_conv($channel,$data['conv']); + if (is_array($data['chatroom'])) + import_chatrooms($channel, $data['chatroom']); - if(is_array($data['mail'])) - import_mail($channel,$data['mail']); + if (is_array($data['event'])) + import_events($channel, $data['event']); - if(is_array($data['event'])) - import_events($channel,$data['event']); + if (is_array($data['event_item'])) + import_items($channel, $data['event_item'], false, $relocate); - if(is_array($data['event_item'])) - import_items($channel,$data['event_item'],false,$relocate); + if (is_array($data['menu'])) + import_menus($channel, $data['menu']); - if(is_array($data['menu'])) - import_menus($channel,$data['menu']); + if (is_array($data['wiki'])) + import_items($channel, $data['wiki'], false, $relocate); - if(is_array($data['wiki'])) - import_items($channel,$data['wiki'],false,$relocate); + if (is_array($data['webpages'])) + import_items($channel, $data['webpages'], false, $relocate); - if(is_array($data['webpages'])) - import_items($channel,$data['webpages'],false,$relocate); + $addon = ['channel' => $channel, 'data' => $data]; + call_hooks('import_channel', $addon); - $addon = array('channel' => $channel,'data' => $data); - call_hooks('import_channel',$addon); + if ($import_posts && array_key_exists('item', $data) && $data['item']) { + import_items($channel, $data['item'], false, $relocate); + } - $saved_notification_flags = notifications_off($channel['channel_id']); + // Immediately notify old server about the new clone + Master::Summon(['Notifier', 'refresh_all', $channel['channel_id']]); - if($import_posts && array_key_exists('item',$data) && $data['item']) - import_items($channel,$data['item'],false,$relocate); + // This will indirectly perform a refresh_all *and* update the directory + Master::Summon(['Directory', $channel['channel_id']]); - notifications_on($channel['channel_id'],$saved_notification_flags); + $cf_api_compat = true; - if(array_key_exists('item_id',$data) && $data['item_id']) - import_item_ids($channel,$data['item_id']); + if ($api_path && $import_posts) { // we are importing from a server and not a file + if (version_compare($data['compatibility']['version'], '6.3.4', '>=')) { - // This will indirectly perform a refresh_all *and* update the directory + $m = parse_url($api_path); - \Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id'])); + $hz_server = $m['scheme'] . '://' . $m['host']; + $since = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), '0001-01-01 00:00'); + $until = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), 'now + 1 day'); - notice( t('Import completed.') . EOL); + $poll_interval = get_config('system', 'poll_interval', 3); + $page = 0; + + Master::Summon(['Content_importer', sprintf('%d', $page), $since, $until, $channel['channel_address'], urlencode($hz_server)]); + Master::Summon(['File_importer', sprintf('%d', $page), $channel['channel_address'], urlencode($hz_server)]); + } + else { + $cf_api_compat = false; + } + } change_channel($channel['channel_id']); - goaway(z_root() . '/network' ); + if ($api_path && $import_posts && $cf_api_compat) { + goaway(z_root() . '/import_progress'); + } + + if (!$cf_api_compat) { + notice(t('Automatic content and files import was not possible due to API version incompatiblity. Please import content and files manually!') . EOL); + } + + goaway(z_root()); + } /** @@ -604,7 +566,7 @@ class Import extends \Zotlabs\Web\Controller { */ function post() { $account_id = get_account_id(); - if(! $account_id) + if (!$account_id) return; check_form_security_token_redirectOnErr('/import', 'channel_import'); @@ -619,33 +581,35 @@ class Import extends \Zotlabs\Web\Controller { */ function get() { - if(! get_account_id()) { - notice( t('You must be logged in to use this feature.') . EOL); + if (!get_account_id()) { + notice(t('You must be logged in to use this feature.') . EOL); return ''; } - $o = replace_macros(get_markup_template('channel_import.tpl'),array( - '$title' => t('Import Channel'), - '$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'), + nav_set_selected('Channel Import'); + + $o = replace_macros(get_markup_template('channel_import.tpl'), [ + '$title' => t('Channel Import'), + '$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'), '$label_filename' => t('File to Upload'), - '$choice' => t('Or provide the old server/hub details'), + '$choice' => t('Or provide the old server/hub details'), - '$old_address' => [ 'old_address', t('Your old identity address (xyz@example.com)'), '', ''], - '$email' => [ 'email', t('Your old login email address'), '', '' ], - '$password' => [ 'password', t('Your old login password'), '', '' ], - '$import_posts' => [ 'import_posts', t('Import a few months of posts if possible (limited by available memory'), false, '', [ t('No'), t('Yes') ]], + '$old_address' => ['old_address', t('Your old identity address (xyz@example.com)'), '', ''], + '$email' => ['email', t('Your old login email address'), '', ''], + '$password' => ['password', t('Your old login password'), '', ''], + '$import_posts' => ['import_posts', t('Import your items and files (limited by available memory)'), false, '', [t('No'), t('Yes')]], '$common' => t('For either option, please choose whether to make this hub your new primary address, or whether your old location should continue this role. You will be able to post from either location, but only one can be marked as the primary location for files, photos, and media.'), - '$make_primary' => [ 'make_primary', t('Make this hub my primary location'), false, '', [ t('No'), t('Yes') ] ], - '$moving' => [ 'moving', t('Move this channel (disable all previous locations)'), false, '', [ t('No'), t('Yes') ] ], - '$newname' => [ 'newname', t('Use this channel nickname instead of the one provided'), '', t('Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site.')], + '$make_primary' => ['make_primary', t('Make this hub my primary location'), false, '', [t('No'), t('Yes')]], + '$moving' => ['moving', t('Move this channel (disable all previous locations)'), false, '', [t('No'), t('Yes')]], + '$newname' => ['newname', t('Use this channel nickname instead of the one provided'), '', t('Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site.')], '$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'), '$form_security_token' => get_form_security_token('channel_import'), - '$submit' => t('Submit') - )); + '$submit' => t('Submit') + ]); return $o; } diff --git a/Zotlabs/Module/Import_items.php b/Zotlabs/Module/Import_items.php index c2b2506fe..1a1e8d061 100644 --- a/Zotlabs/Module/Import_items.php +++ b/Zotlabs/Module/Import_items.php @@ -1,6 +1,11 @@ <?php + namespace Zotlabs\Module; +use App; +use ZipArchive; +use Zotlabs\Web\Controller; + require_once('include/import.php'); /** @@ -8,128 +13,184 @@ require_once('include/import.php'); * * Import existing posts and content from an export file. */ -class Import_items extends \Zotlabs\Web\Controller { +class Import_items extends Controller { function post() { - if(! local_channel()) + if (!local_channel()) return; check_form_security_token_redirectOnErr('/import_items', 'import_items'); - $data = null; + $data = null; $src = $_FILES['filename']['tmp_name']; $filename = basename($_FILES['filename']['name']); $filesize = intval($_FILES['filename']['size']); $filetype = $_FILES['filename']['type']; - if($src) { + $channel = App::get_channel(); + + if ($src) { + + if ($filetype === 'application/zip') { + $zip = new ZipArchive; + + $r = $zip->open($src); + if ($r === true) { + for ($i = 0; $i < $zip->count(); $i++) { + $data = $zip->getFromIndex($i); + self::import($channel, $data); + } + $zip->close(); + unlink($src); + return; + } + + notice(t('Not a zip file or zip file corrupted.') . EOL); + unlink($src); + return; + } + // This is OS specific and could also fail if your tmpdir isn't very large // mostly used for Diaspora which exports gzipped files. - if(strpos($filename,'.gz')){ - @rename($src,$src . '.gz'); - @system('gunzip ' . escapeshellarg($src . '.gz')); - } + //if(strpos($filename,'.gz')){ + //@rename($src,$src . '.gz'); + //@system('gunzip ' . escapeshellarg($src . '.gz')); + //} - if($filesize) { + if ($filesize) { $data = @file_get_contents($src); + self::import($channel, $data); } unlink($src); + return; } + /* + if(! $src) { + + $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : ''); + + if(! $old_address) { + logger('Nothing to import.'); + notice( t('Nothing to import.') . EOL); + return; + } + + $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : ''); + $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : ''); + + $year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : ''); + + $channelname = substr($old_address,0,strpos($old_address,'@')); + $servername = substr($old_address,strpos($old_address,'@')+1); + + $scheme = 'https://'; + $api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year); + $binary = false; + $redirects = 0; + $opts = array('http_auth' => $email . ':' . $password); + $url = $scheme . $servername . $api_path; + $ret = z_fetch_url($url, $binary, $redirects, $opts); + if(! $ret['success']) + $ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts); + if($ret['success']) + $data = $ret['body']; + else + notice( t('Unable to download data from old server') . EOL); + } + */ - if(! $src) { + } - $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : ''); - if(! $old_address) { - logger('Nothing to import.'); - notice( t('Nothing to import.') . EOL); - return; - } + /** + * @brief Generate item import page. + * + * @return string with parsed HTML. + */ + function get() { - $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : ''); - $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : ''); - - $year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : ''); - - $channelname = substr($old_address,0,strpos($old_address,'@')); - $servername = substr($old_address,strpos($old_address,'@')+1); - - $scheme = 'https://'; - $api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year); - $binary = false; - $redirects = 0; - $opts = array('http_auth' => $email . ':' . $password); - $url = $scheme . $servername . $api_path; - $ret = z_fetch_url($url, $binary, $redirects, $opts); - if(! $ret['success']) - $ret = z_fetch_url('http://' . $servername . $api_path, $binary, $redirects, $opts); - if($ret['success']) - $data = $ret['body']; - else - notice( t('Unable to download data from old server') . EOL); + if (!local_channel()) { + notice(t('Permission denied') . EOL); + return login(); } - if(! $data) { + $o = replace_macros(get_markup_template('item_import.tpl'), [ + '$title' => t('Import Items'), + '$desc' => t('Use this form to import existing posts and content from an export file.'), + '$label_filename' => t('File to Upload'), + '$form_security_token' => get_form_security_token('import_items'), + '$submit' => t('Submit') + ]); + + return $o; + } + + + public static function import($channel, $data) { + + if (!$data) { logger('Empty file.'); - notice( t('Imported file is empty.') . EOL); + notice(t('Imported file is empty.') . EOL); return; } $data = json_decode($data, true); - //logger('import: data: ' . print_r($data,true)); //print_r($data); - if(! is_array($data)) + if (!is_array($data)) { return; + } - if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) { - $v1 = substr($data['compatibility']['database'],-4); - $v2 = substr(DB_UPDATE_VERSION,-4); - if($v2 > $v1) { - $t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 ); - notice($t . EOL); - } + //if (array_key_exists('compatibility', $data) && array_key_exists('database', $data['compatibility'])) { + //$v1 = substr($data['compatibility']['database'], -4); + //$v2 = substr(DB_UPDATE_VERSION, -4); + //if ($v2 > $v1) { + //$t = sprintf(t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1); + //notice($t . EOL); + //} + //} + + if (array_key_exists('item', $data) && is_array($data['item'])) { + import_items($channel, $data['item'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null)); + info(t('Content import completed') . EOL); } - $channel = \App::get_channel(); + if (array_key_exists('chatroom', $data) && is_array($data['chatroom'])) { + import_chatrooms($channel, $data['chatroom']); + info(t('Chatroom import completed') . EOL); - if(array_key_exists('item',$data) && $data['item']) { - import_items($channel,$data['item'],false,((array_key_exists('relocate',$data)) ? $data['relocate'] : null)); } - if(array_key_exists('item_id',$data) && $data['item_id']) { - import_item_ids($channel,$data['item_id']); - } + if (array_key_exists('event', $data) && is_array($data['event'])) { + import_events($channel, $data['event']); + info(t('Channel calendar import 1/2 completed') . EOL); - info( t('Import completed') . EOL); - } + } + if (array_key_exists('event_item', $data) && is_array($data['event_item'])) { + import_items($channel, $data['event_item'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null)); + info(t('Channel calendar import 2/2 completed') . EOL); + } - /** - * @brief Generate item import page. - * - * @return string with parsed HTML. - */ - function get() { + if (array_key_exists('menu', $data) && is_array($data['menu'])) { + import_menus($channel, $data['menu']); + info(t('Menu import completed') . EOL); + } - if(! local_channel()) { - notice( t('Permission denied') . EOL); - return login(); + if (array_key_exists('wiki', $data) && is_array($data['wiki'])) { + import_items($channel, $data['wiki'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null)); + info(t('Wiki import completed') . EOL); } - $o = replace_macros(get_markup_template('item_import.tpl'), array( - '$title' => t('Import Items'), - '$desc' => t('Use this form to import existing posts and content from an export file.'), - '$label_filename' => t('File to Upload'), - '$form_security_token' => get_form_security_token('import_items'), - '$submit' => t('Submit') - )); + if (array_key_exists('webpages', $data) && is_array($data['webpages'])) { + import_items($channel, $data['webpages'], false, ((array_key_exists('relocate', $data)) ? $data['relocate'] : null)); + info(t('Webpages import completed') . EOL); + } - return $o; } } diff --git a/Zotlabs/Module/Import_progress.php b/Zotlabs/Module/Import_progress.php new file mode 100644 index 000000000..761d2f215 --- /dev/null +++ b/Zotlabs/Module/Import_progress.php @@ -0,0 +1,122 @@ +<?php +namespace Zotlabs\Module; + +use Zotlabs\Lib\PConfig; +use Zotlabs\Daemon\Master; + +class Import_progress extends \Zotlabs\Web\Controller { + + function post() { + + if(! local_channel()) + return; + + } + + function get() { + + if(! local_channel()) { + return; + } + + nav_set_selected('Channel Import'); + + // items + $c = PConfig::Get(local_channel(), 'import', 'content_progress'); + + if ($c) { + $total_cpages = floor(intval($c['items_total']) / intval($c['items_page'])); + if(!$total_cpages) { + $total_cpages = 1; // because of floor + } + + $cpage = $c['last_page'] + 1; // because page count start at 0 + + $cprogress = intval(floor((intval($cpage) * 100) / $total_cpages)); + $ccompleted_str = t('Item sync completed!'); + + if(argv(1) === 'resume_itemsync' && $cprogress < 100) { + Master::Summon($c['next_cmd']); + goaway('/import_progress'); + } + } + else { + $cprogress = 'waiting to start...'; + + if (PConfig::Get(local_channel(), 'import', 'content_completed')) { + // There was nothing todo. Fake 100% and mention that there were no files found + $cprogress = 100; + } + + $ccompleted_str = t('Item sync completed but no items were found!'); + + if(argv(1) === 'resume_itemsync') { + Master::Summon(["Content_importer","0","0001-01-01 00:00:00","2021-10-02 19:49:14","ct5","https%3A%2F%2Fhub.somaton.com"]); + goaway('/import_progress'); + } + } + + $cprogress_str = ((intval($cprogress)) ? $cprogress . '%' : $cprogress); + + // files + $f = PConfig::Get(local_channel(), 'import', 'files_progress'); + + if ($f) { + $total_fpages = floor(intval($f['files_total']) / intval($f['files_page'])); + if(!$total_fpages) { + $total_fpages = 1; + } + + $fpage = $f['last_page'] + 1; + + $fprogress = intval(floor((intval($fpage) * 100) / $total_fpages)); + $fcompleted_str = t('File sync completed!'); + + if(argv(1) === 'resume_filesync' && $fprogress < 100) { + Master::Summon($f['next_cmd']); + goaway('/import_progress'); + } + + + } + else { + $fprogress = 'waiting to start...'; + + if (PConfig::Get(local_channel(), 'import', 'files_completed')) { + // There was nothing todo. Fake 100% and mention that there were no files found + $fprogress = 100; + } + + $fcompleted_str = t('File sync completed but no files were found!'); + } + + $fprogress_str = ((intval($fprogress)) ? $fprogress . '%' : $fprogress); + + if(is_ajax()) { + $ret = [ + 'cprogress' => $cprogress, + 'fprogress' => $fprogress + ]; + + json_return_and_die($ret); + } + + $o = replace_macros(get_markup_template("import_progress.tpl"), [ + '$chtitle_str' => t('Channel clone status'), + '$ctitle_str' => t('Item sync status'), + '$ftitle_str' => t('File sync status'), + '$cprogress_str' => $cprogress_str, + '$cprogress' => intval($cprogress), + '$fprogress_str' => $fprogress_str, + '$fprogress' => intval($fprogress), + '$fcompleted_str' => $fcompleted_str, + '$ccompleted_str' => $ccompleted_str, + '$chcompleted_str' => t('Channel cloning completed!'), + '$resume_str' => t('Resume'), + '$resume_helper_str' => t('Only resume if sync stalled!') + ]); + + return $o; + } + +} diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php index 34f1858fd..2a126ac27 100644 --- a/Zotlabs/Module/Invite.php +++ b/Zotlabs/Module/Invite.php @@ -129,11 +129,11 @@ class Invite extends Controller { if(! $recip) continue; // see if we have an email address who@domain.tld - if (!preg_match('/^.{2,64}\@[a-z0-9.-]{4,32}\.[a-z]{2,12}$/', $recip)) { - $feedbk .= 'ZAI0203E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a valid email address'), $recip) . $eol; - $ko++; - continue; - } + //if (!preg_match('/^.{2,64}\@[a-z0-9.-]{2,32}\.[a-z]{2,12}$/', $recip)) { + //$feedbk .= 'ZAI0203E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a valid email address'), $recip) . $eol; + //$ko++; + //continue; + //} if(! validate_email($recip)) { $feedbk .= 'ZAI0204E ' . ($n+1) . ': ' . sprintf( t('(%s) : Not a real email address'), $recip) . $eol; $ko++; @@ -225,7 +225,7 @@ class Invite extends Controller { '$projectname' => t('$Projectname'), '$invite_code' => $invite_code, '$invite_where' => z_root() . '/register', - '$invite_whereami' => str_replace('@', '@+', $reonar['whereami']), + '$invite_whereami' => $reonar['whereami'], '$invite_whoami' => z_root() . '/channel/' . $reonar['whoami'], '$invite_anywhere' => z_root() . '/pubsites' ) @@ -306,9 +306,8 @@ class Invite extends Controller { if(! Apps::system_app_installed(local_channel(), 'Invite')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = 'ZAI0102E,' . t('Invite App') . ' (' . t('Not Installed') . ')' . EOL; - return $o; + $papp = Apps::get_papp('Invite'); + return Apps::app_render($papp, 'module'); } if (! (get_config('system','invitation_also') || get_config('system','invitation_only')) ) { @@ -423,8 +422,6 @@ class Invite extends Controller { // let take one descriptive for template (as said is never used) $invite_code = 'INVITATE2020'; - // what languages we use now - $lccmy = ((isset(App::$config['system']['language'])) ? App::$config['system']['language'] : 'en'); // and all the localized templates belonging to invite $tpls = glob('view/*/invite.*.tpl'); @@ -445,6 +442,9 @@ class Invite extends Controller { $langs = array_keys($tpla); asort($langs); + // Use the current language if we have a template for it. Otherwise fall back to 'en'. + $lccmy = ((in_array(App::$language, $langs)) ? App::$language : 'en'); + $tplx = array_unique($tplx); asort($tplx); diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 73a943039..574a90c1a 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module; +use App; +use URLify; use Zotlabs\Lib\Config; use Zotlabs\Lib\IConfig; use Zotlabs\Lib\Enotify; @@ -15,7 +17,6 @@ use Zotlabs\Lib\Libzot; use Zotlabs\Lib\Libsync; use Zotlabs\Lib\ThreadListener; use Zotlabs\Access\PermissionRoles; -use App; require_once('include/crypto.php'); require_once('include/items.php'); @@ -37,8 +38,6 @@ require_once('include/conversation.php'); * posting categories go through item_store() instead of this function. * */ - - class Item extends Controller { @@ -46,11 +45,9 @@ class Item extends Controller { if (Libzot::is_zot_request()) { - $conversation = false; - $item_id = argv(1); - if(! $item_id) + if (!$item_id) http_status_exit(404, 'Not found'); $portable_id = EMPTY_STR; @@ -70,8 +67,8 @@ class Item extends Controller { dbesc(z_root() . '/item/' . $item_id) ); - if (! $r) { - http_status_exit(404,'Not found'); + if (!$r) { + http_status_exit(404, 'Not found'); } // process an authenticated fetch @@ -79,10 +76,10 @@ class Item extends Controller { $sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR); if ($sigdata['portable_id'] && $sigdata['header_valid']) { $portable_id = $sigdata['portable_id']; - if (! check_channelallowed($portable_id)) { + if (!check_channelallowed($portable_id)) { http_status_exit(403, 'Permission denied'); } - if (! check_siteallowed($sigdata['signer'])) { + if (!check_siteallowed($sigdata['signer'])) { http_status_exit(403, 'Permission denied'); } observer_auth($portable_id); @@ -92,8 +89,8 @@ class Item extends Controller { dbesc($portable_id) ); } - elseif (Config::get('system','require_authenticated_fetch',false)) { - http_status_exit(403,'Permission denied'); + elseif (Config::get('system', 'require_authenticated_fetch', false)) { + http_status_exit(403, 'Permission denied'); } // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access @@ -101,47 +98,47 @@ class Item extends Controller { $sql_extra = item_permissions_sql(0); - if (! $i) { + if (!$i) { $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1", dbesc($r[0]['parent_mid']) ); } - if(! $i) { - http_status_exit(403,'Forbidden'); + if (!$i) { + http_status_exit(403, 'Forbidden'); } - $parents_str = ids_to_querystr($i,'item_id'); + $parents_str = ids_to_querystr($i, 'item_id'); $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal order by item.id asc", dbesc($parents_str) ); - if(! $items) { + if (!$items) { http_status_exit(404, 'Not found'); } - xchan_query($items,true); - $items = fetch_post_tags($items,true); + xchan_query($items, true); + $items = fetch_post_tags($items, true); - if(! $items) + if (!$items) http_status_exit(404, 'Not found'); $chan = channelx_by_n($items[0]['uid']); - if(! $chan) + if (!$chan) http_status_exit(404, 'Not found'); - if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream')) + if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) http_status_exit(403, 'Forbidden'); $i = Activity::encode_item_collection($items, 'conversation/' . $item_id, 'OrderedCollection'); - if(! $i) + if (!$i) http_status_exit(404, 'Not found'); - if($portable_id && (! intval($items[0]['item_private']))) { + if ($portable_id && (!intval($items[0]['item_private']))) { ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id); } @@ -149,25 +146,25 @@ class Item extends Controller { ACTIVITYSTREAMS_JSONLD_REV, 'https://w3id.org/security/v1', z_root() . ZOT_APSCHEMA_REV - ]], $i); + ]], $i); - $headers = []; - $headers['Content-Type'] = 'application/x-zot+json' ; - $x['signature'] = LDSignatures::sign($x,$chan); - $ret = json_encode($x, JSON_UNESCAPED_SLASHES); - $headers['Digest'] = HTTPSig::generate_digest_header($ret); + $headers = []; + $headers['Content-Type'] = 'application/x-zot+json'; + $x['signature'] = LDSignatures::sign($x, $chan); + $ret = json_encode($x, JSON_UNESCAPED_SLASHES); + $headers['Digest'] = HTTPSig::generate_digest_header($ret); $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; - $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan)); + $h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan)); HTTPSig::set_headers($h); echo $ret; killme(); } - if(ActivityStreams::is_as_request()) { + if (ActivityStreams::is_as_request()) { $item_id = argv(1); - if(! $item_id) + if (!$item_id) http_status_exit(404, 'Not found'); $portable_id = EMPTY_STR; @@ -189,8 +186,8 @@ class Item extends Controller { dbesc($item_id) ); - if (! $r) { - http_status_exit(404,'Not found'); + if (!$r) { + http_status_exit(404, 'Not found'); } // process an authenticated fetch @@ -198,10 +195,10 @@ class Item extends Controller { $sigdata = HTTPSig::verify(EMPTY_STR); if ($sigdata['portable_id'] && $sigdata['header_valid']) { $portable_id = $sigdata['portable_id']; - if (! check_channelallowed($portable_id)) { + if (!check_channelallowed($portable_id)) { http_status_exit(403, 'Permission denied'); } - if (! check_siteallowed($sigdata['signer'])) { + if (!check_siteallowed($sigdata['signer'])) { http_status_exit(403, 'Permission denied'); } observer_auth($portable_id); @@ -211,8 +208,8 @@ class Item extends Controller { dbesc($portable_id) ); } - elseif (Config::get('system','require_authenticated_fetch',false)) { - http_status_exit(403,'Permission denied'); + elseif (Config::get('system', 'require_authenticated_fetch', false)) { + http_status_exit(403, 'Permission denied'); } // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access @@ -220,40 +217,40 @@ class Item extends Controller { $sql_extra = item_permissions_sql(0); - if (! $i) { + if (!$i) { $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1", dbesc($r[0]['parent_mid']) ); } - if(! $i) { - http_status_exit(403,'Forbidden'); + if (!$i) { + http_status_exit(403, 'Forbidden'); } // If we get to this point we have determined we can access the original in $r (fetched much further above), so use it. - xchan_query($r,true); - $items = fetch_post_tags($r,false); + xchan_query($r, true); + $items = fetch_post_tags($r, false); $chan = channelx_by_n($items[0]['uid']); - if(! $chan) + if (!$chan) http_status_exit(404, 'Not found'); - if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream')) + if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) http_status_exit(403, 'Forbidden'); - $i = Activity::encode_item($items[0],true); + $i = Activity::encode_item($items[0]); - if(! $i) + if (!$i) http_status_exit(404, 'Not found'); - if ($portable_id && (! intval($items[0]['item_private']))) { + if ($portable_id && (!intval($items[0]['item_private']))) { $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'", intval($items[0]['uid']), dbesc($portable_id) ); - if (! $c) { + if (!$c) { ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id); } } @@ -262,16 +259,16 @@ class Item extends Controller { ACTIVITYSTREAMS_JSONLD_REV, 'https://w3id.org/security/v1', z_root() . ZOT_APSCHEMA_REV - ]], $i); - - $headers = []; - $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ; - $x['signature'] = LDSignatures::sign($x,$chan); - $ret = json_encode($x, JSON_UNESCAPED_SLASHES); - $headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T'); - $headers['Digest'] = HTTPSig::generate_digest_header($ret); + ]], $i); + + $headers = []; + $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'; + $x['signature'] = LDSignatures::sign($x, $chan); + $ret = json_encode($x, JSON_UNESCAPED_SLASHES); + $headers['Date'] = datetime_convert('UTC', 'UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T'); + $headers['Digest'] = HTTPSig::generate_digest_header($ret); $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; - $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan)); + $h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan)); HTTPSig::set_headers($h); echo $ret; killme(); @@ -279,17 +276,18 @@ class Item extends Controller { } - if(argc() > 1 && argv(1) !== 'drop') { - $x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' ", + if (argc() > 1 && argv(1) !== 'drop') { + $x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' or uuid = '%s'", dbesc(z_root() . '/item/' . argv(1)), - dbesc(z_root() . '/activity/' . argv(1)) + dbesc(z_root() . '/activity/' . argv(1)), + dbesc(argv(1)) ); - if($x) { - foreach($x as $xv) { + if ($x) { + foreach ($x as $xv) { if (intval($xv['item_wall'])) { $c = channelx_by_n($xv['uid']); if ($c) { - goaway($c['xchan_url'] . '?mid=' . gen_link_id($xv['mid'])); + goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . gen_link_id($xv['mid'])); } } } @@ -301,17 +299,16 @@ class Item extends Controller { } - function post() { // This will change. Figure out who the observer is and whether or not // they have permission to post here. Else ignore the post. - if((! local_channel()) && (! remote_channel()) && (! x($_REQUEST,'anonname'))) + if ((!local_channel()) && (!remote_channel()) && (!x($_REQUEST, 'anonname'))) return; - $uid = local_channel(); - $channel = null; + $uid = local_channel(); + $channel = null; $observer = null; $datarray = []; @@ -320,34 +317,34 @@ class Item extends Controller { * Is this a reply to something? */ - $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0); - $parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : ''); - $mode = (($_REQUEST['conv_mode'] === 'channel') ? 'channel' : 'network'); + $parent = ((x($_REQUEST, 'parent')) ? intval($_REQUEST['parent']) : 0); + $parent_mid = ((x($_REQUEST, 'parent_mid')) ? trim($_REQUEST['parent_mid']) : ''); + $mode = (($_REQUEST['conv_mode'] === 'channel') ? 'channel' : 'network'); - $remote_xchan = ((x($_REQUEST,'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false); - $r = q("select * from xchan where xchan_hash = '%s' limit 1", + $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) + if ($r) $remote_observer = $r[0]; else $remote_xchan = $remote_observer = false; - $profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0); + $profile_uid = ((x($_REQUEST, 'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0); require_once('include/channel.php'); $sys = get_sys_channel(); - if($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) { - $uid = intval($sys['channel_id']); - $channel = $sys; + if ($sys && $profile_uid && ($sys['channel_id'] == $profile_uid) && is_site_admin()) { + $uid = intval($sys['channel_id']); + $channel = $sys; $observer = $sys; } - if(x($_REQUEST,'dropitems')) { + if (x($_REQUEST, 'dropitems')) { require_once('include/items.php'); - $arr_drop = explode(',',$_REQUEST['dropitems']); + $arr_drop = explode(',', $_REQUEST['dropitems']); drop_items($arr_drop); - $json = array('success' => 1); + $json = ['success' => 1]; echo json_encode($json); killme(); } @@ -356,12 +353,12 @@ class Item extends Controller { // logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA); - $api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false); + $api_source = ((x($_REQUEST, 'api_source') && $_REQUEST['api_source']) ? true : false); $consensus = intval($_REQUEST['consensus']); $nocomment = intval($_REQUEST['nocomment']); - $is_poll = ((trim($_REQUEST['poll_answers'][0]) != '' && trim($_REQUEST['poll_answers'][1]) != '') ? true : false); + $is_poll = ((trim((string)$_REQUEST['poll_answers'][0]) != '' && trim((string)$_REQUEST['poll_answers'][1]) != '') ? true : false); // 'origin' (if non-zero) indicates that this network is where the message originated, // for the purpose of relaying comments to other conversation members. @@ -372,77 +369,75 @@ class Item extends Controller { // If you are unsure, it is prudent (and important) to leave it unset. - $origin = (($api_source && array_key_exists('origin',$_REQUEST)) ? intval($_REQUEST['origin']) : 1); + $origin = (($api_source && array_key_exists('origin', $_REQUEST)) ? intval($_REQUEST['origin']) : 1); // To represent message-ids on other networks - this will create an iconfig record - $namespace = (($api_source && array_key_exists('namespace',$_REQUEST)) ? strip_tags($_REQUEST['namespace']) : ''); - $remote_id = (($api_source && array_key_exists('remote_id',$_REQUEST)) ? strip_tags($_REQUEST['remote_id']) : ''); + $namespace = (($api_source && array_key_exists('namespace', $_REQUEST)) ? strip_tags($_REQUEST['namespace']) : ''); + $remote_id = (($api_source && array_key_exists('remote_id', $_REQUEST)) ? strip_tags($_REQUEST['remote_id']) : ''); $owner_hash = null; - $message_id = ((x($_REQUEST,'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : ''); - $created = ((x($_REQUEST,'created')) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['created']) : datetime_convert()); - $post_id = ((x($_REQUEST,'post_id')) ? intval($_REQUEST['post_id']) : 0); - $app = ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''); - $return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : ''); - $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0); - $categories = ((x($_REQUEST,'category')) ? escape_tags($_REQUEST['category']) : ''); - $webpage = ((x($_REQUEST,'webpage')) ? intval($_REQUEST['webpage']) : 0); - $item_obscured = ((x($_REQUEST,'obscured')) ? intval($_REQUEST['obscured']) : 0); - $pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : ''); - $layout_mid = ((x($_REQUEST,'layout_mid')) ? escape_tags($_REQUEST['layout_mid']): ''); - $plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : ''); - $obj_type = ((x($_REQUEST,'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE); + $message_id = ((x($_REQUEST, 'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : ''); + $created = ((x($_REQUEST, 'created')) ? datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['created']) : datetime_convert()); + $post_id = ((x($_REQUEST, 'post_id')) ? intval($_REQUEST['post_id']) : 0); + $app = ((x($_REQUEST, 'source')) ? strip_tags($_REQUEST['source']) : ''); + $return_path = ((x($_REQUEST, 'return')) ? $_REQUEST['return'] : ''); + $preview = ((x($_REQUEST, 'preview')) ? intval($_REQUEST['preview']) : 0); + $categories = ((x($_REQUEST, 'category')) ? escape_tags($_REQUEST['category']) : ''); + $webpage = ((x($_REQUEST, 'webpage')) ? intval($_REQUEST['webpage']) : 0); + $item_obscured = ((x($_REQUEST, 'obscured')) ? intval($_REQUEST['obscured']) : 0); + $pagetitle = ((x($_REQUEST, 'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : ''); + $layout_mid = ((x($_REQUEST, 'layout_mid')) ? escape_tags($_REQUEST['layout_mid']) : ''); + $plink = ((x($_REQUEST, 'permalink')) ? escape_tags($_REQUEST['permalink']) : ''); + $obj_type = ((x($_REQUEST, 'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE); // allow API to bulk load a bunch of imported items with sending out a bunch of posts. - $nopush = ((x($_REQUEST,'nopush')) ? intval($_REQUEST['nopush']) : 0); + $nopush = ((x($_REQUEST, 'nopush')) ? intval($_REQUEST['nopush']) : 0); /* * Check service class limits */ - if ($uid && !(x($_REQUEST,'parent')) && !(x($_REQUEST,'post_id'))) { - $ret = $this->item_check_service_class($uid,(($_REQUEST['webpage'] == ITEM_TYPE_WEBPAGE) ? true : false)); + if ($uid && !(x($_REQUEST, 'parent')) && !(x($_REQUEST, 'post_id'))) { + $ret = $this->item_check_service_class($uid, (($_REQUEST['webpage'] == ITEM_TYPE_WEBPAGE) ? true : false)); if (!$ret['success']) { - notice( t($ret['message']) . EOL) ; - if($api_source) - return ( [ 'success' => false, 'message' => 'service class exception' ] ); - if(x($_REQUEST,'return')) - goaway(z_root() . "/" . $return_path ); + notice(t($ret['message']) . EOL); + if ($api_source) + return (['success' => false, 'message' => 'service class exception']); + if (x($_REQUEST, 'return')) + goaway(z_root() . "/" . $return_path); killme(); } } - if($pagetitle) { - require_once('library/urlify/URLify.php'); - $pagetitle = strtolower(\URLify::transliterate($pagetitle)); + if ($pagetitle) { + $pagetitle = strtolower(URLify::transliterate($pagetitle)); } - $item_flags = $item_restrict = 0; $expires = NULL_DATE; + $comments_closed = NULL_DATE; - $route = ''; - $parent_item = null; + $route = ''; + $parent_item = null; $parent_contact = null; - $thr_parent = ''; - $parid = 0; - $r = false; + $thr_parent = ''; + $r = false; - if($parent || $parent_mid) { + if ($parent || $parent_mid) { - if(! x($_REQUEST,'type')) + if (!x($_REQUEST, 'type')) $_REQUEST['type'] = 'net-comment'; - if($obj_type == ACTIVITY_OBJ_NOTE) + if ($obj_type == ACTIVITY_OBJ_NOTE) $obj_type = ACTIVITY_OBJ_COMMENT; - if($parent) { + if ($parent) { $r = q("SELECT * FROM item WHERE id = %d LIMIT 1", intval($parent) ); } - elseif($parent_mid && $uid) { + elseif ($parent_mid && $uid) { // This is coming from an API source, and we are logged in $r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d LIMIT 1", dbesc($parent_mid), @@ -450,10 +445,10 @@ class Item extends Controller { ); } // if this isn't the real parent of the conversation, find it - if($r) { - $parid = $r[0]['parent']; + if ($r) { + $parid = $r[0]['parent']; $parent_mid = $r[0]['mid']; - if($r[0]['id'] != $r[0]['parent']) { + if ($r[0]['id'] != $r[0]['parent']) { $r = q("SELECT * FROM item WHERE id = parent AND parent = %d LIMIT 1", intval($parid) ); @@ -462,24 +457,24 @@ class Item extends Controller { // if interacting with a pubstream item, // create a copy of the parent in your stream - if($r[0]['uid'] === $sys['channel_id'] && local_channel()) { - $r = [ copy_of_pubitem(\App::get_channel(), $r[0]['mid']) ]; + if ($r[0]['uid'] === $sys['channel_id'] && local_channel()) { + $r = [copy_of_pubitem(App::get_channel(), $r[0]['mid'])]; } } - if(! $r) { - notice( t('Unable to locate original post.') . EOL); - if($api_source) - return ( [ 'success' => false, 'message' => 'invalid post id' ] ); - if(x($_REQUEST,'return')) - goaway(z_root() . "/" . $return_path ); + if (!$r) { + notice(t('Unable to locate original post.') . EOL); + if ($api_source) + return (['success' => false, 'message' => 'invalid post id']); + if (x($_REQUEST, 'return')) + goaway(z_root() . "/" . $return_path); killme(); } - xchan_query($r,true); + xchan_query($r, true); $parent_item = $r[0]; - $parent = $r[0]['id']; + $parent = $r[0]['id']; // multi-level threading - preserve the info but re-parent to our single level threading @@ -491,52 +486,52 @@ class Item extends Controller { $moderated = false; - if(! $observer) { - $observer = \App::get_observer(); - if(! $observer) { + if (!$observer) { + $observer = App::get_observer(); + if (!$observer) { $observer = anon_identity_init($_REQUEST); - if($observer) { - $moderated = true; + if ($observer) { + $moderated = true; $remote_xchan = $remote_observer = $observer; } } } - if(! $observer) { - notice( t('Permission denied.') . EOL) ; - if($api_source) - return ( [ 'success' => false, 'message' => 'permission denied' ] ); - if(x($_REQUEST,'return')) - goaway(z_root() . "/" . $return_path ); + if (!$observer) { + notice(t('Permission denied.') . EOL); + if ($api_source) + return (['success' => false, 'message' => 'permission denied']); + if (x($_REQUEST, 'return')) + goaway(z_root() . "/" . $return_path); killme(); } - if($parent) { + if ($parent) { logger('mod_item: item_post parent=' . $parent); $can_comment = false; - $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item); - if (!$can_comment) { - if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self'])==1 ) - $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments'); - } - - if(! $can_comment) { - notice( t('Permission denied.') . EOL) ; - if($api_source) - return ( [ 'success' => false, 'message' => 'permission denied' ] ); - if(x($_REQUEST,'return')) - goaway(z_root() . "/" . $return_path ); + $can_comment = can_comment_on_post($observer['xchan_hash'], $parent_item); + if (!$can_comment) { + if ((array_key_exists('owner', $parent_item)) && intval($parent_item['owner']['abook_self']) == 1) + $can_comment = perm_is_allowed($profile_uid, $observer['xchan_hash'], 'post_comments'); + } + + if (!$can_comment) { + notice(t('Permission denied.') . EOL); + if ($api_source) + return (['success' => false, 'message' => 'permission denied']); + if (x($_REQUEST, 'return')) + goaway(z_root() . "/" . $return_path); killme(); } } else { - if(! perm_is_allowed($profile_uid,$observer['xchan_hash'],($webpage) ? 'write_pages' : 'post_wall')) { - notice( t('Permission denied.') . EOL) ; - if($api_source) - return ( [ 'success' => false, 'message' => 'permission denied' ] ); - if(x($_REQUEST,'return')) - goaway(z_root() . "/" . $return_path ); + if (!perm_is_allowed($profile_uid, $observer['xchan_hash'], ($webpage) ? 'write_pages' : 'post_wall')) { + notice(t('Permission denied.') . EOL); + if ($api_source) + return (['success' => false, 'message' => 'permission denied']); + if (x($_REQUEST, 'return')) + goaway(z_root() . "/" . $return_path); killme(); } } @@ -546,53 +541,53 @@ class Item extends Controller { $orig_post = null; - if($namespace && $remote_id) { + if ($namespace && $remote_id) { // It wasn't an internally generated post - see if we've got an item matching this remote service id $i = q("select iid from iconfig where cat = 'system' and k = '%s' and v = '%s' limit 1", dbesc($namespace), dbesc($remote_id) ); - if($i) + if ($i) $post_id = $i[0]['iid']; } $iconfig = null; - if($post_id) { + if ($post_id) { $i = q("SELECT * FROM item WHERE uid = %d AND id = %d LIMIT 1", intval($profile_uid), intval($post_id) ); - if(! count($i)) + if (!count($i)) killme(); $orig_post = $i[0]; - $iconfig = q("select * from iconfig where iid = %d", + $iconfig = q("select * from iconfig where iid = %d", intval($post_id) ); } - if(! $channel) { - if($uid && $uid == $profile_uid) { - $channel = \App::get_channel(); + if (!$channel) { + if ($uid && $uid == $profile_uid) { + $channel = App::get_channel(); } else { // posting as yourself but not necessarily to a channel you control $r = q("select * from channel left join account on channel_account_id = account_id where channel_id = %d LIMIT 1", intval($profile_uid) ); - if($r) + if ($r) $channel = $r[0]; } } - if(! $channel) { + if (!$channel) { logger("mod_item: no channel."); - if($api_source) - return ( [ 'success' => false, 'message' => 'no channel' ] ); - if(x($_REQUEST,'return')) - goaway(z_root() . "/" . $return_path ); + if ($api_source) + return (['success' => false, 'message' => 'no channel']); + if (x($_REQUEST, 'return')) + goaway(z_root() . "/" . $return_path); killme(); } @@ -601,37 +596,37 @@ class Item extends Controller { $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($channel['channel_hash']) ); - if($r && count($r)) { + if ($r && count($r)) { $owner_xchan = $r[0]; } else { logger("mod_item: no owner."); - if($api_source) - return ( [ 'success' => false, 'message' => 'no owner' ] ); - if(x($_REQUEST,'return')) - goaway(z_root() . "/" . $return_path ); + if ($api_source) + return (['success' => false, 'message' => 'no owner']); + if (x($_REQUEST, 'return')) + goaway(z_root() . "/" . $return_path); killme(); } - $walltowall = false; + $walltowall = false; $walltowall_comment = false; - if($remote_xchan && ! $moderated) + if ($remote_xchan && !$moderated) $observer = $remote_observer; - if($observer) { + if ($observer) { logger('mod_item: post accepted from ' . $observer['xchan_name'] . ' for ' . $owner_xchan['xchan_name'], LOGGER_DEBUG); // wall-to-wall detection. // For top-level posts, if the author and owner are different it's a wall-to-wall // For comments, We need to additionally look at the parent and see if it's a wall post that originated locally. - if($observer['xchan_name'] != $owner_xchan['xchan_name']) { - if(($parent_item) && ($parent_item['item_wall'] && $parent_item['item_origin'])) { + if ($observer['xchan_name'] != $owner_xchan['xchan_name']) { + if (($parent_item) && ($parent_item['item_wall'] && $parent_item['item_origin'])) { $walltowall_comment = true; - $walltowall = true; + $walltowall = true; } - if(! $parent) { + if (!$parent) { $walltowall = true; } } @@ -639,83 +634,80 @@ class Item extends Controller { $acl = new \Zotlabs\Access\AccessList($channel); - $view_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'); - $comment_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments'); + $view_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_stream'); + $comment_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'post_comments'); - $public_policy = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy,true)); - if($webpage) + $public_policy = ((x($_REQUEST, 'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy, true)); + if ($webpage) $public_policy = ''; - if($public_policy) + if ($public_policy) $private = 1; - if($orig_post) { + if ($orig_post) { $private = 0; // webpages are allowed to change ACLs after the fact. Normal conversation items aren't. - if($webpage) { + if ($webpage) { $acl->set_from_array($_REQUEST); } else { $acl->set($orig_post); - $public_policy = $orig_post['public_policy']; - $private = $orig_post['item_private']; + $public_policy = $orig_post['public_policy']; + $private = $orig_post['item_private']; } - if($public_policy || $acl->is_private()) { + if ($public_policy || $acl->is_private()) { $private = (($private) ? $private : 1); } - $location = $orig_post['location']; - $coord = $orig_post['coord']; - $verb = $orig_post['verb']; - $app = $orig_post['app']; - $title = escape_tags(trim($_REQUEST['title'])); - $summary = trim($_REQUEST['summary']); - $body = trim($_REQUEST['body']); - $item_flags = $orig_post['item_flags']; - - $item_origin = $orig_post['item_origin']; - $item_unseen = $orig_post['item_unseen']; - $item_starred = $orig_post['item_starred']; - $item_uplink = $orig_post['item_uplink']; - $item_consensus = $orig_post['item_consensus']; - $item_wall = $orig_post['item_wall']; - $item_thread_top = $orig_post['item_thread_top']; - $item_notshown = $orig_post['item_notshown']; - $item_nsfw = $orig_post['item_nsfw']; - $item_relay = $orig_post['item_relay']; - $item_mentionsme = $orig_post['item_mentionsme']; - $item_nocomment = $orig_post['item_nocomment']; - $item_obscured = $orig_post['item_obscured']; - $item_verified = $orig_post['item_verified']; - $item_retained = $orig_post['item_retained']; - $item_rss = $orig_post['item_rss']; - $item_deleted = $orig_post['item_deleted']; - $item_type = $orig_post['item_type']; - $item_hidden = $orig_post['item_hidden']; - $item_unpublished = $orig_post['item_unpublished']; - $item_delayed = $orig_post['item_delayed']; - $item_pending_remove = $orig_post['item_pending_remove']; - $item_blocked = $orig_post['item_blocked']; - - - - $postopts = $orig_post['postopts']; - $created = $orig_post['created']; - $expires = $orig_post['expires']; - $mid = $orig_post['mid']; - $parent_mid = $orig_post['parent_mid']; - $plink = $orig_post['plink']; - + $location = $orig_post['location']; + $coord = $orig_post['coord']; + $verb = $orig_post['verb']; + $app = $orig_post['app']; + $title = escape_tags(trim($_REQUEST['title'])); + $summary = trim($_REQUEST['summary']); + $body = trim($_REQUEST['body']); + $item_flags = $orig_post['item_flags']; + $item_origin = $orig_post['item_origin']; + $item_unseen = $orig_post['item_unseen']; + $item_starred = $orig_post['item_starred']; + $item_uplink = $orig_post['item_uplink']; + $item_consensus = $orig_post['item_consensus']; + $item_wall = $orig_post['item_wall']; + $item_thread_top = $orig_post['item_thread_top']; + $item_notshown = $orig_post['item_notshown']; + $item_nsfw = $orig_post['item_nsfw']; + $item_relay = $orig_post['item_relay']; + $item_mentionsme = $orig_post['item_mentionsme']; + $item_nocomment = $orig_post['item_nocomment']; + $item_obscured = $orig_post['item_obscured']; + $item_verified = $orig_post['item_verified']; + $item_retained = $orig_post['item_retained']; + $item_rss = $orig_post['item_rss']; + $item_deleted = $orig_post['item_deleted']; + $item_type = $orig_post['item_type']; + $item_hidden = $orig_post['item_hidden']; + $item_unpublished = $orig_post['item_unpublished']; + $item_delayed = $orig_post['item_delayed']; + $item_pending_remove = $orig_post['item_pending_remove']; + $item_blocked = $orig_post['item_blocked']; + $postopts = $orig_post['postopts']; + $created = $orig_post['created']; + $expires = $orig_post['expires']; + $comments_closed = $orig_post['comments_closed']; + $mid = $orig_post['mid']; + $thr_parent = $orig_post['thr_parent']; + $parent_mid = $orig_post['parent_mid']; + $plink = $orig_post['plink']; } else { - if(! $walltowall) { - if((array_key_exists('contact_allow',$_REQUEST)) - || (array_key_exists('group_allow',$_REQUEST)) - || (array_key_exists('contact_deny',$_REQUEST)) - || (array_key_exists('group_deny',$_REQUEST))) { + if (!$walltowall) { + if ((array_key_exists('contact_allow', $_REQUEST)) + || (array_key_exists('group_allow', $_REQUEST)) + || (array_key_exists('contact_deny', $_REQUEST)) + || (array_key_exists('group_deny', $_REQUEST))) { $acl->set_from_array($_REQUEST); } - elseif(! $api_source) { + elseif (!$api_source) { // if no ACL has been defined and we aren't using the API, the form // didn't send us any parameters. This means there's no ACL or it has @@ -723,27 +715,27 @@ class Item extends Controller { // If $api_source is set and there are no ACL parameters, we default // to the channel permissions which were set in the ACL contructor. - $acl->set(array('allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '')); + $acl->set(['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '']); } } - $location = notags(trim($_REQUEST['location'])); - $coord = notags(trim($_REQUEST['coord'])); - $verb = notags(trim($_REQUEST['verb'])); - $title = escape_tags(trim($_REQUEST['title'])); - $summary = trim($_REQUEST['summary']); - $body = trim($_REQUEST['body']); - $body .= trim($_REQUEST['attachment']); - $postopts = ''; + $location = notags(trim((string)$_REQUEST['location'])); + $coord = notags(trim((string)$_REQUEST['coord'])); + $verb = notags(trim((string)$_REQUEST['verb'])); + $title = escape_tags(trim((string)$_REQUEST['title'])); + $summary = trim((string)$_REQUEST['summary']); + $body = trim((string)$_REQUEST['body']); + $body .= trim((string)$_REQUEST['attachment']); + $postopts = ''; - $allow_empty = ((array_key_exists('allow_empty',$_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0); + $allow_empty = ((array_key_exists('allow_empty', $_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0); $private = (($private) ? $private : intval($acl->is_private() || ($public_policy))); // If this is a comment, set the permissions from the parent. - if($parent_item) { + if ($parent_item) { $acl->set($parent_item); $private = intval($parent_item['item_private']); $public_policy = $parent_item['public_policy']; @@ -751,51 +743,50 @@ class Item extends Controller { $webpage = $parent_item['item_type']; } - if((! $allow_empty) && (! strlen($body))) { - if($preview) + if ((!$allow_empty) && (!strlen($body))) { + if ($preview) killme(); - info( t('Empty post discarded.') . EOL ); - if($api_source) - return ( [ 'success' => false, 'message' => 'no content' ] ); - if(x($_REQUEST,'return')) - goaway(z_root() . "/" . $return_path ); + info(t('Empty post discarded.') . EOL); + if ($api_source) + return (['success' => false, 'message' => 'no content']); + if (x($_REQUEST, 'return')) + goaway(z_root() . "/" . $return_path); killme(); } } - - if(feature_enabled($profile_uid,'content_expire')) { - if(x($_REQUEST,'expire')) { - $expires = datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expire']); - if($expires <= datetime_convert()) + if (feature_enabled($profile_uid, 'content_expire')) { + if (x($_REQUEST, 'expire')) { + $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['expire']); + if ($expires <= datetime_convert()) $expires = NULL_DATE; } } - $mimetype = notags(trim($_REQUEST['mimetype'])); - if(! $mimetype) + $mimetype = notags(trim((string)$_REQUEST['mimetype'])); + if (!$mimetype) $mimetype = 'text/bbcode'; $execflag = ((intval($uid) == intval($profile_uid) && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false); - if($preview) { - $summary = z_input_filter($summary,$mimetype,$execflag); - $body = z_input_filter($body,$mimetype,$execflag); + if ($preview) { + $summary = z_input_filter($summary, $mimetype, $execflag); + $body = z_input_filter($body, $mimetype, $execflag); } - $arr = [ 'profile_uid' => $profile_uid, 'summary' => $summary, 'content' => $body, 'mimetype' => $mimetype ]; - call_hooks('post_content',$arr); - $summary = $arr['summary']; - $body = $arr['content']; + $arr = ['profile_uid' => $profile_uid, 'summary' => $summary, 'content' => $body, 'mimetype' => $mimetype]; + call_hooks('post_content', $arr); + $summary = $arr['summary']; + $body = $arr['content']; $mimetype = $arr['mimetype']; - $gacl = $acl->get(); + $gacl = $acl->get(); $str_contact_allow = $gacl['allow_cid']; $str_group_allow = $gacl['allow_gid']; $str_contact_deny = $gacl['deny_cid']; @@ -806,23 +797,18 @@ class Item extends Controller { // if this is a wall-to-wall post to a group, turn it into a direct message - $role = get_pconfig($profile_uid,'system','permissions_role'); - - $rolesettings = PermissionRoles::role_perms($role); - - $channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal'; - - $is_group = (($channel_type === 'group') ? true : false); + $is_group = get_pconfig($profile_uid, 'system', 'group_actor'); - if (($is_group) && ($walltowall) && (! $walltowall_comment)) { - $groupww = true; + if (($is_group) && ($walltowall) && (!$walltowall_comment)) { + $groupww = true; $str_contact_allow = $owner_xchan['xchan_hash']; - $str_group_allow = ''; + $str_group_allow = ''; } $post_tags = []; - if($mimetype === 'text/bbcode') { + + if ($mimetype === 'text/bbcode') { require_once('include/text.php'); @@ -837,27 +823,27 @@ class Item extends Controller { $results = linkify_tags($body, ($uid) ? $uid : $profile_uid); - if($results) { + if ($results) { // Set permissions based on tag replacements set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item); - foreach($results as $result) { + foreach ($results as $result) { $success = $result['success']; - if($success['replaced']) { - $post_tags[] = array( + if ($success['replaced']) { + $post_tags[] = [ 'uid' => $profile_uid, 'ttype' => $success['termtype'], 'otype' => TERM_OBJ_POST, 'term' => $success['term'], 'url' => $success['url'] - ); + ]; } } } - if(($str_contact_allow) && (! $str_group_allow)) { + if (($str_contact_allow) && (!$str_group_allow)) { // direct message - private between individual channels but not groups $private = 2; } @@ -882,45 +868,45 @@ class Item extends Controller { * */ - if(! $preview) { - fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny); - fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($summary,'[/crypt]')) ? $_POST['media_str'] : $summary),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny); - fix_attached_file_permissions($channel,$observer['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny); + if (!$preview) { + fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); + fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($summary, '[/crypt]')) ? $_POST['media_str'] : $summary), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); + fix_attached_file_permissions($channel, $observer['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); } $attachments = ''; - $match = false; + $match = false; - if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) { - $attachments = array(); - $i = 0; - foreach($match[2] as $mtch) { + if (preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/', $body, $match)) { + $attachments = []; + $i = 0; + foreach ($match[2] as $mtch) { $attach_link = ''; - $hash = substr($mtch,0,strpos($mtch,',')); - $rev = intval(substr($mtch,strpos($mtch,','))); - $r = attach_by_hash_nodata($hash, $observer['xchan_hash'], $rev); - if($r['success']) { - $attachments[] = array( + $hash = substr($mtch, 0, strpos($mtch, ',')); + $rev = intval(substr($mtch, strpos($mtch, ','))); + $r = attach_by_hash_nodata($hash, $observer['xchan_hash'], $rev); + if ($r['success']) { + $attachments[] = [ 'href' => z_root() . '/attach/' . $r['data']['hash'], 'length' => $r['data']['filesize'], 'type' => $r['data']['filetype'], 'title' => urlencode($r['data']['filename']), 'revision' => $r['data']['revision'] - ); + ]; } - $body = str_replace($match[1][$i],$attach_link,$body); + $body = str_replace($match[1][$i], $attach_link, $body); $i++; } } - if(preg_match_all('/(\[share=(.*?)\](.*?)\[\/share\])/',$body,$match)) { + if (preg_match_all('/(\[share=(.*?)\](.*?)\[\/share\])/', $body, $match)) { // process share by id $i = 0; - foreach($match[2] as $mtch) { + foreach ($match[2] as $mtch) { $reshare = new \Zotlabs\Lib\Share($mtch); - $body = str_replace($match[1][$i],$reshare->bbcode(),$body); + $body = str_replace($match[1][$i], $reshare->bbcode(), $body); $i++; } } @@ -928,32 +914,32 @@ class Item extends Controller { // BBCODE end alert } - if(strlen($categories)) { + if (strlen($categories)) { - $cats = explode(',',$categories); - foreach($cats as $cat) { + $cats = explode(',', $categories); + foreach ($cats as $cat) { - if($webpage == ITEM_TYPE_CARD) { + if ($webpage == ITEM_TYPE_CARD) { $catlink = z_root() . '/cards/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat)); } - elseif($webpage == ITEM_TYPE_ARTICLE) { + elseif ($webpage == ITEM_TYPE_ARTICLE) { $catlink = z_root() . '/articles/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat)); } else { $catlink = $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat)); } - $post_tags[] = array( + $post_tags[] = [ 'uid' => $profile_uid, 'ttype' => TERM_CATEGORY, 'otype' => TERM_OBJ_POST, 'term' => trim($cat), 'url' => $catlink - ); + ]; } } - if($orig_post) { + if ($orig_post) { // preserve original tags $t = q("select * from term where oid = %d and otype = %d and uid = %d and ttype in ( %d, %d, %d )", intval($orig_post['id']), @@ -963,120 +949,133 @@ class Item extends Controller { intval(TERM_FILE), intval(TERM_COMMUNITYTAG) ); - if($t) { - foreach($t as $t1) { - $post_tags[] = array( + if ($t) { + foreach ($t as $t1) { + $post_tags[] = [ 'uid' => $profile_uid, 'ttype' => $t1['ttype'], 'otype' => TERM_OBJ_POST, 'term' => $t1['term'], 'url' => $t1['url'], - ); + ]; } } } - $item_unseen = ((local_channel() != $profile_uid) ? 1 : 0); - $item_wall = (($_REQUEST['type'] === 'wall' || $_REQUEST['type'] === 'wall-comment') ? 1 : 0); - $item_origin = (($origin) ? 1 : 0); + $item_unseen = ((local_channel() != $profile_uid) ? 1 : 0); + $item_wall = (($_REQUEST['type'] === 'wall' || $_REQUEST['type'] === 'wall-comment') ? 1 : 0); + $item_origin = (($origin) ? 1 : 0); $item_consensus = (($consensus) ? 1 : 0); $item_nocomment = (($nocomment) ? 1 : 0); // determine if this is a wall post - if($parent) { + if ($parent) { $item_wall = $parent_item['item_wall']; } else { - if(! $webpage) { + if (!$webpage) { $item_wall = 1; } } - if($moderated) + if ($moderated) $item_blocked = ITEM_MODERATED; - if(! strlen($verb)) - $verb = ACTIVITY_POST ; + if (!strlen($verb)) + $verb = ACTIVITY_POST; + + $notify_type = (($parent) ? 'comment-new' : 'wall-new'); - $notify_type = (($parent) ? 'comment-new' : 'wall-new' ); + $uuid = (($message_id) ? $message_id : item_message_id()); - if(! $mid) { - $uuid = (($message_id) ? $message_id : item_message_id()); - $mid = z_root() . '/item/' . $uuid; + if (!$mid) { + $mid = z_root() . '/item/' . $uuid; } - if($is_poll) { + if ($is_poll) { $poll = [ - 'question' => $body, - 'answers' => $_REQUEST['poll_answers'], + 'question' => $body, + 'answers' => $_REQUEST['poll_answers'], 'multiple_answers' => $_REQUEST['poll_multiple_answers'], - 'expire_value' => $_REQUEST['poll_expire_value'], - 'expire_unit' => $_REQUEST['poll_expire_unit'] + 'expire_value' => $_REQUEST['poll_expire_value'], + 'expire_unit' => $_REQUEST['poll_expire_unit'] ]; - $obj = $this->extract_poll_data($poll, [ 'item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny ]); + $obj = $this->extract_poll_data($poll, ['item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny]); } else { - $obj = $this->extract_bb_poll_data($body,[ 'item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny ]); + $obj = $this->extract_bb_poll_data($body, ['item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny]); } if ($obj) { - $obj['url'] = $mid; - $obj['attributedTo'] = channel_url($channel); - $datarray['obj'] = $obj; + $obj['url'] = $mid; + $obj['id'] = $mid; + $obj['diaspora:guid'] = $uuid; + $obj['attributedTo'] = channel_url($channel); + $obj['published'] = $created; + $obj['name'] = $title; + + $datarray['obj'] = $obj; + + if ($obj['endTime']) { + $d = datetime_convert('UTC','UTC', $obj['endTime']); + if ($d > NULL_DATE) { + $comments_closed = $d; + } + } + $obj_type = 'Question'; } - if(! $parent_mid) { + if (!$parent_mid) { $parent_mid = $mid; } - if($parent_item) + if ($parent_item) $parent_mid = $parent_item['mid']; - // Fallback so that we alway have a thr_parent - if(!$thr_parent) + if (!$thr_parent) $thr_parent = $mid; - $item_thread_top = ((! $parent) ? 1 : 0); + $item_thread_top = ((!$parent) ? 1 : 0); // fix permalinks for cards - if($webpage == ITEM_TYPE_CARD) { + if ($webpage == ITEM_TYPE_CARD) { $plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : $uuid); } - if(($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_CARD)) { + if (($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_CARD)) { $r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.iid = %d limit 1", intval($parent_item['id']) ); - if($r) { + if ($r) { $plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . $r[0]['v']; } } - if($webpage == ITEM_TYPE_ARTICLE) { + if ($webpage == ITEM_TYPE_ARTICLE) { $plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : $uuid); } - if(($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_ARTICLE)) { + if (($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_ARTICLE)) { $r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and iconfig.iid = %d limit 1", intval($parent_item['id']) ); - if($r) { + if ($r) { $plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . $r[0]['v']; } } - if ((! $plink) && ($item_thread_top)) { + if ((!$plink) && ($item_thread_top)) { // $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid); // $plink = substr($plink,0,190); $plink = $mid; @@ -1094,6 +1093,7 @@ class Item extends Controller { $datarray['created'] = $created; $datarray['edited'] = (($orig_post) ? datetime_convert() : $created); $datarray['expires'] = $expires; + $datarray['comments_closed'] = (($nocomment) ? $created : $comments_closed); $datarray['commented'] = (($orig_post) ? datetime_convert() : $created); $datarray['received'] = (($orig_post) ? datetime_convert() : $created); $datarray['changed'] = (($orig_post) ? datetime_convert() : $created); @@ -1149,33 +1149,33 @@ class Item extends Controller { // A specific ACL over-rides public_policy completely - if(! empty_acl($datarray)) + if (!empty_acl($datarray)) $datarray['public_policy'] = ''; - if($iconfig) + if ($iconfig) $datarray['iconfig'] = $iconfig; // preview mode - prepare the body for display and send it via json - if($preview) { + if ($preview) { require_once('include/conversation.php'); - $datarray['owner'] = $owner_xchan; + $datarray['owner'] = $owner_xchan; $datarray['author'] = $observer; $datarray['attach'] = json_encode($datarray['attach']); - $o = conversation(array($datarray),'search',false,'preview'); - // logger('preview: ' . $o, LOGGER_DEBUG); - echo json_encode(array('preview' => $o)); + $o = conversation([$datarray], 'search', false, 'preview'); + // logger('preview: ' . $o, LOGGER_DEBUG); + echo json_encode(['preview' => $o]); killme(); } - if($orig_post) + if ($orig_post) $datarray['edit'] = true; // suppress duplicates, *unless* you're editing an existing post. This could get picked up // as a duplicate if you're editing it very soon after posting it initially and you edited // some attribute besides the content, such as title or categories. - if(feature_enabled($profile_uid,'suppress_duplicates') && (! $orig_post)) { + if (feature_enabled($profile_uid, 'suppress_duplicates') && (!$orig_post)) { $z = q("select created from item where uid = %d and created > %s - INTERVAL %s and body = '%s' limit 1", intval($profile_uid), @@ -1184,45 +1184,45 @@ class Item extends Controller { dbesc($body) ); - if($z) { + if ($z) { $datarray['cancel'] = 1; - notice( t('Duplicate post suppressed.') . EOL); + notice(t('Duplicate post suppressed.') . EOL); logger('Duplicate post. Faking plugin cancel.'); } } - call_hooks('post_local',$datarray); + call_hooks('post_local', $datarray); - if(x($datarray,'cancel')) { + if (x($datarray, 'cancel')) { logger('mod_item: post cancelled by plugin or duplicate suppressed.'); - if($return_path) + if ($return_path) goaway(z_root() . "/" . $return_path); - if($api_source) - return ( [ 'success' => false, 'message' => 'operation cancelled' ] ); - $json = array('cancel' => 1); + if ($api_source) + return (['success' => false, 'message' => 'operation cancelled']); + $json = ['cancel' => 1]; $json['reload'] = z_root() . '/' . $_REQUEST['jsreload']; echo json_encode($json); killme(); } - if(mb_strlen($datarray['title']) > 191) - $datarray['title'] = mb_substr($datarray['title'],0,191); + if (mb_strlen($datarray['title']) > 191) + $datarray['title'] = mb_substr($datarray['title'], 0, 191); - if($webpage) { - IConfig::Set($datarray,'system', webpage_to_namespace($webpage), + if ($webpage) { + IConfig::Set($datarray, 'system', webpage_to_namespace($webpage), (($pagetitle) ? $pagetitle : basename($datarray['mid'])), true); } - elseif($namespace) { - IConfig::Set($datarray,'system', $namespace, + elseif ($namespace) { + IConfig::Set($datarray, 'system', $namespace, (($remote_id) ? $remote_id : basename($datarray['mid'])), true); } - if($orig_post) { + if ($orig_post) { $datarray['id'] = $post_id; - $x = item_store_update($datarray,$execflag); + $x = item_store_update($datarray, $execflag); // We only need edit activities for other federated protocols // which do not support edits natively. While this does federate @@ -1236,82 +1236,80 @@ class Item extends Controller { // item_create_edit_activity($x); - if(! $parent) { + if (!$parent) { $r = q("select * from item where id = %d", intval($post_id) ); - if($r) { + if ($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - Libsync::build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true)))); + Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]); } } - if(! $nopush) - Master::Summon([ 'Notifier', 'edit_post', $post_id ]); + if (!$nopush) + Master::Summon(['Notifier', 'edit_post', $post_id]); - if($api_source) - return($x); + if ($api_source) + return ($x); - if((x($_REQUEST,'return')) && strlen($return_path)) { + if ((x($_REQUEST, 'return')) && strlen($return_path)) { logger('return: ' . $return_path); - goaway(z_root() . "/" . $return_path ); + goaway(z_root() . "/" . $return_path); } killme(); } - else - $post_id = 0; - $post = item_store($datarray,$execflag); + $post = item_store($datarray, $execflag); $post_id = $post['item_id']; $datarray = $post['item']; - if($post_id) { + if ($post_id) { logger('mod_item: saved item ' . $post_id); - if($parent) { + if ($parent) { // prevent conversations which you are involved from being expired - if(local_channel()) + if (local_channel()) retain_item($parent); // only send comment notification if this is a wall-to-wall comment, // otherwise it will happen during delivery - if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) { - Enotify::submit(array( - 'type' => NOTIFY_COMMENT, - 'from_xchan' => $datarray['author_xchan'], - 'to_xchan' => $datarray['owner_xchan'], - 'item' => $datarray, - 'link' => z_root() . '/display/' . gen_link_id($datarray['mid']), - 'verb' => ACTIVITY_POST, - 'otype' => 'item', - 'parent' => $parent, - 'parent_mid' => $parent_item['mid'] - )); + if (($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) { + Enotify::submit([ + 'type' => NOTIFY_COMMENT, + 'from_xchan' => $datarray['author_xchan'], + 'to_xchan' => $datarray['owner_xchan'], + 'item' => $datarray, + 'link' => z_root() . '/display/' . gen_link_id($datarray['mid']), + 'verb' => ACTIVITY_POST, + 'otype' => 'item', + 'parent' => $parent, + 'parent_mid' => $parent_item['mid'] + ]); } } else { $parent = $post_id; - if(($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) { - Enotify::submit(array( - 'type' => NOTIFY_WALL, - 'from_xchan' => $datarray['author_xchan'], - 'to_xchan' => $datarray['owner_xchan'], - 'item' => $datarray, - 'link' => z_root() . '/display/' . gen_link_id($datarray['mid']), - 'verb' => ACTIVITY_POST, - 'otype' => 'item' - )); + if (($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) { + Enotify::submit([ + 'type' => NOTIFY_WALL, + 'from_xchan' => $datarray['author_xchan'], + 'to_xchan' => $datarray['owner_xchan'], + 'item' => $datarray, + 'link' => z_root() . '/display/' . gen_link_id($datarray['mid']), + 'verb' => ACTIVITY_POST, + 'otype' => 'item' + ]); } - if($uid && $uid == $profile_uid && (is_item_normal($datarray))) { + if ($uid && $uid == $profile_uid && (is_item_normal($datarray))) { q("update channel set channel_lastpost = '%s' where channel_id = %d", dbesc(datetime_convert()), intval($uid) @@ -1323,7 +1321,7 @@ class Item extends Controller { // This way we don't see every picture in your new photo album posted to your wall at once. // They will show up as people comment on them. - if(intval($parent_item['item_hidden'])) { + if (intval($parent_item['item_hidden'])) { $r = q("UPDATE item SET item_hidden = 0 WHERE id = %d", intval($parent_item['id']) ); @@ -1331,22 +1329,22 @@ class Item extends Controller { } else { logger('mod_item: unable to retrieve post that was just stored.'); - notice( t('System error. Post not saved.') . EOL); - if($return_path) - goaway(z_root() . "/" . $return_path ); - if($api_source) - return ( [ 'success' => false, 'message' => 'system error' ] ); + notice(t('System error. Post not saved.') . EOL); + if ($return_path) + goaway(z_root() . "/" . $return_path); + if ($api_source) + return (['success' => false, 'message' => 'system error']); killme(); } - if($parent || $datarray['item_private'] == 1) { + if ($parent || $datarray['item_private'] == 1) { $r = q("select * from item where id = %d", intval($post_id) ); - if($r) { + if ($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - Libsync::build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true)))); + Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]); } } @@ -1359,42 +1357,46 @@ class Item extends Controller { $nopush = false; } - if(! $nopush) - Master::Summon([ 'Notifier', $notify_type, $post_id ]); + if (!$nopush) + Master::Summon(['Notifier', $notify_type, $post_id]); logger('post_complete'); - if($moderated) { + if ($moderated) { info(t('Your comment is awaiting approval.') . EOL); } // figure out how to return, depending on from whence we came - if($api_source) + if ($api_source) return $post; - if($return_path) { + if ($return_path) { + if ($return_path === 'hq') { + goaway(z_root() . '/hq/' . gen_link_id($datarray['mid'])); + } + goaway(z_root() . "/" . $return_path); } - if($mode === 'channel') + if ($mode === 'channel') profile_load($channel['channel_address']); - $item[] = $datarray; - $item[0]['owner'] = $owner_xchan; + $item[] = $datarray; + $item[0]['owner'] = $owner_xchan; $item[0]['author'] = $observer; $item[0]['attach'] = $datarray['attach']; $json = [ 'success' => 1, - 'id' => $post_id, - 'html' => conversation($item,$mode,true,'r_preview'), + 'id' => $post_id, + 'html' => conversation($item, $mode, true, 'r_preview'), ]; - if(x($_REQUEST,'jsreload') && strlen($_REQUEST['jsreload'])) + if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload'])) $json['reload'] = z_root() . '/' . $_REQUEST['jsreload']; - logger('post_json: ' . print_r($json,true), LOGGER_DEBUG); + logger('post_json: ' . print_r($json, true), LOGGER_DEBUG); echo json_encode($json); killme(); @@ -1404,10 +1406,10 @@ class Item extends Controller { function get() { - if((! local_channel()) && (! remote_channel())) + if ((!local_channel()) && (!remote_channel())) return; - if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) { + if ((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) { require_once('include/items.php'); @@ -1416,16 +1418,16 @@ class Item extends Controller { intval(argv(2)) ); - if($i) { - $can_delete = false; + if ($i) { + $can_delete = false; $local_delete = false; - if(local_channel() && local_channel() == $i[0]['uid']) { + if (local_channel() && local_channel() == $i[0]['uid']) { $local_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'])) { + if ($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) { $can_delete = true; } @@ -1433,15 +1435,15 @@ class Item extends Controller { // If the item originated on this site+channel the deletion will propagate downstream. // Otherwise just the local copy is removed. - if(is_site_admin()) { + if (is_site_admin()) { $local_delete = true; - if(intval($i[0]['item_origin'])) + if (intval($i[0]['item_origin'])) $can_delete = true; } - if(! ($can_delete || $local_delete)) { - notice( t('Permission denied.') . EOL); + if (!($can_delete || $local_delete)) { + notice(t('Permission denied.') . EOL); return; } @@ -1450,35 +1452,34 @@ class Item extends Controller { $complex = false; - if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) { + if (intval($i[0]['item_type']) || ($local_delete && (!$can_delete))) { drop_item($i[0]['id']); } else { // complex deletion that needs to propagate and be performed in phases - drop_item($i[0]['id'],true,DROPITEM_PHASE1); + drop_item($i[0]['id'], true, DROPITEM_PHASE1); $complex = true; } $r = q("select * from item where id = %d", intval($i[0]['id']) ); - if($r) { + if ($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - Libsync::build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true)))); + Libsync::build_sync_packet($i[0]['uid'], ['item' => [encode_item($sync_item[0], true)]]); } - if($complex) { - tag_deliver($i[0]['uid'],$i[0]['id']); + if ($complex) { + tag_deliver($i[0]['uid'], $i[0]['id']); } } } } - - function item_check_service_class($channel_id,$iswebpage) { - $ret = array('success' => false, 'message' => ''); + function item_check_service_class($channel_id, $iswebpage) { + $ret = ['success' => false, 'message' => '']; if ($iswebpage) { $r = q("select count(i.id) as total from item i @@ -1494,23 +1495,23 @@ class Item extends Controller { ); } - if(! $r) { + if (!$r) { $ret['message'] = t('Unable to obtain post information from database.'); return $ret; } if (!$iswebpage) { - $max = engr_units_to_bytes(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; + $max = engr_units_to_bytes(service_class_fetch($channel_id, 'total_items')); + if (!service_class_allows($channel_id, 'total_items', $r[0]['total'])) { + $ret['message'] .= upgrade_message() . sprintf(t('You have reached your limit of %1$.0f top level posts.'), $max); + return $ret; } } else { - $max = engr_units_to_bytes(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; + $max = engr_units_to_bytes(service_class_fetch($channel_id, 'total_pages')); + if (!service_class_allows($channel_id, 'total_pages', $r[0]['total'])) { + $ret['message'] .= upgrade_message() . sprintf(t('You have reached your limit of %1$.0f webpages.'), $max); + return $ret; } } @@ -1518,51 +1519,51 @@ class Item extends Controller { return $ret; } - function extract_bb_poll_data(&$body,$item) { + function extract_bb_poll_data(&$body, $item) { $multiple = false; - if (strpos($body,'[/question]') === false && strpos($body,'[/answer]') === false) { + if (strpos($body, '[/question]') === false && strpos($body, '[/answer]') === false) { return false; } - if (strpos($body,'[nobb]') !== false) { + if (strpos($body, '[nobb]') !== false) { return false; } - $obj = []; - $ptr = []; - $matches = null; + $obj = []; + $ptr = []; + $matches = null; $obj['type'] = 'Question'; - if (preg_match_all('/\[answer\](.*?)\[\/answer\]/ism',$body,$matches,PREG_SET_ORDER)) { + if (preg_match_all('/\[answer\](.*?)\[\/answer\]/ism', $body, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { - $ptr[] = [ 'name' => $match[1], 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]]; - $body = str_replace('[answer]' . $match[1] . '[/answer]', EMPTY_STR, $body); + $ptr[] = ['name' => $match[1], 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]]; + $body = str_replace('[answer]' . $match[1] . '[/answer]', EMPTY_STR, $body); } } $matches = null; - if (preg_match('/\[question\](.*?)\[\/question\]/ism',$body,$matches)) { + if (preg_match('/\[question\](.*?)\[\/question\]/ism', $body, $matches)) { $obj['content'] = bbcode($matches[1]); - $body = str_replace('[question]' . $matches[1] . '[/question]', $matches[1], $body); - $obj['oneOf'] = $ptr; + $body = str_replace('[question]' . $matches[1] . '[/question]', $matches[1], $body); + $obj['oneOf'] = $ptr; } $matches = null; - if (preg_match('/\[question=multiple\](.*?)\[\/question\]/ism',$body,$matches)) { + if (preg_match('/\[question=multiple\](.*?)\[\/question\]/ism', $body, $matches)) { $obj['content'] = bbcode($matches[1]); - $body = str_replace('[question=multiple]' . $matches[1] . '[/question]', $matches[1], $body); - $obj['anyOf'] = $ptr; + $body = str_replace('[question=multiple]' . $matches[1] . '[/question]', $matches[1], $body); + $obj['anyOf'] = $ptr; } $matches = null; - if (preg_match('/\[ends\](.*?)\[\/ends\]/ism',$body,$matches)) { - $obj['endTime'] = datetime_convert(date_default_timezone_get(),'UTC', $matches[1],ATOM_TIME); - $body = str_replace('[ends]' . $matches[1] . '[/ends]', EMPTY_STR, $body); + if (preg_match('/\[ends\](.*?)\[\/ends\]/ism', $body, $matches)) { + $obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', $matches[1], ATOM_TIME); + $body = str_replace('[ends]' . $matches[1] . '[/ends]', EMPTY_STR, $body); } @@ -1570,7 +1571,7 @@ class Item extends Controller { $obj['to'] = Activity::map_acl($item); } else { - $obj['to'] = [ ACTIVITY_PUBLIC_INBOX ]; + $obj['to'] = [ACTIVITY_PUBLIC_INBOX]; } return $obj; @@ -1580,23 +1581,23 @@ class Item extends Controller { function extract_poll_data($poll, $item) { - $multiple = intval($poll['multiple_answers']); + $multiple = intval($poll['multiple_answers']); $expire_value = intval($poll['expire_value']); - $expire_unit = $poll['expire_unit']; - $question = $poll['question']; - $answers = $poll['answers']; + $expire_unit = $poll['expire_unit']; + $question = $poll['question']; + $answers = $poll['answers']; - $obj = []; - $ptr = []; - $obj['type'] = 'Question'; + $obj = []; + $ptr = []; + $obj['type'] = 'Question'; $obj['content'] = bbcode($question); - foreach($answers as $answer) { - if(trim($answer)) - $ptr[] = [ 'name' => escape_tags($answer), 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]]; + foreach ($answers as $answer) { + if (trim($answer)) + $ptr[] = ['name' => escape_tags($answer), 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]]; } - if($multiple) { + if ($multiple) { $obj['anyOf'] = $ptr; } else { @@ -1605,11 +1606,13 @@ class Item extends Controller { $obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', 'now + ' . $expire_value . ' ' . $expire_unit, ATOM_TIME); + $obj['directMessage'] = (intval($item['item_private']) === 2); + if ($item['item_private']) { $obj['to'] = Activity::map_acl($item); } else { - $obj['to'] = [ ACTIVITY_PUBLIC_INBOX ]; + $obj['to'] = [ACTIVITY_PUBLIC_INBOX]; } return $obj; @@ -1617,5 +1620,4 @@ class Item extends Controller { } - } diff --git a/Zotlabs/Module/Lang.php b/Zotlabs/Module/Lang.php index a32f933a6..fe185ebea 100644 --- a/Zotlabs/Module/Lang.php +++ b/Zotlabs/Module/Lang.php @@ -7,16 +7,60 @@ use Zotlabs\Web\Controller; class Lang extends Controller { + const MYP = 'ZIN'; + const VERSION = '2.0.0'; + + function post() { + + $re = []; + $isajax = is_ajax(); + $eol = $isajax ? "\n" : EOL; + + if (! Apps::system_app_installed(local_channel(), 'Language')) { + $re['msg'] = 'ZIN0202E, ' . t('Language App') . ' (' . t('Not Installed') . ')' ; + notice( $re['msg'] . EOL); + if ($isajax) { + echo json_encode( $re ); + killme(); + exit; + } else { + return; + } + } + + $lc = x($_POST['zinlc']) && preg_match('/^\?\?|[a-z]{2,2}[x_\-]{0,1}[a-zA-Z]{0,2}$/', $_POST['zinlc']) + ? $_POST['zinlc'] : ''; + $lcs= x($_POST['zinlcs']) && preg_match('/^[a-z,_\-]{0,191}$/', $_POST['zinlcs']) + ? $_POST['zinlcs'] : ''; + + if ($isajax) { + + if ($lc == '??') { + $re['lc'] = get_best_language(); + $re['lcs'] = language_list(); + } else { + $re['lc'] = $lc; + $re['alc'] = App::$language; + $re['slc'] = $_SESSION['language']; + $_SESSION['language'] = $lc; + App::$language = $lc; + load_translation_table($lc, true); + } + + echo json_encode( $re ); + killme(); + exit; + } + } + function get() { if(local_channel()) { if(! Apps::system_app_installed(local_channel(), 'Language')) { - //Do not display any associated widgets at this point - App::$pdl = ''; - - $o = '<b>' . t('Language App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Change UI language'); - return $o; + //Do not display any associated widgets at this point + App::$pdl = ''; + $papp = Apps::get_papp('Language'); + return Apps::app_render($papp, 'module'); } } @@ -24,5 +68,5 @@ class Lang extends Controller { return lang_selector(); } - + } diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php index e3fe4a954..8b36e8396 100644 --- a/Zotlabs/Module/Like.php +++ b/Zotlabs/Module/Like.php @@ -91,6 +91,12 @@ class Like extends Controller { 'id' => $arr['item']['id'], 'html' => conversation($items, $conv_mode, true, $page_mode), ]; + + // mod photos + if (isset($_REQUEST['reload']) && $_REQUEST['reload']) { + $ret['reload'] = 1; + } + return $ret; } diff --git a/Zotlabs/Module/Linkinfo.php b/Zotlabs/Module/Linkinfo.php index 76c679cc5..038c739d5 100644 --- a/Zotlabs/Module/Linkinfo.php +++ b/Zotlabs/Module/Linkinfo.php @@ -5,37 +5,40 @@ namespace Zotlabs\Module; class Linkinfo extends \Zotlabs\Web\Controller { function get() { - + logger('linkinfo: ' . print_r($_REQUEST,true)); - + $text = null; $str_tags = ''; - $process_oembed = true; - + $process_oembed = true; + $br = "\n"; - + if(x($_GET,'binurl')) $url = trim(hex2bin($_GET['binurl'])); else $url = trim($_GET['url']); - + if(substr($url,0,1) === '!') { $process_oembed = false; $url = substr($url,1); } $url = strip_zids($url); - + if((substr($url,0,1) != '/') && (substr($url,0,4) != 'http')) $url = 'http://' . $url; - - + + $x = parse_url($url); + if ($x) + $url = str_replace($x['host'], punify($x['host']), $url); + if($_GET['title']) $title = strip_tags(trim($_GET['title'])); - + if($_GET['description']) $text = strip_tags(trim($_GET['description'])); - + if($_GET['tags']) { $arr_tags = str_getcsv($_GET['tags']); if(count($arr_tags)) { @@ -43,23 +46,25 @@ class Linkinfo extends \Zotlabs\Web\Controller { $str_tags = $br . implode(' ',$arr_tags) . $br; } } - + logger('linkinfo: ' . $url); - - // Replace plink URL with 'share' tag if possible - preg_match("/(mid=b64\.|display\/|posts\/)([\w\-]+)(&.+)?$/", $url, $mid); - - if (!empty($mid) && $mid[1] == 'mid=b64.') - $mid[2] = base64_decode($mid[2]); - - $r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1", - dbesc((empty($mid) ? $url : $mid[2])), - intval(local_channel()) - ); - if ($r) { - echo "[share=" . $r[0]['id'] . "][/share]"; - killme(); - } + + // Replace plink URL with 'share' tag if possible + preg_match("/(mid=b64\.|display\/|posts\/)([\w\-]+)(&.+)?$/", $url, $mid); + + if (!empty($mid)) { + $mid[2] = unpack_link_id($mid[2]); + } + + $r = q("SELECT id FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1", + dbesc((empty($mid) ? $url : $mid[2])), + intval(local_channel()) + ); + + if ($r) { + echo "[share=" . $r[0]['id'] . "][/share]"; + killme(); + } $result = z_fetch_url($url,false,0,array('novalidate' => true, 'nobody' => true)); if($result['success']) { @@ -108,13 +113,13 @@ class Linkinfo extends \Zotlabs\Web\Controller { } } } - + $template = $br . '#^[url=%s]%s[/url]%s' . $br; - + $arr = array('url' => $url, 'text' => ''); - + call_hooks('parse_link', $arr); - + if(strlen($arr['text'])) { echo $arr['text']; killme(); @@ -127,28 +132,28 @@ class Linkinfo extends \Zotlabs\Web\Controller { killme(); } } - + if($url && $title && $text) { - + $text = $br . '[quote]' . trim($text) . '[/quote]' . $br; - + $title = str_replace(array("\r","\n"),array('',''),$title); - + $result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags; - + logger('linkinfo (unparsed): returns: ' . $result); - + echo $result; killme(); } - + $siteinfo = self::parseurl_getsiteinfo($url); - + // If the site uses this platform, use zrl rather than url so they get zids sent to them by default - + if(is_matrix_url($url)) $template = str_replace('url','zrl',$template); - + if($siteinfo["title"] == "") { echo sprintf($template,$url,$url,'') . $str_tags; killme(); @@ -156,19 +161,19 @@ class Linkinfo extends \Zotlabs\Web\Controller { $text = $siteinfo["text"]; $title = $siteinfo["title"]; } - + $image = ""; if(is_array($siteinfo["images"]) && count($siteinfo["images"])){ /* Execute below code only if image is present in siteinfo */ - + $total_images = 0; $max_images = get_config('system','max_bookmark_images'); if($max_images === false) $max_images = 2; else $max_images = intval($max_images); - + foreach ($siteinfo["images"] as $imagedata) { if ($url) { $image .= sprintf('[url=%s]', $url); @@ -183,57 +188,57 @@ class Linkinfo extends \Zotlabs\Web\Controller { break; } } - + if(strlen($text)) { $text = $br.'[quote]'.trim($text).'[/quote]'.$br ; } - + if($image) { $text = $br.$br.$image.$text; } $title = str_replace(array("\r","\n"),array('',''),$title); - + $result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags; - + logger('linkinfo: returns: ' . $result, LOGGER_DEBUG); - + echo trim($result); killme(); - + } - - + + public static function deletexnode(&$doc, $node) { $xpath = new \DomXPath($doc); $list = $xpath->query("//".$node); foreach ($list as $child) $child->parentNode->removeChild($child); } - + public static function completeurl($url, $scheme) { $urlarr = parse_url($url); - + if (isset($urlarr["scheme"])) return($url); - + $schemearr = parse_url($scheme); - + $complete = $schemearr["scheme"]."://".$schemearr["host"]; - + if ($schemearr["port"] != "") $complete .= ":".$schemearr["port"]; - + if(strpos($urlarr['path'],'/') !== 0) $complete .= '/'; - + $complete .= $urlarr["path"]; - + if ($urlarr["query"] != "") $complete .= "?".$urlarr["query"]; - + if ($urlarr["fragment"] != "") $complete .= "#".$urlarr["fragment"]; - + return($complete); } @@ -251,7 +256,7 @@ class Linkinfo extends \Zotlabs\Web\Controller { $p = substr($m,strpos($m,'/')+1); // get the channel to check permissions - + $u = channelx_by_nick($nick); if($u && $p) { @@ -272,18 +277,18 @@ class Linkinfo extends \Zotlabs\Web\Controller { return EMPTY_STR; } - + public static function parseurl_getsiteinfo($url) { $siteinfo = array(); - - + + $result = z_fetch_url($url,false,0,array('novalidate' => true)); if(! $result['success']) return $siteinfo; - + $header = $result['header']; $body = $result['body']; - + // Check codepage in HTTP headers or HTML if not exist $cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : ''); if(empty($cp)) @@ -291,10 +296,10 @@ class Linkinfo extends \Zotlabs\Web\Controller { $body = mb_convert_encoding($body, 'UTF-8', $cp); $body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8"); - + $doc = new \DOMDocument(); @$doc->loadHTML($body); - + self::deletexnode($doc, 'style'); self::deletexnode($doc, 'script'); self::deletexnode($doc, 'option'); @@ -306,14 +311,14 @@ class Linkinfo extends \Zotlabs\Web\Controller { self::deletexnode($doc, 'h6'); self::deletexnode($doc, 'ol'); self::deletexnode($doc, 'ul'); - + $xpath = new \DomXPath($doc); - + //$list = $xpath->query("head/title"); $list = $xpath->query("//title"); foreach ($list as $node) $siteinfo["title"] = html_entity_decode($node->nodeValue, ENT_QUOTES, "UTF-8"); - + //$list = $xpath->query("head/meta[@name]"); $list = $xpath->query("//meta[@name]"); foreach ($list as $node) { @@ -321,9 +326,9 @@ class Linkinfo extends \Zotlabs\Web\Controller { if ($node->attributes->length) foreach ($node->attributes as $attribute) $attr[$attribute->name] = $attribute->value; - + $attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"); - + switch (strtolower($attr["name"])) { case "fulltitle": $siteinfo["title"] = trim($attr["content"]); @@ -365,7 +370,7 @@ class Linkinfo extends \Zotlabs\Web\Controller { break; } } - + //$list = $xpath->query("head/meta[@property]"); $list = $xpath->query("//meta[@property]"); foreach ($list as $node) { @@ -373,9 +378,9 @@ class Linkinfo extends \Zotlabs\Web\Controller { if ($node->attributes->length) foreach ($node->attributes as $attribute) $attr[$attribute->name] = $attribute->value; - + $attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"); - + switch (strtolower($attr["property"])) { case "og:image": $siteinfo["image"] = $attr["content"]; @@ -388,7 +393,7 @@ class Linkinfo extends \Zotlabs\Web\Controller { break; } } - + if ($siteinfo["image"] == "") { $list = $xpath->query("//img[@src]"); foreach ($list as $node) { @@ -396,10 +401,10 @@ class Linkinfo extends \Zotlabs\Web\Controller { if ($node->attributes->length) foreach ($node->attributes as $attribute) $attr[$attribute->name] = $attribute->value; - + $src = self::completeurl($attr["src"], $url); $photodata = @getimagesize($src); - + if (($photodata) && ($photodata[0] > 150) and ($photodata[1] > 150)) { if ($photodata[0] > 300) { $photodata[1] = round($photodata[1] * (300 / $photodata[0])); @@ -413,36 +418,36 @@ class Linkinfo extends \Zotlabs\Web\Controller { "width"=>$photodata[0], "height"=>$photodata[1]); } - + } } else { $src = self::completeurl($siteinfo["image"], $url); - + unset($siteinfo["image"]); - + $photodata = @getimagesize($src); - + if (($photodata) && ($photodata[0] > 10) and ($photodata[1] > 10)) $siteinfo["images"][] = array("src"=>$src, "width"=>$photodata[0], "height"=>$photodata[1]); } - + if ($siteinfo["text"] == "") { $text = ""; - + $list = $xpath->query("//div[@class='article']"); foreach ($list as $node) if (strlen($node->nodeValue) > 40) $text .= " ".trim($node->nodeValue); - + if ($text == "") { $list = $xpath->query("//div[@class='content']"); foreach ($list as $node) if (strlen($node->nodeValue) > 40) $text .= " ".trim($node->nodeValue); } - + // If none text was found then take the paragraph content if ($text == "") { $list = $xpath->query("//p"); @@ -450,21 +455,21 @@ class Linkinfo extends \Zotlabs\Web\Controller { if (strlen($node->nodeValue) > 40) $text .= " ".trim($node->nodeValue); } - + if ($text != "") { $text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text)); - + while (strpos($text, " ")) $text = trim(str_replace(" ", " ", $text)); - + $text = substr(html_entity_decode($text, ENT_QUOTES, "UTF-8"), 0, 350); $siteinfo["text"] = rtrim(substr($text, 0, strrpos($text, " ")), "?.,:;!-") . '...'; } } - + return($siteinfo); } - + private static function arr_add_hashes(&$item,$k) { $item = '#' . $item; diff --git a/Zotlabs/Module/Lockview.php b/Zotlabs/Module/Lockview.php index 11c781df0..3637482c7 100644 --- a/Zotlabs/Module/Lockview.php +++ b/Zotlabs/Module/Lockview.php @@ -1,21 +1,30 @@ <?php + namespace Zotlabs\Module; +use Zotlabs\Lib\AccessList; +use Zotlabs\Web\Controller; + require_once('include/security.php'); -class Lockview extends \Zotlabs\Web\Controller { +class Lockview extends Controller { function get() { - $atokens = array(); + $atokens = []; + $atoken_xchans = []; + $access_list = []; + $guest_access_list = []; - if(local_channel()) { + if (local_channel()) { $at = q("select * from atoken where atoken_uid = %d", intval(local_channel()) ); - if($at) { - foreach($at as $t) { - $atokens[] = atoken_xchan($t); + if ($at) { + foreach ($at as $t) { + $atoken_xchan = atoken_xchan($t); + $atokens[] = array_merge($t, $atoken_xchan); + $atoken_xchans[] = $atoken_xchan['xchan_hash']; } } } @@ -23,20 +32,20 @@ class Lockview extends \Zotlabs\Web\Controller { $type = ((argc() > 1) ? argv(1) : 0); if (is_numeric($type)) { $item_id = intval($type); - $type='item'; + $type = 'item'; } else { $item_id = ((argc() > 2) ? intval(argv(2)) : 0); } - if(! $item_id) + if (!$item_id) killme(); - if (! in_array($type, array('item', 'photo', 'attach', 'event', 'menu_item', 'chatroom'))) + if (!in_array($type, ['item', 'photo', 'attach', 'menu_item', 'chatroom'])) killme(); // we have different naming in in menu_item table and chatroom table - switch($type) { + switch ($type) { case 'menu_item': $id = 'mitem_id'; break; @@ -53,134 +62,177 @@ class Lockview extends \Zotlabs\Web\Controller { intval($item_id) ); - if(! $r) + if (!$r) killme(); $item = $r[0]; + $uid = null; + $url = ''; - //we have different naming in in menu_item table and chatroom table - switch($type) { + switch ($type) { case 'menu_item': $uid = $item['mitem_channel_id']; break; case 'chatroom': - $uid = $item['cr_uid']; + $uid = $item['cr_uid']; + $channel = channelx_by_n($uid); + $url = z_root() . '/chat/' . $channel['channel_address'] . '/' . $item['cr_id']; break; - default: + case 'item': $uid = $item['uid']; + $url = $item['plink']; + break; + case 'photo': + $uid = $item['uid']; + $channel = channelx_by_n($uid); + $url = z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $item['resource_id']; + break; + case 'attach': + $uid = $item['uid']; + $channel = channelx_by_n($uid); + $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $item['display_path']; + break; + default: break; } - if($uid != local_channel()) { - echo '<div class="dropdown-item">' . t('Remote privacy information not available.') . '</div>'; + if (intval($uid) !== local_channel()) { + echo '<div class="dropdown-item-text">' . t('Remote privacy information not available') . '</div>'; killme(); } - if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid'])) - && (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) { + if (intval($item['item_private']) && (!strlen($item['allow_cid'])) && (!strlen($item['allow_gid'])) + && (!strlen($item['deny_cid'])) && (!strlen($item['deny_gid']))) { // if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any // specific recipients, we're the recipient of a post with "bcc" or targeted recipients; so we'll just show it // as unknown specific recipients. The sender will have the visibility list and will fall through to the // next section. - echo '<div class="dropdown-item">' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>'; + echo '<div class="dropdown-item-text">' . translate_scope((!$item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>'; killme(); } - $allowed_users = expand_acl($item['allow_cid']); + $allowed_users = expand_acl($item['allow_cid']); $allowed_groups = expand_acl($item['allow_gid']); - $deny_users = expand_acl($item['deny_cid']); - $deny_groups = expand_acl($item['deny_gid']); - - $o = '<div class="dropdown-item">' . t('Visible to:') . '</div>'; - $l = array(); + $deny_users = expand_acl($item['deny_cid']); + $deny_groups = expand_acl($item['deny_gid']); - stringify_array_elms($allowed_groups,true); - stringify_array_elms($allowed_users,true); - stringify_array_elms($deny_groups,true); - stringify_array_elms($deny_users,true); + stringify_array_elms($allowed_groups, true); + stringify_array_elms($allowed_users, true); + stringify_array_elms($deny_groups, true); + stringify_array_elms($deny_users, true); + $allowed_xchans = []; $profile_groups = []; - if($allowed_groups) { - foreach($allowed_groups as $g) { - if(substr($g,0,4) === '\'vp.') { - $profile_groups[] = '\'' . substr($g,4); + if ($allowed_groups) { + foreach ($allowed_groups as $g) { + if (substr($g, 0, 4) === '\'vp.') { + $profile_groups[] = '\'' . substr($g, 4); } } } - if(count($profile_groups)) { - $r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )"); - if($r) - foreach($r as $rr) - $l[] = '<div class="dropdown-item"><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></div>'; - } - - if(count($allowed_groups)) { - $r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )"); - if($r) - foreach($r as $rr) - $l[] = '<div class="dropdown-item"><b>' . $rr['gname'] . '</b></div>'; - } - if(count($allowed_users)) { - $r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ',$allowed_users) . " )"); - if($r) - foreach($r as $rr) - $l[] = '<div class="dropdown-item">' . $rr['xchan_name'] . '</div>'; - if($atokens) { - foreach($atokens as $at) { - if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) { - $l[] = '<div class="dropdown-item">' . $at['xchan_name'] . '</div>'; - } + + if ($profile_groups) { + $r = q("SELECT id, profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )"); + if ($r) { + foreach ($r as $rr) { + $pgrp_members = AccessList::profile_members_xchan($uid, $rr['id']); + $allowed_xchans = array_merge($allowed_xchans, $pgrp_members); + $access_list[] = '<div class="dropdown-item-text" title="' . t('Profile', 'acl') . '">' . $rr['profile_name'] . '</div>'; + } + } + } + + if ($allowed_groups) { + $r = q("SELECT id, gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )"); + if ($r) { + foreach ($r as $rr) { + $pgrp_members = AccessList::members_xchan($uid, $rr['id']); + $allowed_xchans = array_merge($allowed_xchans, $pgrp_members); + $access_list[] = '<div class="dropdown-item-text" title="' . t('Privacy group') . '">' . $rr['gname'] . '</div>'; } } } + if ($allowed_users) { + $r = q("SELECT xchan_name, xchan_hash FROM xchan WHERE xchan_hash IN ( " . implode(', ', $allowed_users) . " )"); + if ($r) { + foreach ($r as $rr) { + $allowed_xchans[] = $rr['xchan_hash']; + if (!in_array($rr['xchan_hash'], $atoken_xchans)) { + $access_list[] = '<div class="dropdown-item-text">' . $rr['xchan_name'] . '</div>'; + } + } + } + } $profile_groups = []; - if($deny_groups) { - foreach($deny_groups as $g) { - if(substr($g,0,4) === '\'vp.') { - $profile_groups[] = '\'' . substr($g,4); + if ($deny_groups) { + foreach ($deny_groups as $g) { + if (substr($g, 0, 4) === '\'vp.') { + $profile_groups[] = '\'' . substr($g, 4); } } } - if(count($profile_groups)) { + + if ($profile_groups) { $r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )"); - if($r) - foreach($r as $rr) - $l[] = '<div class="dropdown-item"><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></div>'; + if ($r) { + foreach ($r as $rr) { + $access_list[] = '<div class="dropdown-item-text" title="' . t('Profile', 'acl') . '"><strike>' . $rr['profile_name'] . '</strike></b></div>'; + } + } } - - - if(count($deny_groups)) { + if ($deny_groups) { $r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $deny_groups) . " )"); - if($r) - foreach($r as $rr) - $l[] = '<div class="dropdown-item"><b><strike>' . $rr['gname'] . '</strike></b></div>'; + if ($r) { + foreach ($r as $rr) { + $access_list[] = '<div class="dropdown-item-text" title="' . t('Privacy group') . '"><strike>' . $rr['gname'] . '</strike></b></div>'; + } + } } - if(count($deny_users)) { + + if ($deny_users) { $r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )"); - if($r) - foreach($r as $rr) - $l[] = '<div class="dropdown-item"><strike>' . $rr['xchan_name'] . '</strike></div>'; - - if($atokens) { - foreach($atokens as $at) { - if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) { - $l[] = '<div class="dropdown-item"><strike>' . $at['xchan_name'] . '</strike></div>'; - } + if ($r) { + foreach ($r as $rr) { + $access_list[] = '<div class="dropdown-item-text"><strike>' . $rr['xchan_name'] . '</strike></div>'; } } + } + + if ($atokens && $allowed_xchans && $url) { + $guest_access_list = []; + $allowed_xchans = array_unique($allowed_xchans); + foreach ($atokens as $atoken) { + if (in_array($atoken['xchan_hash'], $allowed_xchans)) { + $guest_access_list[] = '<div class="dropdown-item d-flex justify-content-between cursor-pointer" title="' . sprintf(t('Click to copy link to this ressource for guest %s to clipboard'), $atoken['xchan_name']) . '" data-token="' . $url . '?zat=' . $atoken['atoken_token'] . '" onclick="navigator.clipboard.writeText(this.dataset.token); $.jGrowl(\'' . t('Link copied') . '\', { sticky: false, theme: \'info\', life: 1000 });"><span>' . $atoken['xchan_name'] . '</span><i class="fa fa-copy p-1"></i></div>'; + } + } } - echo $o . implode($l); - killme(); + $access_list_header = ''; + if ($access_list) { + $access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Access') . '</div>'; + } + $guest_access_list_header = ''; + if ($guest_access_list) { + $guest_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Guest access') . '</div>'; + } + + $divider = ''; + if ($access_list && $guest_access_list) { + $divider = '<div class="dropdown-divider"></div>'; + } + + echo $access_list_header . implode($access_list) . $divider . $guest_access_list_header . implode($guest_access_list); + killme(); } diff --git a/Zotlabs/Module/Locs.php b/Zotlabs/Module/Locs.php index 2dd359c95..1ece47231 100644 --- a/Zotlabs/Module/Locs.php +++ b/Zotlabs/Module/Locs.php @@ -28,9 +28,8 @@ class Locs extends Controller { return; } - q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND (hubloc_hash = '%s' OR hubloc_hash = '%s')", - dbesc($channel['channel_hash']), - dbesc($channel['channel_portable_id']) + q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND hubloc_hash = '%s'", + dbesc($channel['channel_hash']) ); q("UPDATE hubloc SET hubloc_primary = 1 WHERE hubloc_id = %d AND hubloc_hash = '%s'", @@ -81,10 +80,9 @@ class Locs extends Controller { } } - q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND (hubloc_hash = '%s' OR hubloc_hash = '%s')", + q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND hubloc_hash = '%s'", dbesc($r[0]['hubloc_id_url']), - dbesc($channel['channel_hash']), - dbesc($channel['channel_portable_id']) + dbesc($channel['channel_hash']) ); Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] ); return; @@ -118,11 +116,6 @@ class Locs extends Controller { return; } - for($x = 0; $x < count($r); $x ++) { - $r[$x]['primary'] = (intval($r[$x]['hubloc_primary']) ? true : false); - $r[$x]['deleted'] = (intval($r[$x]['hubloc_deleted']) ? true : false); - } - $o = replace_macros(get_markup_template('locmanage.tpl'), array( '$header' => t('Manage Channel Locations'), '$loc' => t('Location'), @@ -134,7 +127,8 @@ class Locs extends Controller { '$sync_text' => t('Please wait several minutes between consecutive operations.'), '$drop_text' => t('When possible, drop a location by logging into that website/hub and removing your channel.'), '$last_resort' => t('Use this form to drop the location if the hub is no longer operating.'), - '$hubs' => $r + '$hubs' => $r, + '$base_url' => z_root() )); return $o; diff --git a/Zotlabs/Module/Manage.php b/Zotlabs/Module/Manage.php index bc2034b95..3f168c15d 100644 --- a/Zotlabs/Module/Manage.php +++ b/Zotlabs/Module/Manage.php @@ -61,7 +61,7 @@ class Manage extends \Zotlabs\Web\Controller { $channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : ''); $channels[$x]['default_links'] = '1'; - + /* this is not currently implemented in the UI and probably should not (performance) $c = q("SELECT id, item_wall FROM item WHERE item_unseen = 1 and uid = %d " . item_normal(), intval($channels[$x]['channel_id']) @@ -75,7 +75,7 @@ class Manage extends \Zotlabs\Web\Controller { $channels[$x]['network'] ++; } } - + */ $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ", intval($channels[$x]['channel_id']) @@ -84,16 +84,7 @@ class Manage extends \Zotlabs\Web\Controller { if($intr) $channels[$x]['intros'] = intval($intr[0]['total']); - - $mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ", - intval($channels[$x]['channel_id']), - dbesc($channels[$x]['channel_hash']) - ); - - if($mails) - $channels[$x]['mail'] = intval($mails[0]['total']); - - + /* this is not currently implemented in the UI and probably should not (performance) $events = q("SELECT etype, dtstart, adjust FROM event WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0 ORDER BY dtstart ASC ", @@ -126,6 +117,7 @@ class Manage extends \Zotlabs\Web\Controller { } } } + */ } } @@ -167,7 +159,7 @@ class Manage extends \Zotlabs\Web\Controller { } $o = replace_macros(get_markup_template('channels.tpl'), array( - '$header' => t('Channel Manager'), + '$header' => t('Channels'), '$msg_selected' => t('Current Channel'), '$selected' => local_channel(), '$desc' => ((count($channels) > 1 || $delegates) ? t('Switch to one of your channels by selecting it.') : ''), @@ -175,7 +167,6 @@ class Manage extends \Zotlabs\Web\Controller { '$msg_make_default' => t('Make Default'), '$create' => $create, '$all_channels' => $channels, - '$mail_format' => t('%d new messages'), '$intros_format' => t('%d new introductions'), '$channel_usage_message' => $channel_usage_message, '$delegated_desc' => t('Delegated Channel'), diff --git a/Zotlabs/Module/Manifest.php b/Zotlabs/Module/Manifest.php new file mode 100644 index 000000000..4c418a56a --- /dev/null +++ b/Zotlabs/Module/Manifest.php @@ -0,0 +1,55 @@ +<?php +namespace Zotlabs\Module; + +use App; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\System; +use Zotlabs\Render\Theme; + +class Manifest extends Controller { + + function init() { + + // populate App::$theme_info + Theme::current(); + + $ret = [ + 'name' => ucfirst(System::get_platform_name()), + 'short_name' => ucfirst(System::get_platform_name()), + 'icons' => [ + [ 'src' => '/images/app/hz-72.png', 'sizes' => '72x72', 'type' => 'image/png' ], + [ 'src' => '/images/app/hz-96.png', 'sizes' => '96x96', 'type' => 'image/png' ], + [ 'src' => '/images/app/hz-128.png', 'sizes' => '128x128', 'type' => 'image/png' ], + [ 'src' => '/images/app/hz-144.png', 'sizes' => '144x144', 'type' => 'image/png' ], + [ 'src' => '/images/app/hz-152.png', 'sizes' => '152x152', 'type' => 'image/png' ], + [ 'src' => '/images/app/hz-192.png', 'sizes' => '192x192', 'type' => 'image/png', 'purpose' => 'any maskable' ], + [ 'src' => '/images/app/hz-348.png', 'sizes' => '384x384', 'type' => 'image/png' ], + [ 'src' => '/images/app/hz-512.png', 'sizes' => '512x512', 'type' => 'image/png' ], + [ 'src' => '/images/app/hz.svg', 'sizes' => '64x64', 'type' => 'image/xml+svg' ] + ], + 'theme_color' => App::$theme_info['theme_color'], + 'background_color' => App::$theme_info['background_color'], + 'scope' => '/', + 'start_url' => z_root(), + 'display' => 'standalone', + 'share_target' => [ + 'action' => '/rpost', + 'method' => 'POST', + 'enctype' => 'multipart/form-data', + 'params' => [ + 'title' => 'title', + 'text' => 'body', + 'url' => 'url', + 'files' => [ + [ 'name' => 'userfile', + 'accept' => [ 'image/*', 'audio/*', 'video/*', 'text/*', 'application/*' ] + ] + ] + ] + ] + ]; + + json_return_and_die($ret,'application/manifest+json'); + } + +} diff --git a/Zotlabs/Module/Message.php b/Zotlabs/Module/Message.php deleted file mode 100644 index 5856bfbdf..000000000 --- a/Zotlabs/Module/Message.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php -namespace Zotlabs\Module; - -require_once('include/acl_selectors.php'); -require_once('include/message.php'); -require_once('include/zot.php'); -require_once("include/bbcode.php"); - - -class Message extends \Zotlabs\Web\Controller { - - function get() { - - $o = ''; - nav_set_selected('messages'); - - if(! local_channel()) { - notice( t('Permission denied.') . EOL); - return login(); - } - - $channel = \App::get_channel(); - head_set_icon($channel['xchan_photo_s']); - - $cipher = get_pconfig(local_channel(),'system','default_cipher'); - if(! $cipher) - $cipher = 'aes256'; - - /* - if((argc() == 3) && (argv(1) === 'dropconv')) { - if(! intval(argv(2))) - return; - $cmd = argv(1); - $r = private_messages_drop(local_channel(), argv(2), true); - if($r) - info( t('Conversation removed.') . EOL ); - goaway(z_root() . '/mail/combined' ); - } - - if(argc() == 2) { - - switch(argv(1)) { - case 'combined': - $mailbox = 'combined'; - $header = t('Conversations'); - break; - case 'inbox': - $mailbox = 'inbox'; - $header = t('Received Messages'); - break; - case 'outbox': - $mailbox = 'outbox'; - $header = t('Sent Messages'); - break; - default: - break; - } - - // private_messages_list() can do other more complicated stuff, for now keep it simple - - $r = private_messages_list(local_channel(), $mailbox, \App::$pager['start'], \App::$pager['itemspage']); - - if(! $r) { - info( t('No messages.') . EOL); - return $o; - } - - $messages = array(); - - foreach($r as $rr) { - - $messages[] = array( - 'id' => $rr['id'], - 'from_name' => $rr['from']['xchan_name'], - 'from_url' => chanlink_hash($rr['from_xchan']), - 'from_photo' => $rr['from']['xchan_photo_s'], - 'to_name' => $rr['to']['xchan_name'], - 'to_url' => chanlink_hash($rr['to_xchan']), - 'to_photo' => $rr['to']['xchan_photo_s'], - 'subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'), - 'delete' => t('Delete conversation'), - 'body' => zidify_links(smilies(bbcode($rr['body']))), - 'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], t('D, d M Y - g:i A')), - 'seen' => $rr['seen'] - ); - } - - - $tpl = get_markup_template('mail_head.tpl'); - $o = replace_macros($tpl, array( - '$header' => $header, - '$messages' => $messages - )); - - - $o .= alt_pager(count($r)); - - return $o; - - return; - - } - */ - - return; - } - -} diff --git a/Zotlabs/Module/Mood.php b/Zotlabs/Module/Mood.php index 453f08f9f..cb2ca566b 100644 --- a/Zotlabs/Module/Mood.php +++ b/Zotlabs/Module/Mood.php @@ -14,36 +14,36 @@ require_once('include/items.php'); class Mood extends Controller { function init() { - + if(! local_channel()) return; if(! Apps::system_app_installed(local_channel(), 'Mood')) { return; } - + $uid = local_channel(); $channel = App::get_channel(); $verb = notags(trim($_GET['verb'])); - - if(! $verb) + + if(! $verb) return; - + $verbs = get_mood_verbs(); - + if(! array_key_exists($verb,$verbs)) return; - + $activity = ACTIVITY_MOOD . '#' . urlencode($verb); - + $parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : 0); - - + + logger('mood: verb ' . $verb, LOGGER_DEBUG); - - + + if($parent) { - $r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid + $r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid from item where id = %d and parent = %d and uid = %d limit 1", intval($parent), intval($parent), @@ -59,24 +59,24 @@ class Mood extends Controller { } } else { - + $private = 0; - + $allow_cid = $channel['channel_allow_cid']; $allow_gid = $channel['channel_allow_gid']; $deny_cid = $channel['channel_deny_cid']; $deny_gid = $channel['channel_deny_gid']; } - + $poster = App::get_observer(); - + $uuid = item_message_id(); $mid = z_root() . '/item/' . $uuid; - - $action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]); - + + $action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]); + $arr = array(); - + $arr['aid'] = get_account_id(); $arr['uid'] = $uid; $arr['uuid'] = $uuid; @@ -97,31 +97,31 @@ class Mood extends Controller { $arr['item_unseen'] = 1; if(! $parent_mid) $item['item_thread_top'] = 1; - + if ((! $arr['plink']) && intval($arr['item_thread_top'])) { $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']); } - - + + $post = item_store($arr); $item_id = $post['item_id']; - + if($item_id) { \Zotlabs\Daemon\Master::Summon(array('Notifier','activity', $item_id)); } - + call_hooks('post_local_end', $arr); - + if($_SESSION['return_url']) goaway(z_root() . '/' . $_SESSION['return_url']); - + return; } - - - + + + function get() { - + if(! local_channel()) { notice( t('Permission denied.') . EOL); return; @@ -130,26 +130,24 @@ class Mood extends Controller { if(! Apps::system_app_installed(local_channel(), 'Mood')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Mood App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Set your current mood and tell your friends'); - return $o; + $papp = Apps::get_papp('Mood'); + return Apps::app_render($papp, 'module'); } nav_set_selected('Mood'); $parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : '0'); - + $verbs = get_mood_verbs(); - + $shortlist = array(); foreach($verbs as $k => $v) if($v !== 'NOTRANSLATION') $shortlist[] = array($k,$v); - - + + $tpl = get_markup_template('mood_content.tpl'); - + $o = replace_macros($tpl,array( '$title' => t('Mood'), '$desc' => t('Set your current mood and tell your friends'), @@ -157,9 +155,9 @@ class Mood extends Controller { '$parent' => $parent, '$submit' => t('Submit'), )); - + return $o; - + } - + } diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index a21095940..f4f6cc8d1 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -1,12 +1,11 @@ <?php namespace Zotlabs\Module; -use Zotlabs\Lib\Group; +use Zotlabs\Lib\AccessList; use Zotlabs\Lib\Apps; use App; require_once('include/items.php'); -require_once('include/group.php'); require_once('include/contact_widgets.php'); require_once('include/conversation.php'); require_once('include/acl_selectors.php'); @@ -22,11 +21,11 @@ class Network extends \Zotlabs\Web\Controller { $search = $_GET['search'] ?? ''; - if(in_array(substr($search, 0, 1),[ '@', '!', '?']) || strpos($search, 'https://') === 0) + if(in_array(substr($search, 0, 1), [ '@', '!', '?']) || strpos($search, 'https://') === 0) goaway(z_root() . '/search?f=&search=' . $search); if(count($_GET) < 2) { - $network_options = get_pconfig(local_channel(),'system','network_page_default'); + $network_options = get_pconfig(local_channel(), 'system', 'network_page_default'); if($network_options) goaway(z_root() . '/network?f=&' . $network_options); } @@ -84,7 +83,7 @@ class Network extends \Zotlabs\Web\Controller { $search = $_GET['search'] ?? ''; if($search) { - if(strpos($search,'#') === 0) { + if(strpos($search, '#') === 0) { $hashtags = substr($search,1); $search = ''; } @@ -114,31 +113,31 @@ class Network extends \Zotlabs\Web\Controller { $def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>'); } - $default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1)); - $default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1)); - - $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0); - $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0); - $liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0); - $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0); - $spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0); - $cmin = ((array_key_exists('cmin',$_GET)) ? intval($_GET['cmin']) : $default_cmin); - $cmax = ((array_key_exists('cmax',$_GET)) ? intval($_GET['cmax']) : $default_cmax); - $file = ((x($_GET,'file')) ? $_GET['file'] : ''); - $xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : ''); - $net = ((x($_GET,'net')) ? $_GET['net'] : ''); - $pf = ((x($_GET,'pf')) ? $_GET['pf'] : ''); - $unseen = ((x($_GET,'unseen')) ? $_GET['unseen'] : ''); - - if (Apps::system_app_installed(local_channel(),'Affinity Tool')) { - $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); + $default_cmin = ((Apps::system_app_installed(local_channel(), 'Affinity Tool')) ? get_pconfig(local_channel(), 'affinity', 'cmin', 0) : (-1)); + $default_cmax = ((Apps::system_app_installed(local_channel(), 'Affinity Tool')) ? get_pconfig(local_channel(), 'affinity', 'cmax', 99) : (-1)); + + $cid = ((x($_GET, 'cid')) ? intval($_GET['cid']) : 0); + $star = ((x($_GET, 'star')) ? intval($_GET['star']) : 0); + $liked = ((x($_GET, 'liked')) ? intval($_GET['liked']) : 0); + $conv = ((x($_GET, 'conv')) ? intval($_GET['conv']) : 0); + $spam = ((x($_GET, 'spam')) ? intval($_GET['spam']) : 0); + $cmin = ((array_key_exists('cmin', $_GET)) ? intval($_GET['cmin']) : $default_cmin); + $cmax = ((array_key_exists('cmax', $_GET)) ? intval($_GET['cmax']) : $default_cmax); + $file = ((x($_GET, 'file')) ? $_GET['file'] : ''); + $xchan = ((x($_GET, 'xchan')) ? $_GET['xchan'] : ''); + $net = ((x($_GET, 'net')) ? $_GET['net'] : ''); + $pf = ((x($_GET, 'pf')) ? $_GET['pf'] : ''); + $unseen = ((x($_GET, 'unseen')) ? $_GET['unseen'] : ''); + + if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) { + $affinity_locked = intval(get_pconfig(local_channel(), 'affinity', 'lock', 1)); if ($affinity_locked) { - set_pconfig(local_channel(),'affinity','cmin',$cmin); - set_pconfig(local_channel(),'affinity','cmax',$cmax); + set_pconfig(local_channel(), 'affinity', 'cmin', $cmin); + set_pconfig(local_channel(), 'affinity', 'cmax', $cmax); } } - if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen) + if(x($_GET, 'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen) $nouveau = true; $cid_r = []; @@ -164,8 +163,8 @@ class Network extends \Zotlabs\Web\Controller { // search terms header if($search || $hashtags) { - $o .= replace_macros(get_markup_template("section_title.tpl"),array( - '$title' => t('Search Results For:') . ' ' . (($search) ? htmlspecialchars($search, ENT_COMPAT,'UTF-8') : '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8')) + $o .= replace_macros(get_markup_template('section_title.tpl'), array( + '$title' => t('Search Results For:') . ' ' . (($search) ? htmlspecialchars($search, ENT_COMPAT, 'UTF-8') : '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8')) )); } @@ -193,7 +192,7 @@ class Network extends \Zotlabs\Web\Controller { $x = array( 'is_owner' => true, - 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), + 'allow_location' => ((intval(get_pconfig($channel['channel_id'], 'system', 'use_browser_location'))) ? '1' : ''), 'default_location' => $channel['channel_location'], 'nickname' => $channel['channel_address'], 'lockstate' => (($private_editing || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), @@ -209,7 +208,7 @@ class Network extends \Zotlabs\Web\Controller { 'reset' => t('Reset form') ); - $status_editor = status_editor($a,$x,false,'Network'); + $status_editor = status_editor($a, $x, false, 'Network'); $o .= $status_editor; } @@ -221,7 +220,7 @@ class Network extends \Zotlabs\Web\Controller { $sql_options = (($star) - ? " and item_starred = 1 " + ? ' and item_starred = 1 ' : ''); $sql_nets = ''; @@ -233,9 +232,9 @@ class Network extends \Zotlabs\Web\Controller { if($group) { $contact_str = ''; - $contacts = group_get_members($group); + $contacts = AccessList::members(local_channel(), $group); if($contacts) { - $contact_str = ids_to_querystr($contacts,'xchan',true); + $contact_str = ids_to_querystr($contacts, 'xchan', true); } else { $contact_str = " '0' "; @@ -246,10 +245,10 @@ class Network extends \Zotlabs\Web\Controller { $item_thread_top = ''; $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent $item_normal ) "; - $x = group_rec_byhash(local_channel(), $group_hash); + $x = AccessList::by_hash(local_channel(), $group_hash); if($x) { - $title = replace_macros(get_markup_template("section_title.tpl"),array( + $title = replace_macros(get_markup_template('section_title.tpl'), array( '$title' => t('Privacy group: ') . $x['gname'] )); } @@ -273,15 +272,17 @@ class Network extends \Zotlabs\Web\Controller { $likes_sql = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; // This is for nouveau view public forum cid queries (if a forum notification is clicked) - $p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'", - intval(local_channel()), - intval(TERM_FORUM), - dbesc($cid_r[0]['xchan_name']) - ); + //$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'", + //intval(local_channel()), + //intval(TERM_FORUM), + //dbesc($cid_r[0]['xchan_name']) + //); - $p_str = ids_to_querystr($p, 'parent'); - if($p_str) - $p_sql = " OR item.parent IN ( $p_str ) "; + //$p_str = ids_to_querystr($p, 'parent'); + + $p_sql = ''; + //if($p_str) + //$p_sql = " OR item.parent IN ( $p_str ) "; $sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 $likes_sql "; } @@ -289,10 +290,10 @@ class Network extends \Zotlabs\Web\Controller { // This is for threaded view cid queries (e.g. if a forum is selected from the forum filter) $ttype = (($pf) ? TERM_FORUM : TERM_MENTION); - $p1 = q("SELECT DISTINCT parent FROM item WHERE uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' OR owner_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' ) $item_normal "); - $p2 = q("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . dbesc($cid_r[0]['xchan_name']) . "'"); + $p1 = dbq("SELECT DISTINCT parent FROM item WHERE uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' OR owner_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' ) $item_normal "); + $p2 = dbq("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . dbesc($cid_r[0]['xchan_name']) . "'"); - $p_str = ids_to_querystr(array_merge($p1,$p2),'parent'); + $p_str = ids_to_querystr(array_merge($p1, $p2), 'parent'); if(! $p_str) killme(); @@ -300,7 +301,7 @@ class Network extends \Zotlabs\Web\Controller { } } - $title = replace_macros(get_markup_template("section_title.tpl"),array( + $title = replace_macros(get_markup_template('section_title.tpl'), array( '$title' => '<a href="' . zid($cid_r[0]['xchan_url']) . '" ><img src="' . zid($cid_r[0]['xchan_photo_s']) . '" alt="' . urlencode($cid_r[0]['xchan_name']) . '" /></a> <a href="' . zid($cid_r[0]['xchan_url']) . '" >' . $cid_r[0]['xchan_name'] . '</a>' )); @@ -314,7 +315,7 @@ class Network extends \Zotlabs\Web\Controller { if($r) { $item_thread_top = ''; $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($xchan) . "' or owner_xchan = '" . dbesc($xchan) . "' ) $item_normal ) "; - $title = replace_macros(get_markup_template("section_title.tpl"),array( + $title = replace_macros(get_markup_template("section_title.tpl"), array( '$title' => '<a href="' . zid($r[0]['xchan_url']) . '" ><img src="' . zid($r[0]['xchan_photo_s']) . '" alt="' . urlencode($r[0]['xchan_name']) . '" /></a> <a href="' . zid($r[0]['xchan_url']) . '" >' . $r[0]['xchan_name'] . '</a>' )); @@ -345,13 +346,13 @@ class Network extends \Zotlabs\Web\Controller { $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2)))); } - $sql_extra2 = (($nouveau) ? '' : " AND item.parent = item.id "); + $sql_extra2 = (($nouveau) ? '' : ' AND item.parent = item.id '); $sql_extra3 = (($nouveau) ? '' : $sql_extra3); - if(x($_GET,'search')) { + if(x($_GET, 'search')) { $search = escape_tags($_GET['search']); - if(strpos($search,'#') === 0) { - $sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG); + if(strpos($search, '#') === 0) { + $sql_extra .= term_query('item', substr($search, 1), TERM_HASHTAG, TERM_COMMUNITYTAG); } else { $sql_extra .= sprintf(" AND (item.body like '%s' OR item.title like '%s') ", @@ -368,8 +369,8 @@ class Network extends \Zotlabs\Web\Controller { // The name 'verb' is a holdover from the earlier XML // ActivityStreams specification. - if (substr($verb,0,1) === '.') { - $verb = substr($verb,1); + if (substr($verb, 0, 1) === '.') { + $verb = substr($verb, 1); $sql_extra .= sprintf(" AND item.obj_type like '%s' ", dbesc(protect_sprintf('%' . $verb . '%')) ); @@ -382,13 +383,17 @@ class Network extends \Zotlabs\Web\Controller { } if(strlen($file)) { - $sql_extra .= term_query('item',$file,TERM_FILE); + $sql_extra .= term_query('item', $file, TERM_FILE); } if ($dm) { - $sql_extra .= " AND item_private = 2 "; + $sql_extra .= ' AND item_private = 2 '; + } + else { + $sql_extra .= ' AND item_private IN (0, 1) '; } + if($conv) { $item_thread_top = ''; $sql_extra .= " AND ( author_xchan = '" . dbesc($channel['channel_hash']) . "' OR item_mentionsme = 1 ) "; @@ -401,38 +406,38 @@ class Network extends \Zotlabs\Web\Controller { } else { - $itemspage = get_pconfig(local_channel(),'system','itemspage'); + $itemspage = get_pconfig(local_channel(), 'system', 'itemspage'); App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10)); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); } // cmin and cmax are both -1 when the affinity tool is disabled - if(($cmin != (-1)) || ($cmax != (-1))) { + if(($cmin !== (-1)) || ($cmax !== (-1))) { // Not everybody who shows up in the network stream will be in your address book. // By default those that aren't are assumed to have closeness = 99; but this isn't // recorded anywhere. So if cmax is 99, we'll open the search up to anybody in // the stream with a NULL address book entry. - $sql_nets .= " AND "; + $sql_nets .= ' AND '; - if($cmax == 99) - $sql_nets .= " ( "; + if($cmax === 99) + $sql_nets .= ' ( '; - $sql_nets .= "( abook.abook_closeness >= " . intval($cmin) . " "; - $sql_nets .= " AND abook.abook_closeness <= " . intval($cmax) . " ) "; + $sql_nets .= '( abook.abook_closeness >= ' . intval($cmin) . ' '; + $sql_nets .= ' AND abook.abook_closeness <= ' . intval($cmax) . ' ) '; - if($cmax == 99) - $sql_nets .= " OR abook.abook_closeness IS NULL ) "; + if($cmax === 99) + $sql_nets .= ' OR abook.abook_closeness IS NULL ) '; } - $net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : ''); + $net_query = (($net) ? ' left join xchan on xchan_hash = author_xchan ' : ''); $net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : ''); - $abook_uids = " and abook.abook_channel = " . local_channel() . " "; - $uids = " and item.uid = " . local_channel() . " "; + $abook_uids = ' and abook.abook_channel = ' . local_channel() . ' '; + $uids = ' and item.uid = ' . local_channel() . ' '; if(feature_enabled(local_channel(), 'network_list_mode')) $page_mode = 'list'; @@ -461,7 +466,7 @@ class Network extends \Zotlabs\Web\Controller { if($nouveau && $load) { // "New Item View" - show all items unthreaded in reverse created date order - $items = q("SELECT item.*, item.id AS item_id, created FROM item + $items = dbq("SELECT item.*, item.id AS item_id, created FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids $item_normal @@ -471,26 +476,26 @@ class Network extends \Zotlabs\Web\Controller { ORDER BY item.created DESC $pager_sql " ); - $parents_str = ids_to_querystr($items,'item_id'); + $parents_str = ids_to_querystr($items, 'item_id'); require_once('include/items.php'); xchan_query($items); - $items = fetch_post_tags($items,true); + $items = fetch_post_tags($items, true); } elseif($update) { // Normal conversation view if($order === 'post') - $ordering = "created"; + $ordering = 'created'; else - $ordering = "commented"; + $ordering = 'commented'; if($load) { // Fetch a page full of parent items for this page - $r = q("SELECT item.parent AS item_id FROM item + $r = dbq("SELECT item.parent AS item_id FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids $item_thread_top $item_normal @@ -504,31 +509,28 @@ class Network extends \Zotlabs\Web\Controller { else { // this is an update - $r = q("SELECT item.parent AS item_id FROM item + $r = dbq("SELECT item.parent AS item_id FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids $item_normal_update $simple_update and (abook.abook_blocked = 0 or abook.abook_flags is null) - $sql_extra3 $sql_extra $sql_options $sql_nets $net_query2" + $sql_extra3 $sql_extra $sql_options $sql_nets $net_query2 " ); } // Then fetch all the children of the parents that are on this page if($r) { - - $parents_str = ids_to_querystr($r,'item_id'); - - $items = q("SELECT item.*, item.id AS item_id FROM item + $parents_str = ids_to_querystr($r, 'item_id'); + $items = dbq("SELECT item.*, item.id AS item_id FROM item WHERE true $uids $item_normal - AND item.parent IN ( %s ) - $sql_extra ", - dbesc($parents_str) + AND item.parent IN ( $parents_str ) + $sql_extra " ); - xchan_query($items,true); - $items = fetch_post_tags($items,true); - $items = conv_sort($items,$ordering); + xchan_query($items, true); + $items = fetch_post_tags($items, true); + $items = conv_sort($items, $ordering); } else { $items = array(); @@ -546,7 +548,7 @@ class Network extends \Zotlabs\Web\Controller { // We only launch liveUpdate if you aren't filtering in some incompatible // way and also you aren't writing a comment (discovered in javascript). - $maxheight = get_pconfig(local_channel(),'system','network_divmore_height'); + $maxheight = get_pconfig(local_channel(), 'system', 'network_divmore_height'); if(! $maxheight) $maxheight = 400; @@ -591,7 +593,7 @@ class Network extends \Zotlabs\Web\Controller { )); } - $o .= conversation($items,$mode,$update,$page_mode); + $o .= conversation($items, $mode, $update, $page_mode); if(($items) && (! $update)) $o .= alt_pager(count($items)); diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index 84d492f8f..24dbe2944 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use URLify; + require_once('include/channel.php'); require_once('include/permissions.php'); @@ -13,7 +15,6 @@ class New_channel extends \Zotlabs\Web\Controller { $cmd = ((argc() > 1) ? argv(1) : ''); if($cmd === 'autofill.json') { - require_once('library/urlify/URLify.php'); $result = array('error' => false, 'message' => ''); $n = trim($_REQUEST['name']); @@ -24,7 +25,7 @@ class New_channel extends \Zotlabs\Web\Controller { } if((! $x) || strlen($x) > 64) - $x = strtolower(\URLify::transliterate($n)); + $x = strtolower(URLify::transliterate($n)); $test = array(); @@ -46,7 +47,6 @@ class New_channel extends \Zotlabs\Web\Controller { } if($cmd === 'checkaddr.json') { - require_once('library/urlify/URLify.php'); $result = array('error' => false, 'message' => ''); $n = trim($_REQUEST['nick']); if(! $n) { @@ -60,7 +60,7 @@ class New_channel extends \Zotlabs\Web\Controller { } if((! $x) || strlen($x) > 64) - $x = strtolower(\URLify::transliterate($n)); + $x = strtolower(URLify::transliterate($n)); $test = array(); @@ -138,7 +138,7 @@ class New_channel extends \Zotlabs\Web\Controller { intval($aid) ); if($r && (! intval($r[0]['total']))) { - $default_role = get_config('system','default_permissions_role','social'); + $default_role = get_config('system','default_permissions_role','personal'); } $limit = account_service_class_fetch(get_account_id(),'total_identities'); @@ -170,12 +170,12 @@ class New_channel extends \Zotlabs\Web\Controller { $privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" ); - $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); + $perm_roles = \Zotlabs\Access\PermissionRoles::channel_roles(); $name = array('name', t('Channel name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), $name_help, "*"); $nickhub = '@' . \App::get_hostname(); $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), $nick_help, "*"); - $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role compatible with your usage needs and privacy requirements.') . '<br>' . '<a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles); + $role = array('permissions_role' , t('Channel role'), ($privacy_role) ? $privacy_role : 'personal', '', $perm_roles); $o = replace_macros(get_markup_template('new_channel.tpl'), array( '$title' => t('Create a Channel'), diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php index b448cff83..57b8f30db 100644 --- a/Zotlabs/Module/Notes.php +++ b/Zotlabs/Module/Notes.php @@ -19,7 +19,12 @@ class Notes extends Controller { if(! Apps::system_app_installed(local_channel(), 'Notes')) return EMPTY_STR; - $ret = array('success' => true); + $ret = [ + 'success' => false, + 'html' => '' + ]; + + if(array_key_exists('note_text',$_REQUEST)) { $body = escape_tags($_REQUEST['note_text']); @@ -33,12 +38,15 @@ class Notes extends Controller { set_pconfig(local_channel(),'notes','text.bak',$old_text); } set_pconfig(local_channel(),'notes','text',$body); + + $ret['html'] = bbcode($body); + $ret['success'] = true; + } // push updates to channel clones if((argc() > 1) && (argv(1) === 'sync')) { - require_once('include/zot.php'); Libsync::build_sync_packet(); } @@ -52,11 +60,9 @@ class Notes extends Controller { if(! Apps::system_app_installed(local_channel(), 'Notes')) { //Do not display any associated widgets at this point - App::$pdl = EMPTY_STR; - - $o = '<b>' . t('Notes App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('A simple notes app with a widget (note: notes are not encrypted)'); - return $o; + App::$pdl = ''; + $papp = Apps::get_papp('Notes'); + return Apps::app_render($papp, 'module'); } $w = new \Zotlabs\Widget\Notes; diff --git a/Zotlabs/Module/Notifications.php b/Zotlabs/Module/Notifications.php index 8ecf5760a..c08628b47 100644 --- a/Zotlabs/Module/Notifications.php +++ b/Zotlabs/Module/Notifications.php @@ -8,10 +8,58 @@ class Notifications extends \Zotlabs\Web\Controller { function get() { if(! local_channel()) { - notice( t('Permission denied.') . EOL); return; } + // ajax mark all unseen items read + if(x($_REQUEST, 'markRead')) { + switch($_REQUEST['markRead']) { + case 'dm': + $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_private = 2", + intval(local_channel()) + ); + break; + case 'network': + $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_private IN (0, 1)", + intval(local_channel()) + ); + break; + case 'home': + $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_wall = 1 AND item_private IN (0, 1)", + intval(local_channel()) + ); + break; + case 'all_events': + $evdays = intval(get_pconfig(local_channel(), 'system', 'evdays', 3)); + $r = q("UPDATE event SET dismissed = 1 WHERE uid = %d AND dismissed = 0 AND dtstart < '%s' AND dtstart > '%s' ", + 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')) + ); + break; + case 'notify': + $r = q("UPDATE notify SET seen = 1 WHERE seen = 0 AND uid = %d", + intval(local_channel()) + ); + break; + case 'pubs': + unset($_SESSION['static_loadtime']); + break; + default: + break; + } + killme(); + } + + // ajax mark all comments of a parent item read + if(x($_REQUEST, 'markItemRead') && local_channel()) { + $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND parent = %d", + intval(local_channel()), + intval($_REQUEST['markItemRead']) + ); + killme(); + } + nav_set_selected('Notifications'); $o = ''; diff --git a/Zotlabs/Module/Notify.php b/Zotlabs/Module/Notify.php index cffcc8099..4cbcfee05 100644 --- a/Zotlabs/Module/Notify.php +++ b/Zotlabs/Module/Notify.php @@ -1,14 +1,38 @@ <?php namespace Zotlabs\Module; +use \Zotlabs\Lib\PConfig; +use \Zotlabs\Web\Controller; - -class Notify extends \Zotlabs\Web\Controller { +class Notify extends Controller { function init() { if(! local_channel()) return; - + + if($_REQUEST['notify_id']) { + $update_notices_per_parent = PConfig::Get(local_channel(), 'system', 'update_notices_per_parent', 1); + + if($update_notices_per_parent) { + $r = q("SELECT parent FROM notify WHERE id = %d AND uid = %d", + intval($_REQUEST['notify_id']), + intval(local_channel()) + ); + q("update notify set seen = 1 where parent = '%s' and uid = %d", + dbesc($r[0]['parent']), + intval(local_channel()) + ); + } + else { + q("update notify set seen = 1 where id = %d and uid = %d", + intval($_REQUEST['notify_id']), + intval(local_channel()) + ); + } + + killme(); + } + if(argc() > 2 && argv(1) === 'view' && intval(argv(2))) { $r = q("select * from notify where id = %d and uid = %d limit 1", intval(argv(2)), @@ -29,24 +53,24 @@ class Notify extends \Zotlabs\Web\Controller { } goaway(z_root()); } - - + + } - - + + function get() { if(! local_channel()) return login(); - + $notif_tpl = get_markup_template('notifications.tpl'); - + $not_tpl = get_markup_template('notify.tpl'); require_once('include/bbcode.php'); - + $r = q("SELECT * from notify where uid = %d and seen = 0 order by created desc", intval(local_channel()) ); - + if($r) { foreach ($r as $it) { $notif_content .= replace_macros($not_tpl,array( @@ -56,18 +80,18 @@ class Notify extends \Zotlabs\Web\Controller { '$item_when' => relative_date($it['created']) )); } - } + } else { $notif_content .= t('No more system notifications.'); } - + $o .= replace_macros($notif_tpl,array( '$notif_header' => t('System Notifications'), '$tabs' => '', // $tabs, '$notif_content' => $notif_content, )); - + return $o; - + } } diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php index 27c062df2..061296257 100644 --- a/Zotlabs/Module/Oauth.php +++ b/Zotlabs/Module/Oauth.php @@ -17,22 +17,22 @@ class Oauth extends Controller { if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager')) return; - + if(x($_POST,'remove')){ check_form_security_token_redirectOnErr('/oauth', 'oauth'); - + $key = $_POST['remove']; q("DELETE FROM tokens WHERE id='%s' AND uid=%d", dbesc($key), local_channel()); goaway(z_root()."/oauth"); - return; + return; } - + if((argc() > 1) && (argv(1) === 'edit' || argv(1) === 'add') && x($_POST,'submit')) { - + check_form_security_token_redirectOnErr('oauth', 'oauth'); - + $name = ((x($_POST,'name')) ? escape_tags($_POST['name']) : ''); $key = ((x($_POST,'key')) ? escape_tags($_POST['key']) : ''); $secret = ((x($_POST,'secret')) ? escape_tags($_POST['secret']) : ''); @@ -48,7 +48,7 @@ class Oauth extends Controller { $ok = false; notice( t('Key and Secret are required') . EOL); } - + if($ok) { if ($_POST['submit']==t("Update")){ $r = q("UPDATE clients SET @@ -96,13 +96,11 @@ class Oauth extends Controller { if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('OAuth Apps Manager App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('OAuth authentication tokens for mobile and remote apps'); - return $o; + $papp = Apps::get_papp('OAuth Apps Manager'); + return Apps::app_render($papp, 'module'); } - + if((argc() > 1) && (argv(1) === 'add')) { $tpl = get_markup_template("oauth_edit.tpl"); $o .= replace_macros($tpl, array( @@ -118,18 +116,18 @@ class Oauth extends Controller { )); return $o; } - + if((argc() > 2) && (argv(1) === 'edit')) { $r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d", dbesc(argv(2)), local_channel()); - + if (!count($r)){ notice(t('Application not found.')); return; } $app = $r[0]; - + $tpl = get_markup_template("oauth_edit.tpl"); $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("oauth"), @@ -144,26 +142,26 @@ class Oauth extends Controller { )); return $o; } - + if((argc() > 2) && (argv(1) === 'delete')) { check_form_security_token_redirectOnErr('/oauth', 'oauth', 't'); - + $r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d", dbesc(argv(2)), local_channel()); goaway(z_root()."/oauth"); - return; + return; } - - - $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my + + + $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my FROM clients LEFT JOIN tokens ON clients.client_id=tokens.client_id WHERE clients.uid IN (%d,0)", local_channel(), local_channel()); - - + + $tpl = get_markup_template("oauth.tpl"); $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("oauth"), @@ -178,7 +176,7 @@ class Oauth extends Controller { '$apps' => $r, )); return $o; - + } } diff --git a/Zotlabs/Module/Oauth2.php b/Zotlabs/Module/Oauth2.php index db2687b4c..4b0b1991e 100644 --- a/Zotlabs/Module/Oauth2.php +++ b/Zotlabs/Module/Oauth2.php @@ -16,11 +16,11 @@ class Oauth2 extends Controller { if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager')) return; - + if(x($_POST,'remove')){ check_form_security_token_redirectOnErr('oauth2', 'oauth2'); $name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : ''); - logger("REMOVE! ".$name." uid: ".local_channel()); + logger("REMOVE! ".$name." uid: ".local_channel()); $key = $_POST['remove']; q("DELETE FROM oauth_authorization_codes WHERE client_id='%s' AND user_id=%d", dbesc($name), @@ -35,13 +35,13 @@ class Oauth2 extends Controller { intval(local_channel()) ); goaway(z_root()."/oauth2"); - return; + return; } - + if((argc() > 1) && (argv(1) === 'edit' || argv(1) === 'add') && x($_POST,'submit')) { - + check_form_security_token_redirectOnErr('oauth2', 'oauth2'); - + $name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : ''); $secret = ((x($_POST,'secret')) ? escape_tags(trim($_POST['secret'])) : ''); $redirect = ((x($_POST,'redirect')) ? escape_tags(trim($_POST['redirect'])) : ''); @@ -53,7 +53,7 @@ class Oauth2 extends Controller { $ok = false; notice( t('Name and Secret are required') . EOL); } - + if($ok) { if ($_POST['submit']==t("Update")){ $r = q("UPDATE oauth_clients SET @@ -61,7 +61,7 @@ class Oauth2 extends Controller { client_secret = '%s', redirect_uri = '%s', grant_types = '%s', - scope = '%s', + scope = '%s', user_id = %d WHERE client_id='%s' and user_id = %s", dbesc($name), @@ -102,12 +102,10 @@ class Oauth2 extends Controller { if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('OAuth2 Apps Manager App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('OAuth2 authenticatication tokens for mobile and remote apps'); - return $o; + $papp = Apps::get_papp('OAuth2 Apps Manager'); + return Apps::app_render($papp, 'module'); } - + if((argc() > 1) && (argv(1) === 'add')) { $tpl = get_markup_template("oauth2_edit.tpl"); $o .= replace_macros($tpl, array( @@ -123,20 +121,20 @@ class Oauth2 extends Controller { )); return $o; } - + if((argc() > 2) && (argv(1) === 'edit')) { $r = q("SELECT * FROM oauth_clients WHERE client_id='%s' AND user_id= %d", dbesc(argv(2)), intval(local_channel()) ); - + if (! $r){ notice(t('OAuth2 Application not found.')); return; } $app = $r[0]; - + $tpl = get_markup_template("oauth2_edit.tpl"); $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("oauth2"), @@ -151,10 +149,10 @@ class Oauth2 extends Controller { )); return $o; } - + if((argc() > 2) && (argv(1) === 'delete')) { check_form_security_token_redirectOnErr('oauth2', 'oauth2', 't'); - + $r = q("DELETE FROM oauth_clients WHERE client_id = '%s' AND user_id = %d", dbesc(argv(2)), intval(local_channel()) @@ -172,11 +170,11 @@ class Oauth2 extends Controller { intval(local_channel()) ); goaway(z_root()."/oauth2"); - return; + return; } - - $r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my + + $r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my FROM oauth_clients LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id AND oauth_clients.user_id=oauth_access_tokens.user_id @@ -184,7 +182,7 @@ class Oauth2 extends Controller { intval(local_channel()), intval(local_channel()) ); - + $tpl = get_markup_template("oauth2.tpl"); $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("oauth2"), @@ -199,7 +197,7 @@ class Oauth2 extends Controller { '$apps' => $r, )); return $o; - + } } diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php index faad2fc52..8e048a487 100644 --- a/Zotlabs/Module/Oep.php +++ b/Zotlabs/Module/Oep.php @@ -77,8 +77,11 @@ class Oep extends \Zotlabs\Web\Controller { $res = $matches[2]; } - if(strpos($res,'b64.') === 0) { - $res = base64url_decode(substr($res,4)); + $res = unpack_link_id($res); + + if ($res === false) { + notice(t('Malformed message id.') . EOL); + return; } $item_normal = item_normal(); @@ -122,12 +125,12 @@ class Oep extends \Zotlabs\Web\Controller { $o = "[share author='".urlencode($p[0]['author']['xchan_name']). - "' profile='".$p[0]['author']['xchan_url'] . - "' avatar='".$p[0]['author']['xchan_photo_s']. - "' link='".$p[0]['plink']. - "' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') . - "' posted='".$p[0]['created']. - "' message_id='".$p[0]['mid']."']"; + "' profile='".$p[0]['author']['xchan_url'] . + "' avatar='".$p[0]['author']['xchan_photo_s']. + "' link='".$p[0]['plink']. + "' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') . + "' posted='".$p[0]['created']. + "' message_id='".$p[0]['mid']."']"; if($p[0]['title']) $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; @@ -210,13 +213,13 @@ class Oep extends \Zotlabs\Web\Controller { $o = "[share author='".urlencode($p[0]['author']['xchan_name']). - "' profile='".$p[0]['author']['xchan_url'] . - "' avatar='".$p[0]['author']['xchan_photo_s']. - "' link='".$p[0]['plink']. - "' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') . - "' posted='".$p[0]['created']. - "' message_id='".$p[0]['mid']."']"; - if($p[0]['title']) + "' profile='".$p[0]['author']['xchan_url'] . + "' avatar='".$p[0]['author']['xchan_photo_s']. + "' link='".$p[0]['plink']. + "' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') . + "' posted='".$p[0]['created']. + "' message_id='".$p[0]['mid']."']"; + if($p[0]['title']) $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; $o .= $x; @@ -296,14 +299,14 @@ class Oep extends \Zotlabs\Web\Controller { $o = "[share author='".urlencode($p[0]['author']['xchan_name']). - "' profile='".$p[0]['author']['xchan_url'] . - "' avatar='".$p[0]['author']['xchan_photo_s']. - "' link='".$p[0]['plink']. - "' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') . - "' posted='".$p[0]['created']. - "' message_id='".$p[0]['mid']."']"; - if($p[0]['title']) - $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; + "' profile='".$p[0]['author']['xchan_url'] . + "' avatar='".$p[0]['author']['xchan_photo_s']. + "' link='".$p[0]['plink']. + "' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') . + "' posted='".$p[0]['created']. + "' message_id='".$p[0]['mid']."']"; + if($p[0]['title']) + $o .= '[b]'.$p[0]['title'].'[/b]'."\r\n"; $o .= $x; $o .= "[/share]"; @@ -374,7 +377,7 @@ class Oep extends \Zotlabs\Web\Controller { "' profile='".$p[0]['author']['xchan_url'] . "' avatar='".$p[0]['author']['xchan_photo_s']. "' link='".$p[0]['plink']. - "' auth='".((in_array($p[0]['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') . + "' auth='".(($p[0]['author']['xchan_network'] === 'zot6') ? 'true' : 'false') . "' posted='".$p[0]['created']. "' message_id='".$p[0]['mid']."']"; if($p[0]['title']) diff --git a/Zotlabs/Module/Outbox.php b/Zotlabs/Module/Outbox.php new file mode 100644 index 000000000..503b464d1 --- /dev/null +++ b/Zotlabs/Module/Outbox.php @@ -0,0 +1,124 @@ +<?php + +namespace Zotlabs\Module; + +use App; +use Zotlabs\Lib\Activity; +use Zotlabs\Lib\ActivityStreams; +use Zotlabs\Lib\Config; +use Zotlabs\Lib\ThreadListener; +use Zotlabs\Web\Controller; +use Zotlabs\Web\HTTPSig; + +class Outbox extends Controller { + + function init() { + if (ActivityStreams::is_as_request()) { + + if (observer_prohibited(true)) { + killme(); + } + + $channel = channelx_by_nick(argv(1)); + if (!$channel) { + killme(); + } + + if (intval($channel['channel_system'])) { + killme(); + } + + $sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR); + if ($sigdata['portable_id'] && $sigdata['header_valid']) { + $portable_id = $sigdata['portable_id']; + if (!check_channelallowed($portable_id)) { + http_status_exit(403, 'Permission denied'); + } + if (!check_siteallowed($sigdata['signer'])) { + http_status_exit(403, 'Permission denied'); + } + observer_auth($portable_id); + } + elseif (Config::get('system', 'require_authenticated_fetch', false)) { + http_status_exit(403, 'Permission denied'); + } + + $observer_hash = get_observer_hash(); + + $params = []; + + $params['begin'] = ((x($_REQUEST, 'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE); + $params['end'] = ((x($_REQUEST, 'date_end')) ? $_REQUEST['date_end'] : ''); + $params['type'] = 'json'; + $params['pages'] = ((x($_REQUEST, 'pages')) ? intval($_REQUEST['pages']) : 0); + $params['top'] = ((x($_REQUEST, 'top')) ? intval($_REQUEST['top']) : 0); + $params['direction'] = ((x($_REQUEST, 'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); // unimplemented + $params['cat'] = ((x($_REQUEST, 'cat')) ? escape_tags($_REQUEST['cat']) : ''); + $params['compat'] = 1; + + $total = items_fetch( + [ + 'total' => true, + 'wall' => 1, + 'datequery' => $params['end'], + 'datequery2' => $params['begin'], + 'direction' => dbesc($params['direction']), + 'pages' => $params['pages'], + 'order' => dbesc('post'), + 'top' => $params['top'], + 'cat' => $params['cat'], + 'compat' => $params['compat'] + ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module + ); + + if ($total) { + App::set_pager_total($total); + App::set_pager_itemspage(30); + } + + if (App::$pager['unset'] && $total > 30) { + $ret = Activity::paged_collection_init($total, App::$query_string); + } + else { + + $items = items_fetch( + [ + 'wall' => 1, + 'datequery' => $params['end'], + 'datequery2' => $params['begin'], + 'records' => intval(App::$pager['itemspage']), + 'start' => intval(App::$pager['start']), + 'direction' => dbesc($params['direction']), + 'pages' => $params['pages'], + 'order' => dbesc('post'), + 'top' => $params['top'], + 'cat' => $params['cat'], + 'compat' => $params['compat'] + ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module + ); + + if ($items && $observer_hash) { + + // check to see if this observer is a connection. If not, register any items + // belonging to this channel for notification of deletion/expiration + + $x = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'", + intval($channel['channel_id']), + dbesc($observer_hash) + ); + if (!$x) { + foreach ($items as $item) { + if (strpos($item['mid'], z_root()) === 0) { + ThreadListener::store($item['mid'], $observer_hash); + } + } + } + } + + $ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', $total); + } + + as_return_and_die($ret, $channel); + } + } +} diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php index 9a3513f34..e30aa5fb4 100644 --- a/Zotlabs/Module/Owa.php +++ b/Zotlabs/Module/Owa.php @@ -32,14 +32,14 @@ class Owa extends Controller { $keyId = $sigblock['keyId']; if ($keyId) { $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash - WHERE hubloc_id_url = '%s'", + WHERE hubloc_id_url = '%s' AND xchan_pubkey != '' ", dbesc($keyId) ); if (! $r) { $found = discover_by_webbie(str_replace('acct:','',$keyId)); if ($found) { $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash - WHERE hubloc_id_url = '%s'", + WHERE hubloc_id_url = '%s' AND xchan_pubkey != '' ", dbesc($keyId) ); } diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php index 36201544f..3b94c9611 100644 --- a/Zotlabs/Module/Pdledit.php +++ b/Zotlabs/Module/Pdledit.php @@ -27,10 +27,10 @@ class Pdledit extends Controller { info( t('Layout updated.') . EOL); goaway(z_root() . '/pdledit/' . $_REQUEST['module']); } - - + + function get() { - + if(! local_channel()) { notice( t('Permission denied.') . EOL); return; @@ -39,10 +39,8 @@ class Pdledit extends Controller { if(! Apps::system_app_installed(local_channel(), 'PDL Editor')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('PDL Editor App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Provides the ability to edit system page layouts'); - return $o; + $papp = Apps::get_papp('PDL Editor'); + return Apps::app_render($papp, 'module'); } if(argc() > 2 && argv(2) === 'reset') { @@ -68,7 +66,7 @@ class Pdledit extends Controller { $edited[] = substr(str_replace('.pdl','',$rv['k']),4); } } - + $files = glob('Zotlabs/Module/*.php'); if($files) { foreach($files as $f) { @@ -81,21 +79,21 @@ class Pdledit extends Controller { } $o .= '</div>'; - + // list module pdl files return $o; } - + $t = get_pconfig(local_channel(),'system',$module); $s = file_get_contents(theme_include($module)); if(! $t) { $t = $s; - } + } if(! $t) { notice( t('Layout not found.') . EOL); return ''; } - + $o = replace_macros(get_markup_template('pdledit.tpl'),array( '$header' => t('Edit System Page Description'), '$mname' => t('Module Name:'), @@ -107,8 +105,8 @@ class Pdledit extends Controller { '$content' => htmlspecialchars($t,ENT_COMPAT,'UTF-8'), '$submit' => t('Submit') )); - + return $o; } - + } diff --git a/Zotlabs/Module/Pdledit_gui.php b/Zotlabs/Module/Pdledit_gui.php new file mode 100644 index 000000000..b550b92d3 --- /dev/null +++ b/Zotlabs/Module/Pdledit_gui.php @@ -0,0 +1,553 @@ +<?php + +namespace Zotlabs\Module; + +use App; +use Zotlabs\Web\Controller; +use Zotlabs\Render\Comanche; +use Zotlabs\Lib\Libsync; + +class Pdledit_gui extends Controller { + + function post() { + + if (!local_channel()) { + return; + } + + if (!$_REQUEST['module']) { + return; + } + + $module = $_REQUEST['module']; + + $ret = [ + 'success' => false, + 'module' => $module + ]; + + if ($_REQUEST['reset']) { + del_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl'); + Libsync::build_sync_packet(); + $ret['success'] = true; + json_return_and_die($ret); + } + + if ($_REQUEST['save']) { + if (!$_REQUEST['data']) { + return $ret; + } + + $data = json_decode($_REQUEST['data'],true); + $stored_pdl_result = self::get_pdl($module); + $pdl = $stored_pdl_result['pdl']; + + foreach ($data as $region => $entries) { + $region_pdl = ''; + foreach ($entries as $entry) { + $region_pdl .= base64_decode($entry) . "\r\n"; + } + $pdl = preg_replace('/\[region=' . $region . '\](.*?)\[\/region\]/ism', '[region=' . $region . ']' . "\r\n" . $region_pdl . "\r\n" . '[/region]', $pdl); + } + + set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl)); + Libsync::build_sync_packet(); + + $ret['success'] = true; + json_return_and_die($ret); + } + + if ($_REQUEST['save_src']) { + set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($_REQUEST['src'])); + Libsync::build_sync_packet(); + + $ret['success'] = true; + json_return_and_die($ret); + } + + if ($_REQUEST['save_template']) { + if (!$_REQUEST['data']) { + return $ret; + } + + $template = $_REQUEST['data'][0]['value']; + $pdl_result = self::get_pdl($module); + $stored_template = self::get_template($pdl_result['pdl']); + + if ($template === $stored_template) { + $ret['success'] = true; + return $ret; + } + + $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl_result['pdl'], $matches); + if ($cnt) { + $pdl = str_replace('[template]' . $stored_template . '[/template]', '[template]' . $template . '[/template]', $pdl_result['pdl']); + } + else { + $pdl = '[template]' . $template . '[/template]' . "\r\n"; + $pdl .= $pdl_result['pdl']; + } + + set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl)); + Libsync::build_sync_packet(); + + $ret['success'] = true; + json_return_and_die($ret); + } + + } + + function get() { + + if(! local_channel()) { + return EMPTY_STR; + } + + $module = argv(1); + + if (!$module) { + goaway(z_root() . '/pdledit_gui/hq'); + } + + $pdl_result = self::get_pdl($module); + + $pdl = $pdl_result['pdl']; + $modified = $pdl_result['modified']; + + if(!$pdl) { + return t('Layout not found'); + } + + $template = self::get_template($pdl); + + $template_info = self::get_template_info($template); + + if(empty($template_info['contentregion'])) { + return t('This template does not support pdledi_gui (no content regions defined)'); + } + + App::$page['template'] = $template; + + $regions = self::get_regions($pdl); + + foreach ($regions as $k => $v) { + $region_str = ''; + if (is_array($v)) { + ksort($v); + foreach ($v as $entry) { + // Get the info from the file and replace entry if we get anything useful + $widget_info = get_widget_info($entry['name']); + $entry['name'] = (($widget_info['name']) ? $widget_info['name'] : $entry['name']); + $entry['desc'] = (($widget_info['description']) ? $widget_info['description'] : $entry['desc']); + + $region_str .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ + '$entry' => $entry + ]); + } + } + App::$layout['region_' . $k] = $region_str; + } + + $templates = self::get_templates(); + $templates_html = replace_macros(get_markup_template('pdledit_gui_templates.tpl'), [ + '$templates' => $templates, + '$active' => $template + ]); + + $items_html = ''; + + //$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ + //'$entry' => [ + //'type' => 'content', + //'name' => t('Main page content'), + //'src' => base64_encode('$content') + //], + //'$disable_controls' => true + //]); + + foreach (self::get_widgets($module) as $entry) { + $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ + '$entry' => $entry, + '$disable_controls' => true + ]); + } + + foreach (self::get_menus() as $entry) { + $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ + '$entry' => $entry, + '$disable_controls' => true + ]); + } + + foreach (self::get_blocks() as $entry) { + $items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [ + '$entry' => $entry, + '$disable_controls' => true + ]); + } + + App::$layout['region_content'] .= replace_macros(get_markup_template('pdledit_gui.tpl'), [ + '$content_regions' => $template_info['contentregion'], + '$page_src' => base64_encode($pdl), + '$templates' => base64_encode($templates_html), + '$modules' => base64_encode(self::get_modules()), + '$items' => base64_encode($items_html), + '$module_modified' => $modified, + '$module' => $module + ]); + + } + + function get_templates() { + $ret = []; + + $files = glob('view/php/*.php'); + if($files) { + foreach($files as $f) { + $name = basename($f, '.php'); + $x = get_template_info($name); + if(!empty($x['contentregion'])) { + $ret[] = [ + 'name' => $name, + 'desc' => $x['description'] + ]; + } + } + } + + return $ret; + } + + function get_modules() { + $ret = ''; + + $files = glob('Zotlabs/Module/*.php'); + if($files) { + foreach($files as $f) { + $name = lcfirst(basename($f,'.php')); + + if ($name === 'admin' && !is_site_admin()) { + continue; + } + + $x = theme_include('mod_' . $name . '.pdl'); + if($x) { + $ret .= '<div class="mb-2"><a href="pdledit_gui/' . $name . '">' . $name . '</a></div>'; + } + } + } + + return $ret; + } + + function get_widgets($module) { + $ret = []; + + $checkpaths = [ + 'Zotlabs/Widget/*.php' + ]; + + foreach ($checkpaths as $path) { + $files = glob($path); + if($files) { + foreach($files as $f) { + $name = lcfirst(basename($f, '.php')); + + $widget_info = get_widget_info($name); + if ($widget_info['requires'] && strpos($widget_info['requires'], 'admin') !== false && !is_site_admin()) { + continue; + } + + if ($widget_info['requires'] && strpos($widget_info['requires'], $module) === false) { + continue; + } + + $ret[] = [ + 'type' => 'widget', + 'name' => $widget_info['name'] ?? $name, + 'desc' => $widget_info['description'] ?? '', + 'src' => base64_encode('[widget=' . $name . '][/widget]') + ]; + } + } + } + + return $ret; + } + + function get_menus() { + $ret = []; + + $r = q("select * from menu where menu_channel_id = %d and menu_flags = 0", + intval(local_channel()) + ); + + foreach ($r as $rr) { + $name = $rr['menu_name']; + $desc = $rr['menu_desc']; + $ret[] = [ + 'type' => 'menu', + 'name' => $name, + 'desc' => $desc, + 'src' => base64_encode('[menu]' . $name . '[/menu]') + ]; + } + + return $ret; + } + + function get_blocks() { + $ret = []; + + $r = q("select v, title, summary from item join iconfig on iconfig.iid = item.id and item.uid = %d + and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'", + intval(local_channel()) + ); + + foreach ($r as $rr) { + $name = $rr['v']; + $desc = (($rr['title']) ? $rr['title'] : $rr['summary']); + $ret[] = [ + 'type' => 'block', + 'name' => $name, + 'desc' => $desc, + 'src' => base64_encode('[block]' . $name . '[/block]') + ]; + } + + return $ret; + } + + function get_template($pdl) { + $ret = 'default'; + + $cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl, $matches); + if($cnt && isset($matches[1])) { + $ret = trim($matches[1]); + } + + return $ret; + } + + function get_regions($pdl) { + $ret = []; + $supported_regions = ['aside', 'content', 'right_aside']; + + $cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $pdl, $matches, PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + if (!in_array($mtch[1], $supported_regions)) { + continue; + } + $ret[$mtch[1]] = self::parse_region($mtch[2]); + } + } + + return $ret; + } + + function parse_region($pdl) { + $ret = []; + + $cnt = preg_match_all('/\$content\b/ism', $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); + if($cnt) { + foreach($matches as $mtch) { + $offset = intval($mtch[0][1]); + $name = trim($mtch[0][0]); + //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0])); + $src = base64_encode($mtch[0][0]); + $ret[$offset] = [ + 'type' => 'content', + 'name' => t('Main page content'), + 'desc' => t('The main page content can not be edited!'), + 'src' => $src + ]; + } + } + + $cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); + if($cnt) { + foreach($matches as $mtch) { + $offset = intval($mtch[1][1]); + $name = trim($mtch[1][0]); + //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0])); + $src = base64_encode($mtch[0][0]); + + $ret[$offset] = [ + 'type' => 'menu', + 'name' => $name, + 'desc' => '', + 'src' => $src + ]; + } + } + + // menu class e.g. [menu=horizontal]my_menu[/menu] or [menu=tabbed]my_menu[/menu] + // allows different menu renderings to be applied + + //$cnt = preg_match_all("/\[menu=(.*?)\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER); + //if($cnt) { + //foreach($matches as $mtch) { + //$s = str_replace($mtch[0],$this->menu(trim($mtch[2]),$mtch[1]),$s); + //} + //} + + + $cnt = preg_match_all("/\[block\](.*?)\[\/block\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); + if($cnt) { + foreach($matches as $mtch) { + $offset = intval($mtch[1][1]); + $name = trim($mtch[1][0]); + //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0])); + $src = base64_encode($mtch[0][0]); + $ret[$offset] = [ + 'type' => 'block', + 'name' => $name, + 'desc' => '', + 'src' => $src + ]; + } + } + + //$cnt = preg_match_all("/\[block=(.*?)\](.*?)\[\/block\]/ism", $s, $matches, PREG_SET_ORDER); + //if($cnt) { + //foreach($matches as $mtch) { + //$s = str_replace($mtch[0],$this->block(trim($mtch[2]),trim($mtch[1])),$s); + //} + //} + + //$cnt = preg_match_all("/\[js\](.*?)\[\/js\]/ism", $s, $matches, PREG_SET_ORDER); + //if($cnt) { + //foreach($matches as $mtch) { + //$s = str_replace($mtch[0],$this->js(trim($mtch[1])),$s); + //} + //} + + //$cnt = preg_match_all("/\[css\](.*?)\[\/css\]/ism", $s, $matches, PREG_SET_ORDER); + //if($cnt) { + //foreach($matches as $mtch) { + //$s = str_replace($mtch[0],$this->css(trim($mtch[1])),$s); + //} + //} + + // need to modify this to accept parameters + + $cnt = preg_match_all("/\[widget=(.*?)\](.*?)\[\/widget\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); + + if($cnt) { + foreach($matches as $mtch) { + $offset = intval($mtch[1][1]); + $name = trim($mtch[1][0]); + //$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0])); + $src = base64_encode($mtch[0][0]); + $ret[$offset] = [ + 'type' => 'widget', + 'name' => $name, + 'desc' => '', + 'src' => $src + ]; + } + } + + return $ret; + + } + + + /** + * @brief Parse template comment in search of template info. + * + * like + * \code + * * Name: MyWidget + * * Description: A widget + * * Version: 1.2.3 + * * Author: John <profile url> + * * Author: Jane <email> + * * ContentRegionID: some_id + * * ContentRegionID: some_other_id + * * + *\endcode + * @param string $template the name of the template + * @return array with the information + */ + function get_template_info($template){ + $m = []; + $info = [ + 'name' => $template, + 'description' => '', + 'author' => [], + 'maintainer' => [], + 'version' => '', + 'contentregion' => [] + ]; + + $checkpaths = [ + 'view/php/' . $template . '.php', + ]; + + $template_found = false; + + foreach ($checkpaths as $path) { + if (is_file($path)) { + $template_found = true; + $f = file_get_contents($path); + break; + } + } + + if(!($template_found && $f)) + return $info; + + $f = escape_tags($f); + $r = preg_match('|/\*.*\*/|msU', $f, $m); + + if ($r) { + $ll = explode("\n", $m[0]); + foreach($ll as $l) { + $l = trim($l, "\t\n\r */"); + if ($l != ''){ + list($k, $v) = array_map('trim', explode(':', $l, 2)); + $k = strtolower($k); + if (in_array($k, ['author', 'maintainer'])){ + $r = preg_match('|([^<]+)<([^>]+)>|', $v, $m); + if ($r) { + $info[$k][] = array('name' => $m[1], 'link' => $m[2]); + } else { + $info[$k][] = array('name' => $v); + } + } + elseif (in_array($k, ['contentregion'])){ + $info[$k][] = array_map('trim', explode(',', $v)); + } + else { + $info[$k] = $v; + } + } + } + } + + return $info; + } + + function get_pdl($module) { + $ret = [ + 'pdl' => null, + 'modified' => true + ]; + + $pdl_path = 'mod_' . $module . '.pdl'; + + $ret['pdl'] = get_pconfig(local_channel(), 'system', $pdl_path); + + if(!$ret['pdl']) { + $pdl_path = theme_include($pdl_path); + if ($pdl_path) { + $ret['pdl'] = file_get_contents($pdl_path); + $ret['modified'] = false; + } + } + + return $ret; + } +} diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php index 6a599282c..d42e45beb 100644 --- a/Zotlabs/Module/Permcats.php +++ b/Zotlabs/Module/Permcats.php @@ -3,132 +3,265 @@ namespace Zotlabs\Module; use App; +use Zotlabs\Access\PermissionLimits; +use Zotlabs\Access\Permissions; use Zotlabs\Web\Controller; -use Zotlabs\Lib\Apps; use Zotlabs\Lib\Libsync; +use Zotlabs\Lib\AccessList; +use Zotlabs\Lib\Permcat; class Permcats extends Controller { function post() { - if(! local_channel()) - return; - - if(! Apps::system_app_installed(local_channel(), 'Permission Categories')) + if (!local_channel()) return; $channel = App::get_channel(); check_form_security_token_redirectOnErr('/permcats', 'permcats'); + $name = escape_tags(trim($_REQUEST['name'])); + $is_system_role = isset($_REQUEST['is_system_role']); + $return_path = z_root() . '/permcats/' . $_REQUEST['return_path']; + $group_hash = $_REQUEST['group_select'] ?? ''; + $deleted_role = $_REQUEST['deleted_role'] ?? ''; + $new_role = $_REQUEST['new_role'] ?? ''; + $contacts = []; - $all_perms = \Zotlabs\Access\Permissions::Perms(); - $name = escape_tags(trim($_POST['name'])); - if(! $name) { - notice( t('Permission category name is required.') . EOL); - return; + if (argv(1) && hex2bin(argv(1)) !== $name) { + $return_path = z_root() . '/permcats/' . bin2hex($name); } + if ($deleted_role && $new_role) { + $r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d AND abook_role = '%s' AND abook_self = 0 AND abook_pending = 0", + intval(local_channel()), + dbesc($deleted_role) + ); - $pcarr = []; + if ($r) { + $contacts = ids_to_array($r, 'abook_xchan'); + } - if($all_perms) { - foreach($all_perms as $perm => $desc) { - if(array_key_exists('perms_' . $perm, $_POST)) { - $pcarr[] = $perm; - } + if ($contacts) { + Permcat::assign($channel, $new_role, $contacts); } - } - - \Zotlabs\Lib\Permcat::update(local_channel(),$name,$pcarr); - Libsync::build_sync_packet(); + Permcat::delete(local_channel(), $deleted_role); - info( t('Permission category saved.') . EOL); - - return; - } - + $default_role = get_pconfig(local_channel(), 'system', 'default_permcat', 'default'); + if ($deleted_role === $default_role) { + set_pconfig(local_channel(), 'system', 'default_permcat', $new_role); + } - function get() { + Libsync::build_sync_packet(); + info(t('Contact role deleted.') . EOL); + + goaway(z_root() . '/permcats/' . bin2hex($new_role)); - if(! local_channel()) return; + } - if(! Apps::system_app_installed(local_channel(), 'Permission Categories')) { - //Do not display any associated widgets at this point - App::$pdl = ''; + if ($group_hash === 'all_contacts') { + $r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d and abook_self = 0 and abook_pending = 0", + intval(local_channel()) + ); - $o = '<b>' . t('Permission Categories App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Create custom connection permission limits'); - return $o; + if ($r) { + $contacts = ids_to_array($r, 'abook_xchan'); + } } - $channel = App::get_channel(); + $group = null; + if (!$contacts && $group_hash) { + $group = AccessList::by_hash(local_channel(), $group_hash); + } + + if ($group) { + $contacts = AccessList::members_xchan(local_channel(), $group['id']); + } + + if (!$name) { + notice(t('Permission category name is required.') . EOL); + return; + } + + set_pconfig(local_channel(), 'system', 'default_permcat', 'default'); + + if (isset($_REQUEST['default_role'])) { + set_pconfig(local_channel(), 'system', 'default_permcat', $name); + } - if(argc() > 1) - $name = hex2bin(argv(1)); + if ($is_system_role) { + // if we have a system role just set the default and assign if aplicable and be done with it + if ($contacts) { + Permcat::assign($channel, $name, $contacts); + } - if(argc() > 2 && argv(2) === 'drop') { - \Zotlabs\Lib\Permcat::delete(local_channel(),$name); + info(t('Contact role saved.') . EOL); Libsync::build_sync_packet(); - json_return_and_die([ 'success' => true ]); + goaway($return_path); + return; } + $pcarr = []; + $all_perms = Permissions::Perms(); - $desc = t('Use this form to create permission rules for various classes of people or connections.'); + if ($all_perms) { + foreach ($all_perms as $perm => $desc) { + if (array_key_exists('perms_' . $perm, $_POST)) { + $pcarr[] = $perm; + } + } + } - $existing = []; + $pcat = new Permcat(local_channel()); + $pcatlist = $pcat->listing(); + $existing_raw_perms = []; - $pcat = new \Zotlabs\Lib\Permcat(local_channel()); - $pcatlist = $pcat->listing(); - $permcats = []; - if($pcatlist) { - foreach($pcatlist as $pc) { - if(($pc['name']) && ($name) && ($pc['name'] == $name)) - $existing = $pc['perms']; - if(! $pc['system']) - $permcats[bin2hex($pc['name'])] = $pc['localname']; + if ($pcatlist) { + foreach ($pcatlist as $pc) { + if ($pc['name'] && ($pc['name'] === $name)) { + $existing_raw_perms = $pc['raw_perms']; + } + } + } + + if (!$contacts && array_diff_assoc($existing_raw_perms, Permissions::FilledPerms($pcarr))) { + // If we don't have anyone to assign the role to and an existing role has changed, + // we will re-assign the changed role to all its members if there are any. + + $r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d AND abook_role = '%s' AND abook_self = 0 AND abook_pending = 0", + intval(local_channel()), + dbesc($name) + ); + + if ($r) { + $contacts = ids_to_array($r, 'abook_xchan'); } + + } + + Permcat::update(local_channel(), $name, $pcarr); + + if ($contacts) { + Permcat::assign($channel, $name, $contacts); + } + + Libsync::build_sync_packet(); + + info(t('Contact role saved.') . EOL); + goaway($return_path); + + return; + } + + + function get() { + + if (!local_channel()) + return EMPTY_STR; + + nav_set_selected('Contact Roles'); + + $name = ''; + if (argc() > 1) { + $name = hex2bin(argv(1)); } - $global_perms = \Zotlabs\Access\Permissions::Perms(); + $perms = []; + $existing = []; + $pcat = new Permcat(local_channel()); + $pcatlist = $pcat->listing(); + $is_system_role = false; + $delete_role_select_options = []; + $is_default_role = (get_pconfig(local_channel(), 'system', 'default_permcat', 'default') === $name); + $localname = ''; + + if ($pcatlist) { + foreach ($pcatlist as $pc) { + if ($pc['name'] && $name && ($pc['name'] === $name)) { + $existing = $pc['perms']; + if (isset($pc['system']) && intval($pc['system'])) + $is_system_role = $pc['name']; + } + + if ($pc['name'] == $name) { + $localname = $pc['localname']; + } - foreach($global_perms as $k => $v) { - $thisperm = \Zotlabs\Lib\Permcat::find_permcat($existing,$k); - $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k); + if ($pc['name'] !== $name) { + $delete_role_select_options[$pc['name']] = $pc['localname']; + } - if($existing[$k]) - $thisperm = "1"; + } + } - $perms[] = array('perms_' . $k, $v, '',$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited); + // select for delete action + $delete_role_select = [ + 'new_role', + (($is_default_role) ? t('Role to assign affected contacts and default role to') : t('Role to assign affected contacts to')), + '', + '', + $delete_role_select_options + ]; + + $global_perms = Permissions::Perms(); + + foreach ($global_perms as $k => $v) { + $thisperm = Permcat::find_permcat($existing, $k); + $checkinherited = PermissionLimits::Get(local_channel(), $k); + + if ($existing[$k]) + $thisperm = 1; + + $perms[] = [ + 'perms_' . $k, + $v, + '', + $thisperm, + 1, + (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), + '', + $checkinherited + ]; } + $group_select_options = [ + 'selected' => '', + 'form_id' => 'group_select', + 'label' => t('Assign this role to'), + 'after' => [ + 'name' => t('All my contacts'), + 'id' => 'all_contacts', + 'selected' => false + ] + ]; + $group_select = AccessList::select(local_channel(), $group_select_options); $tpl = get_markup_template("permcats.tpl"); - $o .= replace_macros($tpl, array( + $o = replace_macros($tpl, [ '$form_security_token' => get_form_security_token("permcats"), - '$title' => t('Permission Categories'), - '$desc' => $desc, - '$desc2' => $desc2, - '$tokens' => $t, - '$permcats' => $permcats, - '$atoken' => $atoken, - '$url1' => z_root() . '/channel/' . $channel['channel_address'], - '$url2' => z_root() . '/photos/' . $channel['channel_address'], - '$name' => array('name', t('Permission category name') . ' <span class="required">*</span>', (($name) ? $name : ''), ''), - '$me' => t('My Settings'), - '$perms' => $perms, - '$inherited' => t('inherited'), - '$notself' => 0, - '$self' => 1, - '$permlbl' => t('Individual Permissions'), - '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'), - '$submit' => t('Submit') - )); + '$default_role' => ['default_role', t('Automatically assign this role to new contacts'), intval($is_default_role), '', [t('No'), t('Yes')]], + '$title' => t('Contact Roles'), + '$name' => ['name', t('Role name') . ' <span class="required">*</span>', (($localname) ? $localname : ''), (($is_system_role) ? t('System role - not editable') : ''), '', (($is_system_role) ? 'disabled' : '')], + '$delete_label' => t('Deleting') . ' ' . $localname, + '$current_role' => $name, + '$perms' => $perms, + '$inherited' => t('inherited'), + '$is_system_role' => $is_system_role, + '$permlbl' => t('Role Permissions'), + '$permnote' => t('Some permissions may be inherited from your <a href="settings">channel role</a>, which have higher priority than contact role settings.'), + '$submit' => t('Submit'), + '$return_path' => argv(1), + '$group_select' => $group_select, + '$delete_role_select' => $delete_role_select, + '$delet_role_button' => t('Delete') + ]); + return $o; } - + } diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index 87697f5a7..10d2e8f47 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -3,6 +3,12 @@ namespace Zotlabs\Module; +use Zotlabs\Lib\Activity; +use Zotlabs\Lib\ActivityStreams; +use Zotlabs\Web\HTTPSig; +use Zotlabs\Lib\Config; + + require_once('include/security.php'); require_once('include/attach.php'); require_once('include/photo/photo_driver.php'); @@ -11,6 +17,48 @@ class Photo extends \Zotlabs\Web\Controller { function init() { + if (ActivityStreams::is_as_request()) { + + $sigdata = HTTPSig::verify(EMPTY_STR); + if ($sigdata['portable_id'] && $sigdata['header_valid']) { + $portable_id = $sigdata['portable_id']; + if (! check_channelallowed($portable_id)) { + http_status_exit(403, 'Permission denied'); + } + if (! check_siteallowed($sigdata['signer'])) { + http_status_exit(403, 'Permission denied'); + } + observer_auth($portable_id); + } + elseif (Config::get('system','require_authenticated_fetch',false)) { + http_status_exit(403,'Permission denied'); + } + + $observer_xchan = get_observer_hash(); + $allowed = false; + + $bear = Activity::token_from_request(); + if ($bear) { + logger('bear: ' . $bear, LOGGER_DEBUG); + } + + $r = q("select * from item where resource_type = 'photo' and resource_id = '%s' limit 1", + dbesc(argv(1)) + ); + if ($r) { + $allowed = attach_can_view($r[0]['uid'],$observer_xchan,argv(1)/*,$bear*/); + } + if (! $allowed) { + http_status_exit(404,'Permission denied.'); + } + $channel = channelx_by_n($r[0]['uid']); + + $obj = json_decode($r[0]['obj'],true); + + as_return_and_die($obj,$channel); + + } + $streaming = null; $channel = null; $person = 0; @@ -33,19 +81,19 @@ class Photo extends \Zotlabs\Web\Controller { $cache_mode = [ 'on' => false, 'age' => 86400, 'exp' => true, 'leak' => false ]; call_hooks('cache_mode_hook', $cache_mode); - + $observer_xchan = get_observer_hash(); $cachecontrol = ', no-cache'; if(isset($type)) { - + /** * Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites. - * + * */ - + $default = get_default_profile_photo(); - + if($type === 'profile') { switch($res) { case 'm': @@ -62,9 +110,9 @@ class Photo extends \Zotlabs\Web\Controller { break; } } - + $uid = $person; - + $data = ''; if ($uid > 0) { @@ -81,13 +129,13 @@ class Photo extends \Zotlabs\Web\Controller { else $data = dbunescbin($r[0]['content']); } - + if(! $data) { $d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ]; call_hooks('get_profile_photo',$d); - + $resolution = $d['imgscale']; - $uid = $d['channel_id']; + $uid = $d['channel_id']; $default = $d['default']; $data = $d['data']; $mimetype = $d['mimetype']; @@ -105,11 +153,11 @@ class Photo extends \Zotlabs\Web\Controller { $cachecontrol .= ', must-revalidate'; } else { - + /** * Other photos */ - + /* Check for a cookie to indicate display pixel density, in order to detect high-resolution displays. This procedure was derived from the "Retina Images" by Jeremey Worboys, used in accordance with the Creative Commons Attribution 3.0 Unported License. @@ -127,12 +175,12 @@ class Photo extends \Zotlabs\Web\Controller { // $prvcachecontrol = 'no-cache'; $status = 'no cookie'; } - + $resolution = 0; - + if(strpos($photo,'.') !== false) $photo = substr($photo,0,strpos($photo,'.')); - + if(substr($photo,-2,1) == '-') { $resolution = intval(substr($photo,-1,1)); $photo = substr($photo,0,-2); @@ -140,7 +188,7 @@ class Photo extends \Zotlabs\Web\Controller { if ($resolution == 2 && ($cookie_value > 1)) $resolution = 1; } - + $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", dbesc($photo), intval($resolution) @@ -151,7 +199,7 @@ class Photo extends \Zotlabs\Web\Controller { $u = intval($r[0]['photo_usage']); if($u) { $allowed = 1; - if($u === PHOTO_COVER) + if($u === PHOTO_COVER) if($resolution < PHOTO_RES_COVER_1200) $allowed = (-1); if($u === PHOTO_PROFILE) @@ -184,9 +232,9 @@ class Photo extends \Zotlabs\Web\Controller { dbesc($photo), intval($resolution) ); - + $exists = (($e) ? true : false); - + if($exists && $allowed) { $expires = strtotime($e[0]['expires'] . 'Z'); $data = dbunescbin($e[0]['content']); @@ -209,16 +257,16 @@ class Photo extends \Zotlabs\Web\Controller { } } - } + } else http_status_exit(404,'not found'); } if(! $data) killme(); - + $etag = '"' . md5($data . $modified) . '"'; - + if($modified == 0) $modified = time(); @@ -241,39 +289,39 @@ class Photo extends \Zotlabs\Web\Controller { } if(isset($prvcachecontrol)) { - + // it is a private photo that they have no permission to view. // tell the browser not to cache it, in case they authenticate // and subsequently have permission to see it - + header("Cache-Control: " . $prvcachecontrol); - + } else { // The photo cache default is 1 day to provide a privacy trade-off, - // as somebody reducing photo permissions on a photo that is already + // as somebody reducing photo permissions on a photo that is already // "in the wild" won't be able to stop the photo from being viewed // for this amount amount of time once it is in the browser cache. - // The privacy expectations of your site members and their perception + // The privacy expectations of your site members and their perception // of privacy where it affects the entire project may be affected. - // This has performance considerations but we highly recommend you - // leave it alone. - + // This has performance considerations but we highly recommend you + // leave it alone. + $maxage = $cache_mode['age']; if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time())) $expires = time() + $maxage; else $maxage = $expires - time(); - + header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT"); - // set CDN/Infrastructure caching much lower than maxage + // set CDN/Infrastructure caching much lower than maxage // in the event that infrastructure caching is present. $smaxage = intval($maxage/12); header("Cache-Control: s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol); - + } header("Content-type: " . $mimetype); @@ -281,7 +329,7 @@ class Photo extends \Zotlabs\Web\Controller { header("ETag: " . $etag); header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data))); - // If it's a file resource, stream it. + // If it's a file resource, stream it. if($streaming) { if(strpos($streaming,'store') !== false) $istream = fopen($streaming,'rb'); @@ -300,5 +348,5 @@ class Photo extends \Zotlabs\Web\Controller { killme(); } - + } diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index e62accb06..45fe3d9e0 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -171,6 +171,7 @@ class Photos extends \Zotlabs\Web\Controller { } goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); + } if((argc() > 2) && (x($_REQUEST,'delete')) && ($_REQUEST['delete'] === t('Delete Photo'))) { @@ -501,6 +502,9 @@ class Photos extends \Zotlabs\Web\Controller { goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); } + if(is_ajax()) + killme(); + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $r['data']['folder']); } @@ -709,13 +713,15 @@ class Photos extends \Zotlabs\Web\Controller { ]); if($x = photos_album_exists($owner_uid, get_observer_hash(), $datum)) { - \App::set_pager_itemspage(30); $album = $x['display_path']; } else { - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); + $album = '/'; + //goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); } + \App::set_pager_itemspage(30); + if($_GET['order'] === 'posted') $order = 'ASC'; else @@ -1178,10 +1184,8 @@ class Photos extends \Zotlabs\Web\Controller { if($observer['xchan_hash'] === $item['author_xchan'] || $observer['xchan_hash'] === $item['owner_xchan']) $drop = replace_macros(get_markup_template('photo_drop.tpl'), array('$id' => $item['id'], '$delete' => t('Delete'))); - $name_e = $profile_name; $title_e = $item['title']; - unobscure($item); $body_e = prepare_text($item['body'],$item['mimetype']); $comments .= replace_macros($template,array( diff --git a/Zotlabs/Module/Pin.php b/Zotlabs/Module/Pin.php index e02fb017b..f82327ce6 100644 --- a/Zotlabs/Module/Pin.php +++ b/Zotlabs/Module/Pin.php @@ -37,7 +37,7 @@ class Pin extends \Zotlabs\Web\Controller { http_status_exit(404, 'Not found'); } - $midb64 = 'b64.' . base64url_encode($r[0]['mid']); + $midb64 = gen_link_id($r[0]['mid']); $pinned = (in_array($midb64, get_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], [])) ? true : false); switch(argv(1)) { diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php deleted file mode 100644 index 6e8042eaf..000000000 --- a/Zotlabs/Module/Ping.php +++ /dev/null @@ -1,707 +0,0 @@ -<?php - -namespace Zotlabs\Module; - -use Zotlabs\Lib\Apps; - -require_once('include/bbcode.php'); - -/** - * @brief Ping Controller. - * - */ -class Ping extends \Zotlabs\Web\Controller { - - /** - * @brief do several updates when pinged. - * - * This function does several tasks. Whenever called it checks for new messages, - * introductions, notifications, etc. and returns a json with the results. - * - * @result JSON - */ - function init() { - - $result = array(); - $notifs = array(); - - $result['notify'] = 0; - $result['home'] = 0; - $result['network'] = 0; - $result['intros'] = 0; - $result['mail'] = 0; - $result['register'] = 0; - $result['events'] = 0; - $result['events_today'] = 0; - $result['birthdays'] = 0; - $result['birthdays_today'] = 0; - $result['all_events'] = 0; - $result['all_events_today'] = 0; - $result['notice'] = []; - $result['info'] = []; - $result['pubs'] = 0; - $result['files'] = 0; - $result['forums'] = 0; - $result['forums_sub'] = []; - - if(! $_SESSION['static_loadtime']) - $_SESSION['static_loadtime'] = datetime_convert(); - - $t0 = dba_timer(); - - header("content-type: application/json"); - - $vnotify = false; - - $item_normal = item_normal(); - - if(local_channel()) { - $vnotify = get_pconfig(local_channel(),'system','vnotify'); - $evdays = intval(get_pconfig(local_channel(),'system','evdays')); - $ob_hash = get_observer_hash(); - } - - // if unset show all visual notification types - if($vnotify === false) - $vnotify = (-1); - if($evdays < 1) - $evdays = 3; - - /** - * If you have several windows open to this site and switch to a different channel - * in one of them, the others may get into a confused state showing you a page or options - * on that page which were only valid under the old identity. You session has changed. - * Therefore we send a notification of this fact back to the browser where it is picked up - * in javascript and which reloads the page it is on so that it is valid under the context - * of the now current channel. - */ - - $result['invalid'] = ((intval($_GET['uid'])) && (intval($_GET['uid']) != local_channel()) ? 1 : 0); - - /** - * Send all system messages (alerts) to the browser. - * Some are marked as informational and some represent - * errors or serious notifications. These typically - * will popup on the current page (no matter what page it is) - */ - - if(x($_SESSION, 'sysmsg')){ - foreach ($_SESSION['sysmsg'] as $m){ - $result['notice'][] = array('message' => $m); - } - unset($_SESSION['sysmsg']); - } - if(x($_SESSION, 'sysmsg_info')){ - foreach ($_SESSION['sysmsg_info'] as $m){ - $result['info'][] = array('message' => $m); - } - unset($_SESSION['sysmsg_info']); - } - if(! ($vnotify & VNOTIFY_INFO)) - $result['info'] = array(); - if(! ($vnotify & VNOTIFY_ALERT)) - $result['notice'] = array(); - - if(\App::$install) { - echo json_encode($result); - killme(); - } - - /** - * Update chat presence indication (if applicable) - */ - - if(get_observer_hash() && (! $result['invalid'])) { - $r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1", - dbesc(get_observer_hash()), - dbesc($_SERVER['REMOTE_ADDR']) - ); - $basic_presence = false; - if($r) { - $basic_presence = true; - q("update chatpresence set cp_last = '%s' where cp_id = %d", - dbesc(datetime_convert()), - intval($r[0]['cp_id']) - ); - } - if(! $basic_presence) { - q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client) - values( '%s', '%s', '%s', '%s' ) ", - dbesc(get_observer_hash()), - dbesc(datetime_convert()), - dbesc('online'), - dbesc($_SERVER['REMOTE_ADDR']) - ); - } - } - - /** - * Chatpresence continued... if somebody hasn't pinged recently, they've most likely left the page - * and shouldn't count as online anymore. We allow an expection for bots. - */ - - q("delete from chatpresence where cp_last < %s - INTERVAL %s and cp_client != 'auto' ", - db_utcnow(), db_quoteinterval('3 MINUTE') - ); - - - $sql_extra = ''; - if(! ($vnotify & VNOTIFY_LIKE)) - $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; - - if(local_channel()) { - $notify_pubs = ($vnotify & VNOTIFY_PUBS) && can_view_public_stream() && Apps::system_app_installed(local_channel(), 'Public Stream'); - } - else { - $notify_pubs = can_view_public_stream(); - } - - if($notify_pubs) { - $sys = get_sys_channel(); - - $pubs = q("SELECT count(id) as total from item - WHERE uid = %d - AND item_unseen = 1 - AND author_xchan != '%s' - AND created > '" . datetime_convert('UTC','UTC',$_SESSION['static_loadtime']) . "' - $item_normal - $sql_extra", - intval($sys['channel_id']), - dbesc(get_observer_hash()) - ); - - if($pubs) - $result['pubs'] = intval($pubs[0]['total']); - } - - - - if((argc() > 1) && (argv(1) === 'pubs') && ($notify_pubs)) { - $sys = get_sys_channel(); - $result = array(); - - $r = q("SELECT * FROM item - WHERE uid = %d - AND item_unseen = 1 - AND author_xchan != '%s' - AND created > '" . datetime_convert('UTC','UTC',$_SESSION['static_loadtime']) . "' - $item_normal - $sql_extra - ORDER BY created DESC - LIMIT 300", - intval($sys['channel_id']), - dbesc(get_observer_hash()) - ); - - if($r) { - xchan_query($r); - foreach($r as $rr) { - $rr['llink'] = str_replace('display/', 'pubstream/?f=&mid=', $rr['llink']); - $result[] = \Zotlabs\Lib\Enotify::format($rr); - } - } - -// logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA); - echo json_encode(array('notify' => $result)); - killme(); - } - - $t1 = dba_timer(); - - if((! local_channel()) || ($result['invalid'])) { - echo json_encode($result); - killme(); - } - - /** - * Everything following is only permitted under the context of a locally authenticated site member. - */ - - /** - * Handle "mark all xyz notifications read" requests. - */ - - // mark all items read - if(x($_REQUEST, 'markRead') && local_channel()) { - switch($_REQUEST['markRead']) { - case 'network': - $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1", - intval(local_channel()) - ); - break; - case 'home': - $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND item_unseen = 1 AND item_wall = 1", - intval(local_channel()) - ); - break; - case 'mail': - $r = q("UPDATE mail SET mail_seen = 1 WHERE channel_id = %d AND mail_seen = 0", - intval(local_channel()) - ); - break; - case 'all_events': - $r = q("UPDATE event SET dismissed = 1 WHERE uid = %d AND dismissed = 0 AND dtstart < '%s' AND dtstart > '%s' ", - 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')) - ); - break; - case 'notify': - $r = q("update notify set seen = 1 where uid = %d", - intval(local_channel()) - ); - break; - case 'pubs': - unset($_SESSION['static_loadtime']); - break; - default: - break; - } - } - - if(x($_REQUEST, 'markItemRead') && local_channel()) { - $r = q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND parent = %d", - intval(local_channel()), - intval($_REQUEST['markItemRead']) - ); - } - - /** - * URL ping/something will return detail for "something", e.g. a json list with which to populate a notification - * dropdown menu. - */ - if(argc() > 1 && argv(1) === 'notify') { - $t = q("SELECT * FROM notify WHERE uid = %d AND seen = 0 ORDER BY CREATED DESC", - intval(local_channel()) - ); - - if($t) { - foreach($t as $tt) { - $message = trim(strip_tags(bbcode($tt['msg']))); - - if(strpos($message, $tt['xname']) === 0) - $message = substr($message, strlen($tt['xname']) + 1); - - $mid = basename($tt['link']); - $mid = ((strpos($mid, 'b64.') === 0) ? @base64url_decode(substr($mid, 4)) : $mid); - - if(in_array($tt['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) { - // we need the thread parent - $r = q("select thr_parent from item where mid = '%s' and uid = %d limit 1", - dbesc($mid), - intval(local_channel()) - ); - $b64mid = ((strpos($r[0]['thr_parent'], 'b64.') === 0) ? $r[0]['thr_parent'] : 'b64.' . base64url_encode($r[0]['thr_parent'])); - } - else { - $b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid)); - } - - $notifs[] = array( - 'notify_link' => z_root() . '/notify/view/' . $tt['id'], - 'name' => $tt['xname'], - 'url' => $tt['url'], - 'photo' => $tt['photo'], - 'when' => relative_date($tt['created']), - 'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'), - 'b64mid' => (($tt['otype'] == 'item') ? $b64mid : 'undefined'), - 'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : 'undefined'), - 'message' => $message - ); - } - } - - echo json_encode(array('notify' => $notifs)); - killme(); - } - - if(argc() > 1 && argv(1) === 'mail') { - $channel = \App::get_channel(); - $t = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan - where channel_id = %d and mail_seen = 0 and mail_deleted = 0 - and from_xchan != '%s' order by created desc limit 50", - intval(local_channel()), - dbesc($channel['channel_hash']) - ); - - if($t) { - foreach($t as $zz) { - $notifs[] = array( - 'notify_link' => z_root() . '/mail/' . $zz['id'], - 'name' => $zz['xchan_name'], - 'addr' => $zz['xchan_addr'], - 'url' => $zz['xchan_url'], - 'photo' => $zz['xchan_photo_s'], - 'when' => relative_date($zz['created']), - 'hclass' => (intval($zz['mail_seen']) ? 'notify-seen' : 'notify-unseen'), - 'message' => t('sent you a private message'), - ); - } - } - - echo json_encode(array('notify' => $notifs)); - killme(); - } - - if(argc() > 1 && (argv(1) === 'network' || argv(1) === 'home')) { - $result = array(); - - if(argv(1) === 'home') { - $sql_extra .= ' and item_wall = 1 '; - } - - $r = q("SELECT * FROM item - WHERE uid = %d - AND item_unseen = 1 - AND author_xchan != '%s' - $item_normal - $sql_extra - ORDER BY created DESC - LIMIT 300", - intval(local_channel()), - dbesc($ob_hash) - ); - - if($r) { - xchan_query($r); - foreach($r as $item) { - $result[] = \Zotlabs\Lib\Enotify::format($item); - } - } -// logger('ping (network||home): ' . print_r($result, true), LOGGER_DATA); - echo json_encode(array('notify' => $result)); - killme(); - } - - 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_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ORDER BY abook_created DESC LIMIT 50", - intval(local_channel()) - ); - - if($r) { - foreach($r as $rr) { - $result[] = array( - 'notify_link' => z_root() . '/connections/ifpending', - 'name' => $rr['xchan_name'], - 'addr' => $rr['xchan_addr'], - 'url' => $rr['xchan_url'], - 'photo' => $rr['xchan_photo_s'], - 'when' => relative_date($rr['abook_created']), - 'hclass' => ('notify-unseen'), - 'message' => t('added your channel') - ); - } - } - logger('ping (intros): ' . print_r($result, true), LOGGER_DATA); - echo json_encode(array('notify' => $result)); - killme(); - } - - if((argc() > 1 && (argv(1) === 'register')) && is_site_admin()) { - $result = array(); - - $r = q("SELECT account_email, account_created from account where (account_flags & %d) > 0", - intval(ACCOUNT_PENDING) - ); - if($r) { - foreach($r as $rr) { - $result[] = array( - 'notify_link' => z_root() . '/admin/accounts', - 'name' => $rr['account_email'], - 'addr' => $rr['account_email'], - 'url' => '', - 'photo' => z_root() . '/' . get_default_profile_photo(48), - 'when' => relative_date($rr['account_created']), - 'hclass' => ('notify-unseen'), - 'message' => t('requires approval') - ); - } - } - logger('ping (register): ' . print_r($result, true), LOGGER_DATA); - echo json_encode(array('notify' => $result)); - killme(); - } - - if(argc() > 1 && (argv(1) === 'all_events')) { - $bd_format = t('g A l F d') ; // 8 AM Friday January 18 - - $result = array(); - - $r = q("SELECT * FROM event left join xchan on event_xchan = xchan_hash - WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0 - and etype in ( 'event', 'birthday' ) - ORDER BY dtstart 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')) - ); - - if($r) { - foreach($r as $rr) { - - $strt = datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart']); - $today = ((substr($strt, 0, 10) === datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d')) ? true : false); - $when = day_translate(datetime_convert('UTC', (($rr['adjust']) ? date_default_timezone_get() : 'UTC'), $rr['dtstart'], $bd_format)) . (($today) ? ' ' . t('[today]') : ''); - - $result[] = array( - 'notify_link' => z_root() . '/cdav/calendar/' . $rr['event_hash'], - 'name' => $rr['xchan_name'], - 'addr' => $rr['xchan_addr'], - 'url' => $rr['xchan_url'], - 'photo' => $rr['xchan_photo_s'], - 'when' => $when, - 'hclass' => ('notify-unseen'), - 'message' => t('posted an event') - ); - } - } - logger('ping (all_events): ' . print_r($result, true), LOGGER_DATA); - echo json_encode(array('notify' => $result)); - killme(); - } - - if(argc() > 1 && (argv(1) === 'files')) { - $result = array(); - - $r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM item - LEFT JOIN xchan on author_xchan = xchan_hash - WHERE item.verb = '%s' - AND item.obj_type = '%s' - AND item.uid = %d - AND item.owner_xchan != '%s' - AND item.item_unseen = 1", - dbesc(ACTIVITY_POST), - dbesc(ACTIVITY_OBJ_FILE), - intval(local_channel()), - dbesc($ob_hash) - ); - if($r) { - foreach($r as $rr) { - $result[] = array( - 'notify_link' => z_root() . '/sharedwithme', - 'name' => $rr['xchan_name'], - 'addr' => $rr['xchan_addr'], - 'url' => $rr['xchan_url'], - 'photo' => $rr['xchan_photo_s'], - 'when' => relative_date($rr['created']), - 'hclass' => ('notify-unseen'), - 'message' => t('shared a file with you') - ); - } - } - logger('ping (files): ' . print_r($result, true), LOGGER_DATA); - echo json_encode(array('notify' => $result)); - killme(); - } - - /** - * Normal ping - just the counts, no detail - */ - if($vnotify & VNOTIFY_SYSTEM) { - $t = q("select count(*) as total from notify where uid = %d and seen = 0", - intval(local_channel()) - ); - if($t) - $result['notify'] = intval($t[0]['total']); - } - - $t2 = dba_timer(); - - if($vnotify & VNOTIFY_FILES) { - $files = q("SELECT count(id) as total FROM item - WHERE verb = '%s' - AND obj_type = '%s' - AND uid = %d - AND owner_xchan != '%s' - AND item_unseen = 1", - dbesc(ACTIVITY_POST), - dbesc(ACTIVITY_OBJ_FILE), - intval(local_channel()), - dbesc($ob_hash) - ); - if($files) - $result['files'] = intval($files[0]['total']); - } - - $t3 = dba_timer(); - - if($vnotify & (VNOTIFY_NETWORK|VNOTIFY_CHANNEL)) { - - $r = q("SELECT id, item_wall FROM item - WHERE uid = %d and item_unseen = 1 - $item_normal - $sql_extra - AND author_xchan != '%s'", - intval(local_channel()), - dbesc($ob_hash) - ); - - if($r) { - $arr = array('items' => $r); - call_hooks('network_ping', $arr); - - foreach ($r as $it) { - if(intval($it['item_wall'])) - $result['home'] ++; - else - $result['network'] ++; - } - } - } - if(! ($vnotify & VNOTIFY_NETWORK)) - $result['network'] = 0; - if(! ($vnotify & VNOTIFY_CHANNEL)) - $result['home'] = 0; - - $t4 = dba_timer(); - - if($vnotify & VNOTIFY_INTRO) { - $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ", - intval(local_channel()) - ); - - $t5 = dba_timer(); - - if($intr) - $result['intros'] = intval($intr[0]['total']); - } - - $t6 = dba_timer(); - $channel = \App::get_channel(); - - if($vnotify & VNOTIFY_MAIL) { - $mails = q("SELECT count(id) as total from mail - WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ", - intval(local_channel()), - dbesc($channel['channel_hash']) - ); - if($mails) - $result['mail'] = intval($mails[0]['total']); - } - - if($vnotify & VNOTIFY_REGISTER) { - if (\App::$config['system']['register_policy'] == REGISTER_APPROVE && is_site_admin()) { - $regs = q("SELECT count(account_id) as total from account where (account_flags & %d) > 0", - intval(ACCOUNT_PENDING) - ); - if($regs) - $result['register'] = intval($regs[0]['total']); - } - } - - $t7 = dba_timer(); - - if($vnotify & (VNOTIFY_EVENT|VNOTIFY_EVENTTODAY|VNOTIFY_BIRTHDAY)) { - $events = q("SELECT etype, dtstart, adjust FROM event - WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0 - and etype in ( 'event', 'birthday' ) - ORDER BY dtstart ASC ", - 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')) - ); - - if($events) { - $result['all_events'] = count($events); - - if($result['all_events']) { - $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d'); - foreach($events as $x) { - $bd = false; - if($x['etype'] === 'birthday') { - $result['birthdays'] ++; - $bd = true; - } - else { - $result['events'] ++; - } - if(datetime_convert('UTC', ((intval($x['adjust'])) ? date_default_timezone_get() : 'UTC'), $x['dtstart'], 'Y-m-d') === $str_now) { - $result['all_events_today'] ++; - if($bd) - $result['birthdays_today'] ++; - else - $result['events_today'] ++; - } - } - } - } - } - if(! ($vnotify & VNOTIFY_EVENT)) - $result['all_events'] = $result['events'] = 0; - if(! ($vnotify & VNOTIFY_EVENTTODAY)) - $result['all_events_today'] = $result['events_today'] = 0; - if(! ($vnotify & VNOTIFY_BIRTHDAY)) - $result['birthdays'] = 0; - - - - if($vnotify & VNOTIFY_FORUMS) { - $forums = get_forum_channels(local_channel()); - - if($forums) { - $item_normal = item_normal(); - $fcount = count($forums); - $forums['total'] = 0; - - for($x = 0; $x < $fcount; $x ++) { - $p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'", - intval(local_channel()), - intval(TERM_FORUM), - dbesc($forums[$x]['xchan_name']) - ); - - $p_str = ids_to_querystr($p, 'parent'); - $p_sql = (($p_str) ? "OR parent IN ( $p_str )" : ''); - - $r = q("select count(id) as unseen from item - where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $item_normal $sql_extra", - intval(local_channel()), - dbesc($forums[$x]['xchan_hash']), - dbesc($forums[$x]['xchan_hash']) - ); - if($r[0]['unseen']) { - $forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id']); - $forums[$x]['name'] = $forums[$x]['xchan_name']; - $forums[$x]['addr'] = $forums[$x]['xchan_addr']; - $forums[$x]['url'] = $forums[$x]['xchan_url']; - $forums[$x]['photo'] = $forums[$x]['xchan_photo_s']; - $forums[$x]['unseen'] = $r[0]['unseen']; - $forums[$x]['private_forum'] = (($forums[$x]['private_forum']) ? 'lock' : ''); - $forums[$x]['message'] = (($forums[$x]['private_forum']) ? t('Private forum') : t('Public forum')); - - $forums['total'] = $forums['total'] + $r[0]['unseen']; - - unset($forums[$x]['abook_id']); - unset($forums[$x]['xchan_hash']); - unset($forums[$x]['xchan_name']); - unset($forums[$x]['xchan_url']); - unset($forums[$x]['xchan_photo_s']); - - //if($forums[$x]['private_forum']) - // unset($forums[$x]['private_forum']); - - } - else { - unset($forums[$x]); - } - } - $result['forums'] = $forums['total']; - unset($forums['total']); - - $result['forums_sub'] = $forums; - } - } - - $x = json_encode($result); - - $t8 = dba_timer(); - -// logger('ping timer: ' . sprintf('%01.4f %01.4f %01.4f %01.4f %01.4f %01.4f %01.4f %01.4f',$t8 - $t7, $t7 - $t6, $t6 - $t5, $t5 - $t4, $t4 - $t3, $t3 - $t2, $t2 - $t1, $t1 - $t0)); - - echo $x; - killme(); - } - -} diff --git a/Zotlabs/Module/Poke.php b/Zotlabs/Module/Poke.php index 1f1edfa18..d60a7f426 100644 --- a/Zotlabs/Module/Poke.php +++ b/Zotlabs/Module/Poke.php @@ -9,11 +9,11 @@ use Zotlabs\Web\Controller; * * Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book * This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or - * other web request. You must be logged in and connected to a channel. + * other web request. You must be logged in and connected to a channel. * If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb. * parent is a special argument which let's you attach this activity as a comment to an existing conversation, which * may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the adult - * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc. + * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc. * * private creates a private conversation with the recipient. Otherwise your channel's default post privacy is used. * @@ -25,41 +25,41 @@ require_once('include/items.php'); class Poke extends Controller { function init() { - + if(! local_channel()) return; if(! Apps::system_app_installed(local_channel(), 'Poke')) { return; } - + $uid = local_channel(); $channel = App::get_channel(); - + $verb = notags(trim($_REQUEST['verb'])); - - if(! $verb) + + if(! $verb) return; - + $verbs = get_poke_verbs(); - + if(! array_key_exists($verb,$verbs)) return; - + $activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]); - + $contact_id = intval($_REQUEST['cid']); $xchan = trim($_REQUEST['xchan']); if(! ($contact_id || $xchan)) return; - + $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0); - + logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG); - - + + if($contact_id) { $r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1", intval($contact_id), @@ -71,17 +71,17 @@ class Poke extends Controller { dbesc($xchan . '%') ); } - + if(! $r) { logger('poke: no target.'); return; } - + $target = $r[0]; $parent_item = null; - + if($parent) { - $r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid + $r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid from item where id = %d and parent = %d and uid = %d limit 1", intval($parent), intval($parent), @@ -98,18 +98,18 @@ class Poke extends Controller { } } elseif($contact_id) { - + $item_private = ((x($_GET,'private')) ? intval($_GET['private']) : 0); - + $allow_cid = (($item_private) ? '<' . $target['abook_xchan']. '>' : $channel['channel_allow_cid']); $allow_gid = (($item_private) ? '' : $channel['channel_allow_gid']); $deny_cid = (($item_private) ? '' : $channel['channel_deny_cid']); $deny_gid = (($item_private) ? '' : $channel['channel_deny_gid']); } - - + + $arr = array(); - + $arr['item_wall'] = 1; @@ -124,7 +124,7 @@ class Poke extends Controller { $arr['item_private'] = $item_private; $arr['obj_type'] = ACTIVITY_OBJ_PERSON; $arr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t($verbs[$verb][0]) . ' ' . '[zrl=' . $target['xchan_url'] . ']' . $target['xchan_name'] . '[/zrl]'; - + $obj = array( 'type' => ACTIVITY_OBJ_PERSON, 'title' => $target['xchan_name'], @@ -134,25 +134,25 @@ class Poke extends Controller { array('rel' => 'photo', 'type' => $target['xchan_photo_mimetype'], 'href' => $target['xchan_photo_l']) ), ); - + $arr['obj'] = json_encode($obj); - + $arr['item_origin'] = 1; $arr['item_wall'] = 1; $arr['item_unseen'] = 1; if(! $parent_item) $item['item_thread_top'] = 1; - - + + post_activity_item($arr); - + return; } - - - + + + function get() { - + if(! local_channel()) { notice( t('Permission denied.') . EOL); return; @@ -161,19 +161,17 @@ class Poke extends Controller { if(! Apps::system_app_installed(local_channel(), 'Poke')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Poke App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Poke somebody in your addressbook'); - return $o; + $papp = Apps::get_papp('Poke'); + return Apps::app_render($papp, 'module'); } nav_set_selected('Poke'); - + $name = ''; $id = ''; - + if(intval($_REQUEST['c'])) { - $r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash + $r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d limit 1", intval($_REQUEST['c']), intval(local_channel()) @@ -183,17 +181,17 @@ class Poke extends Controller { $id = $r[0]['abook_id']; } } - + $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : '0'); - + $verbs = get_poke_verbs(); - + $shortlist = array(); foreach($verbs as $k => $v) if($v[1] !== 'NOTRANSLATION') $shortlist[] = array($k,$v[1]); - - + + $poke_basic = get_config('system','poke_basic'); if($poke_basic) { $title = t('Poke'); @@ -203,7 +201,7 @@ class Poke extends Controller { $title = t('Poke/Prod'); $desc = t('Poke, prod or do other things to somebody'); } - + $o = replace_macros(get_markup_template('poke_content.tpl'),array( '$title' => $title, '$poke_basic' => $poke_basic, @@ -218,8 +216,8 @@ class Poke extends Controller { '$name' => $name, '$id' => $id )); - + return $o; - + } } diff --git a/Zotlabs/Module/Post.php b/Zotlabs/Module/Post.php deleted file mode 100644 index f67cbf020..000000000 --- a/Zotlabs/Module/Post.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * @file Zotlabs/Module/Post.php - * - * @brief Zot endpoint. - * - */ - -namespace Zotlabs\Module; - -require_once('include/zot.php'); - -/** - * @brief Post module. - * - */ -class Post extends \Zotlabs\Web\Controller { - - function init() { - if(array_key_exists('auth', $_REQUEST)) { - $x = new \Zotlabs\Zot\Auth($_REQUEST); - exit; - } - } - - function post() { - if(array_key_exists('data',$_REQUEST)) { - $z = new \Zotlabs\Zot\Receiver($_REQUEST['data'], get_config('system', 'prvkey'), new \Zotlabs\Zot\ZotHandler()); - exit; - } - - } - -} diff --git a/Zotlabs/Module/Prate.php b/Zotlabs/Module/Prate.php deleted file mode 100644 index 8b71657b8..000000000 --- a/Zotlabs/Module/Prate.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php -namespace Zotlabs\Module; - - -use Zotlabs\Lib\Crypto; - -class Prate extends \Zotlabs\Web\Controller { - - function init() { - if($_SERVER['REQUEST_METHOD'] === 'post') - return; - - if(! local_channel()) - return; - - $channel = \App::get_channel(); - - $target = argv(1); - if(! $target) - return; - - $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1", - dbesc($channel['channel_hash']), - dbesc($target) - ); - if($r) - json_return_and_die(array('rating' => $r[0]['xlink_rating'],'rating_text' => $r[0]['xlink_rating_text'])); - killme(); - } - - function post() { - - if(! local_channel()) - return; - - $channel = \App::get_channel(); - - $target = trim($_REQUEST['target']); - if(! $target) - return; - - if($target === $channel['channel_hash']) - return; - - $rating = intval($_POST['rating']); - if($rating < (-10)) - $rating = (-10); - if($rating > 10) - $rating = 10; - - $rating_text = trim(escape_tags($_REQUEST['rating_text'])); - - $signed = $target . '.' . $rating . '.' . $rating_text; - - $sig = base64url_encode(Crypto::sign($signed,$channel['channel_prvkey'])); - - - $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", - dbesc($channel['channel_hash']), - dbesc($target) - ); - if($z) { - $record = $z[0]['xlink_id']; - $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s' - where xlink_id = %d", - intval($rating), - dbesc($rating_text), - dbesc($sig), - dbesc(datetime_convert()), - intval($record) - ); - } - else { - $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", - dbesc($channel['channel_hash']), - dbesc($target), - intval($rating), - dbesc($rating_text), - dbesc($sig), - dbesc(datetime_convert()) - ); - $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", - dbesc($channel['channel_hash']), - dbesc($orig_record[0]['abook_xchan']) - ); - if($z) - $record = $z[0]['xlink_id']; - } - if($record) { - \Zotlabs\Daemon\Master::Summon(array('Ratenotif','rating',$record)); - } - - json_return_and_die(array('result' => true));; - } - - - - - - - - - - - - -} diff --git a/Zotlabs/Module/Probe.php b/Zotlabs/Module/Probe.php deleted file mode 100644 index 3bc4dac72..000000000 --- a/Zotlabs/Module/Probe.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php -namespace Zotlabs\Module; - -use App; -use Zotlabs\Lib\Apps; -use Zotlabs\Lib\Crypto; - -require_once('include/zot.php'); - -class Probe extends \Zotlabs\Web\Controller { - - function get() { - - if(local_channel()) { - if(! Apps::system_app_installed(local_channel(), 'Remote Diagnostics')) { - //Do not display any associated widgets at this point - App::$pdl = ''; - - $o = '<b>' . t('Remote Diagnostics App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Perform diagnostics on remote channels'); - return $o; - } - } - - nav_set_selected('Remote Diagnostics'); - - $o .= '<h3>Remote Diagnostics</h3>'; - - $o .= '<form action="probe" method="get">'; - $o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />'; - $o .= '<input type="submit" name="submit" value="Submit" /></form>'; - - $o .= '<br /><br />'; - - if(x($_GET,'addr')) { - $channel = App::get_channel(); - $addr = trim($_GET['addr']); - $do_import = ((intval($_GET['import']) && is_site_admin()) ? true : false); - - $j = \Zotlabs\Zot\Finger::run($addr,$channel,false); - - $o .= '<pre>'; - if(! $j['success']) { - $o .= "<strong>https connection failed. Trying again with auto failover to http.</strong>\r\n\r\n"; - $j = \Zotlabs\Zot\Finger::run($addr,$channel,true); - if(! $j['success']) { - return $o; - } - } - if($do_import && $j) - $x = import_xchan($j); - if($j && $j['permissions'] && $j['permissions']['iv']) - $j['permissions'] = json_decode(Crypto::unencapsulate($j['permissions'],$channel['channel_prvkey']),true); - $o .= str_replace("\n",'<br />',print_r($j,true)); - $o .= '</pre>'; - } - return $o; - } - -} diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php index d6c80b653..022efc2cd 100644 --- a/Zotlabs/Module/Profile_photo.php +++ b/Zotlabs/Module/Profile_photo.php @@ -1,7 +1,11 @@ <?php + namespace Zotlabs\Module; +use App; +use Zotlabs\Daemon\Master; use Zotlabs\Lib\Libsync; +use Zotlabs\Web\Controller; /* * @file Profile_photo.php @@ -15,109 +19,123 @@ require_once('include/photos.php'); require_once('include/channel.php'); /* @brief Function for sync'ing permissions of profile-photos and their profile -* -* @param $profileid The id number of the profile to sync -* @return void -*/ - + * + */ +class Profile_photo extends Controller { -class Profile_photo extends \Zotlabs\Web\Controller { - /* @brief Initalize the profile-photo edit view * - * @return void - * */ - + function init() { - - if(! local_channel()) { + + if (!local_channel()) { return; } - - $channel = \App::get_channel(); - profile_load($channel['channel_address']); - + + $channel = App::get_channel(); + $profile = App::$argv[1]; + + profile_load($channel['channel_address'], $profile); + + } - + /* @brief Evaluate posted values * - * @param $a Current application - * @return void - * */ - + function post() { - - if(! local_channel()) { + + if (!local_channel()) { return; } - - $channel = \App::get_channel(); - + + $channel = App::get_channel(); + check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo'); - - // Remove cover photo - if(isset($_POST['remove'])) { - - $r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1", - intval(PHOTO_PROFILE), - intval(local_channel()) - ); - - if($r) { - q("update photo set photo_usage = %d where photo_usage = %d and uid = %d", - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE), - intval(local_channel()) - ); - - $sync = attach_export_data($channel,$r[0]['resource_id']); - if($sync) - Libsync:: build_sync_packet($channel['channel_id'],array('file' => array($sync))); + + $r = q("select id, profile_guid, is_default, gender from profile where uid = %d", + intval(local_channel()) + ); + + $profile_id = intval($_POST['profile']); + $default_profile_id = null; + $profile = []; + + foreach ($r as $rr) { + if ($rr['is_default']) { + $default_profile_id = intval($rr['id']); } - + + if ($profile_id === intval($rr['id'])) { + $profile = $rr; + } + } + + $is_default_profile = ($profile_id === $default_profile_id); + + // Remove profile photo + if (isset($_POST['remove'])) { + + if ($is_default_profile) { + + $r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1", + intval(PHOTO_PROFILE), + intval(local_channel()) + ); + + if ($r) { + q("update photo set photo_usage = %d where photo_usage = %d and uid = %d", + intval(PHOTO_NORMAL), + intval(PHOTO_PROFILE), + intval(local_channel()) + ); + + q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d", + dbesc(z_root() . '/photo/profile/l/' . local_channel()), + dbesc(z_root() . '/photo/profile/m/' . local_channel()), + intval(local_channel()) + ); + } + } + else { + q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d", + dbesc(z_root() . '/' . get_default_profile_photo(300)), + dbesc(z_root() . '/' . get_default_profile_photo(80)), + intval($profile_id), + intval(local_channel()) + ); + } + + $sync = attach_export_data($channel, $r[0]['resource_id']); + if ($sync) + Libsync:: build_sync_packet($channel['channel_id'], ['file' => [$sync]]); + $_SESSION['reload_avatar'] = true; - - goaway(z_root() . '/profiles'); + + goaway(z_root() . '/profiles/' . $profile_id); } - - if((array_key_exists('cropfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) { - + + if ((array_key_exists('cropfinal', $_POST)) && (intval($_POST['cropfinal']) == 1)) { + // logger('crop: ' . print_r($_POST,true)); // phase 2 - we have finished cropping - - if(argc() != 2) { - notice( t('Image uploaded but image cropping failed.') . EOL ); + + if (argc() != 2) { + notice(t('Image uploaded but image cropping failed.') . EOL); return; } - - $image_id = argv(1); - - if(substr($image_id,-2,1) == '-') { - $scale = substr($image_id,-1,1); - $image_id = substr($image_id,0,-2); - } + $image_id = argv(1); - // unless proven otherwise - $is_default_profile = 1; - - if($_REQUEST['profile']) { - $r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1", - intval($_REQUEST['profile']), - intval(local_channel()) - ); - if($r) { - $profile = $r[0]; - if(! intval($profile['is_default'])) - $is_default_profile = 0; - } - } + if (substr($image_id, -2, 1) == '-') { + $scale = substr($image_id, -1, 1); + $image_id = substr($image_id, 0, -2); + } - $srcX = intval($_POST['xstart']); $srcY = intval($_POST['ystart']); $srcW = intval($_POST['xfinal']) - $srcX; @@ -126,45 +144,45 @@ class Profile_photo extends \Zotlabs\Web\Controller { $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = %d LIMIT 1", dbesc($image_id), dbesc(local_channel()), - intval($scale)); - if($r) { - - $base_image = $r[0]; + intval($scale) + ); + + if ($r) { + + $base_image = $r[0]; $base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content'])); - + $im = photo_factory($base_image['content'], $base_image['mimetype']); - if($im->is_valid()) { - - $im->cropImage(300,$srcX,$srcY,$srcW,$srcH); - + if ($im->is_valid()) { + + $im->cropImage(300, $srcX, $srcY, $srcW, $srcH); + $aid = get_account_id(); - - $p = [ - 'aid' => $aid, - 'uid' => local_channel(), + + $p = [ + 'aid' => $aid, + 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'], - 'filename' => $base_image['filename'], + 'filename' => $base_image['filename'], 'album' => t('Profile Photos'), 'os_path' => $base_image['os_path'], 'display_path' => $base_image['display_path'], - 'photo_usage' => PHOTO_PROFILE, - 'edited' => dbescdate($base_image['edited']) + 'photo_usage' => (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL), + 'edited' => dbescdate($base_image['edited']) ]; - - $p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL); - + $r1 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_300); - + $im->scaleImage(80); $r2 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_80); - + $im->scaleImage(48); $r3 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_48); - if($r1 === false || $r2 === false || $r3 === false) { + if ($r1 === false || $r2 === false || $r3 === false) { // if one failed, delete them all so we can start over. - notice( t('Image resize failed.') . EOL ); - $x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d )", + notice(t('Image resize failed.') . EOL); + q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d )", dbesc($base_image['resource_id']), local_channel(), intval(PHOTO_RES_PROFILE_300), @@ -179,59 +197,55 @@ class Profile_photo extends \Zotlabs\Web\Controller { intval(PHOTO_RES_PROFILE_80), intval(PHOTO_RES_PROFILE_48) ); - if($x) { - foreach($x as $xx) { + if ($x) { + foreach ($x as $xx) { @unlink(dbunescbin($xx['content'])); } } - + return; } - + // If setting for the default profile, unset the profile photo flag from any other photos I own - - if($is_default_profile) { - $r = q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d", + if ($is_default_profile) { + q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d", dbesc(z_root() . '/photo/profile/l/' . local_channel()), dbesc(z_root() . '/photo/profile/m/' . local_channel()), intval(local_channel()) ); - - $r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d + q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND resource_id != '%s' AND uid = %d", intval(PHOTO_NORMAL), intval(PHOTO_PROFILE), dbesc($base_image['resource_id']), intval(local_channel()) ); - - send_profile_photo_activity($channel,$base_image,$profile); - + send_profile_photo_activity($channel, $base_image, $profile); } else { - $r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d", + q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d", dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-4'), dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-5'), - intval($_REQUEST['profile']), + intval($profile_id), intval(local_channel()) ); } - + // set $send to false in profiles_build_sync() to return the data - // so that we only send one sync packet. + // so that we only send one sync packet. + + $sync_profiles = profiles_build_sync(local_channel(), false); - $sync_profiles = profiles_build_sync(local_channel(),false); - // We'll set the updated profile-photo timestamp even if it isn't the default profile, // so that browsers will do a cache update unconditionally // Also set links back to site-specific profile photo url in case it was - // changed to a generic URL by a clone operation. Otherwise the new photo may + // changed to a generic URL by a clone operation. Otherwise the new photo may // not get pushed to other sites correctly. - - $r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' + + q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'", dbesc($im->getType()), dbescdate($base_image['edited']), @@ -241,341 +255,372 @@ class Profile_photo extends \Zotlabs\Web\Controller { dbesc($channel['xchan_hash']) ); - photo_profile_setperms(local_channel(),$base_image['resource_id'],$_REQUEST['profile']); + photo_profile_setperms(local_channel(), $base_image['resource_id'], $profile_id); - $sync = attach_export_data($channel,$base_image['resource_id']); - if($sync) - Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles)); + $sync = attach_export_data($channel, $base_image['resource_id']); + if ($sync) + Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync], 'profile' => $sync_profiles]); // Similarly, tell the nav bar to bypass the cache and update the avatar image. $_SESSION['reload_avatar'] = true; - - info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL); - + + info(t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL); + // Update directory in background - \Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id'])); - + Master::Summon(['Directory', $channel['channel_id']]); + } else - notice( t('Unable to process image') . EOL); + notice(t('Unable to process image') . EOL); } - - goaway(z_root() . '/profiles'); + + goaway(z_root() . '/profiles/' . $profile_id); return; // NOTREACHED } - + // A new photo was uploaded. Store it and save some important details // in App::$data for use in the cropping function - - - $hash = photo_new_resource(); + + $hash = photo_new_resource(); $importing = false; - $smallest = 0; - + $smallest = 0; - if($_REQUEST['importfile']) { - $hash = $_REQUEST['importfile']; + if ($_REQUEST['importfile']) { + $hash = $_REQUEST['importfile']; $importing = true; } else { - require_once('include/attach.php'); - - $res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true)); - - logger('attach_store: ' . print_r($res,true)); + + $matches = []; + $partial = false; + + if (array_key_exists('HTTP_CONTENT_RANGE', $_SERVER)) { + $pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/', $_SERVER['HTTP_CONTENT_RANGE'], $matches); + if ($pm) { + logger('Content-Range: ' . print_r($matches, true)); + $partial = true; + } + } + + if ($partial) { + $x = save_chunk($channel, $matches[1], $matches[2], $matches[3]); + + if ($x['partial']) { + header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0)); + json_return_and_die($x); + } + else { + header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0)); + + $_FILES['userfile'] = [ + 'name' => $x['name'], + 'type' => $x['type'], + 'tmp_name' => $x['tmp_name'], + 'error' => $x['error'], + 'size' => $x['size'] + ]; + } + } + else { + if (!array_key_exists('userfile', $_FILES)) { + $_FILES['userfile'] = [ + 'name' => $_FILES['files']['name'], + 'type' => $_FILES['files']['type'], + 'tmp_name' => $_FILES['files']['tmp_name'], + 'error' => $_FILES['files']['error'], + 'size' => $_FILES['files']['size'] + ]; + } + } + + $res = attach_store(App::get_channel(), get_observer_hash(), '', ['album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true, 'source' => 'photos']); + + json_return_and_die(['message' => $hash]); + } - - if(($res && intval($res['data']['is_photo'])) || $importing) { + + if (($res && intval($res['data']['is_photo'])) || $importing) { $i = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale", dbesc($hash), intval(local_channel()) ); - - if(! $i) { - notice( t('Image upload failed.') . EOL ); + + if (!$i) { + notice(t('Image upload failed.') . EOL); return; } + $os_storage = false; - - foreach($i as $ii) { - if(intval($ii['imgscale']) < PHOTO_RES_640) { - $smallest = intval($ii['imgscale']); + + foreach ($i as $ii) { + if (intval($ii['imgscale']) < PHOTO_RES_640) { + $smallest = intval($ii['imgscale']); $os_storage = intval($ii['os_storage']); - $imagedata = $ii['content']; - $filetype = $ii['mimetype']; + $imagedata = $ii['content']; + $filetype = $ii['mimetype']; } } } - + $imagedata = (($os_storage) ? @file_get_contents(dbunescbin($imagedata)) : dbunescbin($imagedata)); - $ph = photo_factory($imagedata, $filetype); - - if(! $ph->is_valid()) { - notice( t('Unable to process image.') . EOL ); + $ph = photo_factory($imagedata, $filetype); + + if (!$ph->is_valid()) { + notice(t('Unable to process image.') . EOL); return; } - - return $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest); + + return $this->profile_photo_crop_ui_head($ph, $hash, $smallest); // This will "fall through" to the get() method, and since - // App::$data['imagecrop'] is set, it will proceed to cropping - // rather than present the upload form + // App::$data['imagecrop'] is set, it will proceed to cropping + // rather than present the upload form } - - + + /* @brief Generate content of profile-photo view * - * @param $a Current application - * @return void - * */ - - + + function get() { - - if(! local_channel()) { - notice( t('Permission denied.') . EOL ); + + if (!local_channel()) { + notice(t('Permission denied.') . EOL); return; } - - $channel = \App::get_channel(); - $pf = 0; - $newuser = false; - - if(argc() == 2 && argv(1) === 'new') - $newuser = true; - - if(argv(1) === 'use') { - if (argc() < 3) { - notice( t('Permission denied.') . EOL ); - return; - }; - - $resource_id = argv(2); - - $pf = (($_REQUEST['pf']) ? intval($_REQUEST['pf']) : 0); + $channel = App::get_channel(); + $profile_id = (($_REQUEST['profile']) ? intval($_REQUEST['profile']) : intval(argv(1))); + $default_profile_id = null; - $c = q("select id, is_default from profile where uid = %d", - intval(local_channel()) - ); + $r = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc", + intval(local_channel()) + ); - $multi_profiles = true; - if(($c) && (count($c) === 1) && (intval($c[0]['is_default']))) { - $_REQUEST['profile'] = $c[0]['id']; - $multi_profiles = false; + foreach ($r as $rr) { + if ($rr['is_default']) { + $default_profile_id = intval($rr['id']); } - else { - $_REQUEST['profile'] = $pf; + + if ($profile_id === intval($rr['id'])) { + $profile = $rr; } + } + + $is_default_profile = ($profile_id === $default_profile_id); + + if (argv(1) === 'use') { + if (argc() < 3) { + notice(t('Permission denied.') . EOL); + return; + }; + + $resource_id = argv(2); $r = q("SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY imgscale ASC", intval(local_channel()), dbesc($resource_id) ); - if(! $r) { - notice( t('Photo not available.') . EOL ); + if (!$r) { + notice(t('Photo not available.') . EOL); return; } $havescale = false; - foreach($r as $rr) { - if($rr['imgscale'] == PHOTO_RES_PROFILE_80) + foreach ($r as $rr) { + if ($rr['imgscale'] == PHOTO_RES_PROFILE_80) $havescale = true; } - + // set an already loaded and cropped photo as profile photo - - if($havescale) { - // unset any existing profile photos - $x = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d", - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE), + + if ($havescale) { + + if ($is_default_profile) { + + // unset any existing profile photos + q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d", + intval(PHOTO_NORMAL), + intval(PHOTO_PROFILE), + intval(local_channel()) + ); + + $edited = datetime_convert(); + + q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0", + intval(PHOTO_PROFILE), + dbescdate($edited), + intval(local_channel()), + dbesc($resource_id) + ); + + q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'", + dbescdate($edited), + dbesc($channel['xchan_hash']) + + ); + + } + + q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d", + dbesc(z_root() . '/photo/' . $resource_id . '-4'), + dbesc(z_root() . '/photo/' . $resource_id . '-5'), + intval($profile_id), intval(local_channel()) ); - $edited = datetime_convert(); - - $x = q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0", - intval(PHOTO_PROFILE), - dbescdate($edited), - intval(local_channel()), - dbesc($resource_id) - ); - - $x = q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'", - dbescdate($edited), - dbesc($channel['xchan_hash']) - ); - - photo_profile_setperms(local_channel(),$resource_id,$_REQUEST['profile']); + photo_profile_setperms(local_channel(), $resource_id, $profile_id); - $sync = attach_export_data($channel,$resource_id); - if($sync) - Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); + $sync = attach_export_data($channel, $resource_id); + if ($sync) + Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]); $_SESSION['reload_avatar'] = true; - \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel())); - - goaway(z_root() . '/profiles'); + Master::Summon(['Directory', local_channel()]); + + goaway(z_root() . '/profiles/' . $profile_id); } - + $r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1", intval($r[0]['id']), intval(local_channel()) - + ); - if(! $r) { - notice( t('Photo not available.') . EOL ); + if (!$r) { + notice(t('Photo not available.') . EOL); return; } - - if(intval($r[0]['os_storage'])) + + if (intval($r[0]['os_storage'])) { $data = @file_get_contents(dbunescbin($r[0]['content'])); - else - $data = dbunescbin($r[0]['content']); - - $ph = photo_factory($data, $r[0]['mimetype']); + } + else { + $data = dbunescbin($r[0]['content']); + } + + $ph = photo_factory($data, $r[0]['mimetype']); $smallest = 0; - if($ph->is_valid()) { + + if ($ph->is_valid()) { + // go ahead as if we have just uploaded a new photo to crop $i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d order by imgscale", dbesc($r[0]['resource_id']), intval(local_channel()) ); - - if($i) { + + if ($i) { $hash = $i[0]['resource_id']; - foreach($i as $ii) { - if(intval($ii['imgscale']) < PHOTO_RES_640) { + foreach ($i as $ii) { + if (intval($ii['imgscale']) < PHOTO_RES_640) { $smallest = intval($ii['imgscale']); } } - } - } - - if($multi_profiles) { - \App::$data['importfile'] = $resource_id; - } - else { - $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest); + } } + $this->profile_photo_crop_ui_head($ph, $hash, $smallest); + // falls through with App::$data['imagecrop'] set so we go straight to the cropping section } - - // present an upload form - $profiles = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc", - intval(local_channel()) - ); + $importing = ((array_key_exists('importfile', App::$data)) ? true : false); - if($profiles) { - for($x = 0; $x < count($profiles); $x ++) { - $profiles[$x]['selected'] = false; - if($pf && $profiles[$x]['id'] == $pf) - $profiles[$x]['selected'] = true; - if((! $pf) && $profiles[$x]['is_default']) - $profiles[$x]['selected'] = true; - } - } + if (!x(App::$data, 'imagecrop')) { - $importing = ((array_key_exists('importfile',\App::$data)) ? true : false); - - if(! x(\App::$data,'imagecrop')) { - $tpl = get_markup_template('profile_photo.tpl'); - - $o .= replace_macros($tpl,array( - '$user' => \App::$channel['channel_address'], - '$info' => ((count($profiles) > 1) ? t('Your default profile photo is visible to anybody on the internet. Profile photos for alternate profiles will inherit the permissions of the profile') : t('Your profile photo is visible to anybody on the internet and may be distributed to other websites.')), - '$importfile' => (($importing) ? \App::$data['importfile'] : ''), - '$lbl_upfile' => t('Upload File:'), - '$lbl_profiles' => t('Select a profile:'), - '$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')), - '$submit' => (($importing) ? t('Use') : t('Upload')), - '$remove' => t('Remove'), - '$profiles' => $profiles, - '$single' => ((count($profiles) == 1) ? true : false), - '$profile0' => $profiles[0], - '$embedPhotos' => t('Use a photo from your albums'), - '$embedPhotosModalTitle' => t('Use a photo from your albums'), + + $o = replace_macros($tpl, [ + '$user' => App::$channel['channel_address'], + '$info' => (($is_default_profile) ? t('This profile photo will be visible to anybody on the internet and may be distributed to other websites.') : t('This profile photo will be visible only to channels with permission to view this profile.')), + '$importfile' => (($importing) ? App::$data['importfile'] : ''), + '$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')), + '$submit' => t('Upload'), + '$remove' => t('Reset to default'), + '$profile_id' => $profile_id, + '$profile' => $profile, + '$embedPhotos' => t('Use a photo from your albums'), + '$embedPhotosModalTitle' => t('Use a photo from your albums'), '$embedPhotosModalCancel' => t('Cancel'), - '$embedPhotosModalOK' => t('OK'), - '$modalchooseimages' => t('Choose images to embed'), - '$modalchoosealbum' => t('Choose an album'), - '$modaldiffalbum' => t('Choose a different album'), - '$modalerrorlist' => t('Error getting album list'), - '$modalerrorlink' => t('Error getting photo link'), - '$modalerroralbum' => t('Error getting album'), - '$form_security_token' => get_form_security_token("profile_photo"), - '$select' => t('Select existing photo'), - )); - + '$embedPhotosModalOK' => t('OK'), + '$modalchooseimages' => t('Choose images to embed'), + '$modalchoosealbum' => t('Choose an album'), + '$modaldiffalbum' => t('Choose a different album'), + '$modalerrorlist' => t('Error getting album list'), + '$modalerrorlink' => t('Error getting photo link'), + '$modalerroralbum' => t('Error getting album'), + '$form_security_token' => get_form_security_token("profile_photo"), + '$select' => t('Select existing'), + ]); + call_hooks('profile_photo_content_end', $o); - + return $o; } else { // present a cropping form - $filename = \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution']; - $resolution = \App::$data['imagecrop_resolution']; - $tpl = get_markup_template("cropbody.tpl"); - $o .= replace_macros($tpl,array( - '$filename' => $filename, - '$profile' => intval($_REQUEST['profile']), - '$resource' => \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'], - '$image_url' => z_root() . '/photo/' . $filename, - '$title' => t('Crop Image'), - '$desc' => t('Please adjust the image cropping for optimum viewing.'), + $filename = App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution']; + $tpl = get_markup_template("cropbody.tpl"); + + $o = replace_macros($tpl, [ + '$filename' => $filename, + '$profile' => $profile_id, + '$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'], + '$image_url' => z_root() . '/photo/' . $filename, + '$title' => t('Crop Image'), + '$desc' => t('Please adjust the image cropping for optimum viewing.'), '$form_security_token' => get_form_security_token("profile_photo"), - '$done' => t('Done Editing') - )); + '$done' => t('Done editing') + ]); + return $o; } - + return; // NOTREACHED } - + /* @brief Generate the UI for photo-cropping * - * @param $a Current application - * @param $ph Photo-Factory - * @return void + * @param $ph + * @param $hash + * @param $smallest * */ - - - - function profile_photo_crop_ui_head(&$a, $ph, $hash, $smallest){ - - $max_length = get_config('system','max_image_length'); - if(! $max_length) + + + function profile_photo_crop_ui_head($ph, $hash, $smallest) { + + $max_length = get_config('system', 'max_image_length'); + + if (!$max_length) { $max_length = MAX_IMAGE_LENGTH; - if($max_length > 0) + } + if ($max_length > 0) { $ph->scaleImage($max_length); - - \App::$data['width'] = $ph->getWidth(); - \App::$data['height'] = $ph->getHeight(); - - if(\App::$data['width'] < 500 || \App::$data['height'] < 500) { + } + + App::$data['width'] = $ph->getWidth(); + App::$data['height'] = $ph->getHeight(); + + if (App::$data['width'] < 500 || App::$data['height'] < 500) { $ph->scaleImageUp(400); - \App::$data['width'] = $ph->getWidth(); - \App::$data['height'] = $ph->getHeight(); + App::$data['width'] = $ph->getWidth(); + App::$data['height'] = $ph->getHeight(); } - - - \App::$data['imagecrop'] = $hash; - \App::$data['imagecrop_resolution'] = $smallest; - \App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array()); + + App::$data['imagecrop'] = $hash; + App::$data['imagecrop_resolution'] = $smallest; + App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), []); + return; } - - + + } diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php index 9aa342223..e248cd028 100644 --- a/Zotlabs/Module/Profiles.php +++ b/Zotlabs/Module/Profiles.php @@ -163,35 +163,6 @@ class Profiles extends \Zotlabs\Web\Controller { killme(); } - - - - // Run profile_load() here to make sure the theme is set before - // we start loading content - if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) { - if(feature_enabled(local_channel(),'multi_profiles')) - $id = \App::$argv[1]; - else { - $x = q("select id from profile where uid = %d and is_default = 1", - intval(local_channel()) - ); - if($x) - $id = $x[0]['id']; - } - $r = q("SELECT * FROM profile WHERE id = %d AND uid = %d LIMIT 1", - intval($id), - intval(local_channel()) - ); - if(! count($r)) { - notice( t('Profile not found.') . EOL); - \App::$error = 404; - return; - } - - $chan = \App::get_channel(); - - profile_load($chan['channel_address'],$r[0]['id']); - } } function post() { @@ -317,8 +288,6 @@ class Profiles extends \Zotlabs\Web\Controller { $work = fix_mce_lf(escape_tags(trim($_POST['work']))); $education = fix_mce_lf(escape_tags(trim($_POST['education']))); - $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0); - // start fresh and create a new vcard. TODO: preserve the original guid or whatever else needs saving // $orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null); @@ -514,6 +483,16 @@ class Profiles extends \Zotlabs\Web\Controller { $value = $locality . $comma1 . $region . $comma2 . $country_name; } + $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0); + + $suggestme = ((x($_POST, 'suggestme')) ? intval($_POST['suggestme']) : 0); + set_pconfig(local_channel(), 'system', 'suggestme', $suggestme); + + $show_presence = (((x($_POST, 'show_presence')) && (intval($_POST['show_presence']) == 1)) ? 1 : 0); + set_pconfig(local_channel(), 'system', 'show_online_status', $show_presence); + + $publish = ((x($_POST, 'profile_in_directory') && (intval($_POST['profile_in_directory']) == 1)) ? 1 : 0); + profile_activity($changes,$value); } @@ -552,7 +531,8 @@ class Profiles extends \Zotlabs\Web\Controller { employment = '%s', education = '%s', hide_friends = %d, - profile_vcard = '%s' + profile_vcard = '%s', + publish = %d WHERE id = %d AND uid = %d", dbesc($profile_name), dbesc($name), @@ -588,6 +568,7 @@ class Profiles extends \Zotlabs\Web\Controller { dbesc($education), intval($hide_friends), dbesc($profile_vcard), + intval($publish), intval(argv(1)), intval(local_channel()) ); @@ -595,32 +576,31 @@ class Profiles extends \Zotlabs\Web\Controller { if($r) info( t('Profile updated.') . EOL); - $r = q("select * from profile where id = %d and uid = %d limit 1", - intval(argv(1)), - intval(local_channel()) - ); - if($r) { - require_once('include/zot.php'); - Libsync::build_sync_packet(local_channel(),array('profile' => $r)); - } - $channel = \App::get_channel(); if($namechanged && $is_default) { - $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'", + // change name on all associated xchans by matching the url + q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'", dbesc($name), dbesc(datetime_convert()), dbesc(z_root() . '/channel/' . $channel['channel_address']) ); - $r = q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'", + q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'", dbesc($name), dbesc($channel['xchan_hash']) ); } + $r = q("select * from profile where id = %d and uid = %d limit 1", + intval(argv(1)), + intval(local_channel()) + ); + + if($r) { + Libsync::build_sync_packet(local_channel(), ['profile' => $r]); + } + if($is_default) { - // reload the info for the sidebar widget - why does this not work? - profile_load($channel['channel_address']); \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel())); } } @@ -631,13 +611,13 @@ class Profiles extends \Zotlabs\Web\Controller { $o = ''; - $channel = \App::get_channel(); - if(! local_channel()) { notice( t('Permission denied.') . EOL); return; } + $channel = \App::get_channel(); + require_once('include/channel.php'); $profile_fields_basic = get_profile_fields_basic(); @@ -653,15 +633,20 @@ class Profiles extends \Zotlabs\Web\Controller { if($x) $id = $x[0]['id']; } + $r = q("SELECT * FROM profile WHERE id = %d AND uid = %d LIMIT 1", intval($id), intval(local_channel()) ); + if(! $r) { notice( t('Profile not found.') . EOL); return; } + // make sure we got uptodate data + profile_load($channel['channel_address'], $id); + $editselect = 'none'; \App::$page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), array( @@ -675,13 +660,43 @@ class Profiles extends \Zotlabs\Web\Controller { else $fields = $profile_fields_basic; - $hide_friends = array( - 'hide_friends', - t('Hide your connections list from viewers of this profile'), - $r[0]['hide_friends'], - '', - array(t('No'),t('Yes')) - ); + $show_presence = []; + $profile_in_dir = ''; + $suggestme = ''; + $hide_friends = []; + $is_default = (($r[0]['is_default']) ? 1 : 0); + + if ($is_default) { + + $hide_friends = array( + 'hide_friends', + t('Hide my connections from viewers of this profile'), + $r[0]['hide_friends'], + '', + [t('No'), t('Yes')] + ); + + + $opt_tpl = get_markup_template("field_checkbox.tpl"); + if (get_config('system', 'publish_all')) { + $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />'; + } + else { + $profile_in_dir = replace_macros($opt_tpl, [ + '$field' => ['profile_in_directory', t('Publish my default profile in the network directory'), $r[0]['publish'], '', [t('No'), t('Yes')]], + ]); + } + + $suggestme = get_pconfig(local_channel(), 'system', 'suggestme'); + $suggestme = (($suggestme === false) ? '0' : $suggestme); // default if not set: 0 + + $suggestme = replace_macros($opt_tpl, [ + '$field' => ['suggestme', t('Suggest me as a potential contact to new members'), $suggestme, '', [t('No'), t('Yes')]], + ]); + + $show_presence_val = intval(get_pconfig(local_channel(), 'system', 'show_online_status')); + $show_presence = ['show_presence', t('Reveal my online status'), $show_presence_val, '', [t('No'), t('Yes')]]; + } $q = q("select * from profdef where true"); if($q) { @@ -702,15 +717,15 @@ class Profiles extends \Zotlabs\Web\Controller { //logger('extra_fields: ' . print_r($extra_fields,true)); - $vc = $r[0]['profile_vcard']; - $vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null); - $vcard = (($vctmp) ? get_vcard_array($vctmp,$r[0]['id']) : [] ); + //$vc = $r[0]['profile_vcard']; + //$vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null); + //$vcard = (($vctmp) ? get_vcard_array($vctmp,$r[0]['id']) : [] ); $f = get_config('system','birthday_input_format'); if(! $f) $f = 'ymd'; - $is_default = (($r[0]['is_default']) ? 1 : 0); + $tpl = get_markup_template("profile_edit.tpl"); $o .= replace_macros($tpl,array( @@ -719,12 +734,12 @@ class Profiles extends \Zotlabs\Web\Controller { '$profile_clone_link' => 'profiles/clone/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_clone"), '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_drop"), '$fields' => $fields, - '$vcard' => $vcard, + //'$vcard' => $vcard, '$guid' => $r[0]['profile_guid'], '$banner' => t('Edit Profile Details'), '$submit' => t('Submit'), '$viewprof' => t('View this profile'), - '$editvis' => t('Edit visibility'), + '$editvis' => t('Edit visibility'), '$tools_label' => t('Profile Tools'), '$coverpic' => t('Change cover photo'), '$profpic' => t('Change profile photo'), @@ -732,7 +747,7 @@ class Profiles extends \Zotlabs\Web\Controller { '$cl_prof' => t('Clone this profile'), '$del_prof' => t('Delete this profile'), '$addthing' => t('Add profile things'), - '$personal' => t('Personal'), + '$basic' => t('Basic'), '$location' => t('Location'), '$relation' => t('Relationship'), '$miscellaneous'=> t('Miscellaneous'), @@ -784,23 +799,28 @@ class Profiles extends \Zotlabs\Web\Controller { '$contact' => array('contact', t('Contact information and social networks'), $r[0]['contact']), '$channels' => array('channels', t('My other channels'), $r[0]['channels']), '$extra_fields' => $extra_fields, - '$comms' => t('Communications'), - '$tel_label' => t('Phone'), - '$email_label' => t('Email'), - '$impp_label' => t('Instant messenger'), - '$url_label' => t('Website'), - '$adr_label' => t('Address'), - '$note_label' => t('Note'), - '$mobile' => t('Mobile'), - '$home' => t('Home'), - '$work' => t('Work'), - '$other' => t('Other'), - '$add_card' => t('Add Contact'), - '$add_field' => t('Add Field'), - '$create' => t('Create'), - '$update' => t('Update'), - '$delete' => t('Delete'), - '$cancel' => t('Cancel'), + //'$comms' => t('Communications'), + //'$tel_label' => t('Phone'), + //'$email_label' => t('Email'), + //'$impp_label' => t('Instant messenger'), + //'$url_label' => t('Website'), + //'$adr_label' => t('Address'), + //'$note_label' => t('Note'), + //'$mobile' => t('Mobile'), + //'$home' => t('Home'), + //'$work' => t('Work'), + //'$other' => t('Other'), + //'$add_card' => t('Add Contact'), + //'$add_field' => t('Add Field'), + //'$create' => t('Create'), + //'$update' => t('Update'), + //'$delete' => t('Delete'), + //'$cancel' => t('Cancel'), + + '$show_presence' => $show_presence, + '$suggestme' => $suggestme, + '$profile_in_dir' => $profile_in_dir, + )); $arr = array('profile' => $r[0], 'entry' => $o); diff --git a/Zotlabs/Module/Pubsites.php b/Zotlabs/Module/Pubsites.php index 4b64d9af6..fd5aeaa72 100644 --- a/Zotlabs/Module/Pubsites.php +++ b/Zotlabs/Module/Pubsites.php @@ -6,7 +6,6 @@ use Zotlabs\Lib\Libzotdir; class Pubsites extends \Zotlabs\Web\Controller { function get() { - require_once('include/dir_fns.php'); $dirmode = intval(get_config('system','directory_mode')); if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) { diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 113f0a196..583974e22 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -16,10 +16,8 @@ class Pubstream extends \Zotlabs\Web\Controller { if(! Apps::system_app_installed(local_channel(), 'Public Stream')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Public Stream App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('The unmoderated public stream of this hub'); - return $o; + $papp = Apps::get_papp('Public Stream'); + return Apps::app_render($papp, 'module'); } } @@ -44,19 +42,16 @@ class Pubstream extends \Zotlabs\Web\Controller { $site_firehose = false; } - $mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : ''); - $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : ''); - - - if(strpos($mid,'b64.') === 0) - $decoded = @base64url_decode(substr($mid,4)); - if($decoded) - $mid = $decoded; + $mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : ''); + if ($mid === false) { + notice(t('Malformed message id.') . EOL); + return; + } + $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : ''); $item_normal = item_normal(); $item_normal_update = item_normal_update(); - - $net = ((array_key_exists('net',$_REQUEST)) ? escape_tags($_REQUEST['net']) : ''); + $net = ((array_key_exists('net',$_REQUEST)) ? escape_tags($_REQUEST['net']) : ''); $title = replace_macros(get_markup_template("section_title.tpl"),array( '$title' => (($hashtags) ? '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8') : '') @@ -65,15 +60,15 @@ class Pubstream extends \Zotlabs\Web\Controller { $o = (($hashtags) ? $title : ''); if(local_channel() && (! $update)) { - + $channel = \App::get_channel(); $channel_acl = array( - 'allow_cid' => $channel['channel_allow_cid'], - 'allow_gid' => $channel['channel_allow_gid'], - 'deny_cid' => $channel['channel_deny_cid'], + 'allow_cid' => $channel['channel_allow_cid'], + 'allow_gid' => $channel['channel_allow_gid'], + 'deny_cid' => $channel['channel_deny_cid'], 'deny_gid' => $channel['channel_deny_gid'] - ); + ); $x = array( 'is_owner' => true, @@ -94,12 +89,12 @@ class Pubstream extends \Zotlabs\Web\Controller { 'jotnets' => true, 'reset' => t('Reset form') ); - + $o .= '<div id="jot-popup">'; $o .= status_editor($a,$x,false,'Pubstream'); $o .= '</div>'; } - + if(! $update && !$load) { nav_set_selected(t('Public Stream')); @@ -110,15 +105,14 @@ class Pubstream extends \Zotlabs\Web\Controller { $maxheight = get_config('system','home_divmore_height'); if(! $maxheight) $maxheight = 400; - + $o .= '<div id="live-pubstream"></div>' . "\r\n"; - $o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1)) - . "; var profile_page = " . \App::$pager['page'] + $o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1)) + . "; var profile_page = " . \App::$pager['page'] . "; divmore_height = " . intval($maxheight) . "; </script>\r\n"; - - //if we got a decoded hash we must encode it again before handing to javascript - if($decoded) - $mid = 'b64.' . base64url_encode($mid); + + //if we got a decoded hash we must encode it again before handing to javascript + $mid = gen_link_id($mid); \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( '$baseurl' => z_root(), @@ -151,7 +145,7 @@ class Pubstream extends \Zotlabs\Web\Controller { '$dbegin' => '' )); } - + if($update && ! $load) { // only setup pagination on initial page view $pager_sql = ''; @@ -160,10 +154,10 @@ class Pubstream extends \Zotlabs\Web\Controller { \App::set_pager_itemspage(10); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); } - + require_once('include/channel.php'); require_once('include/security.php'); - + if($site_firehose) { $uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0 and item_wall = 1 "; } @@ -173,7 +167,7 @@ class Pubstream extends \Zotlabs\Web\Controller { $sql_extra = item_permissions_sql($sys['channel_id']); \App::$data['firehose'] = intval($sys['channel_id']); } - + if(get_config('system','public_list_mode')) $page_mode = 'list'; else @@ -184,7 +178,7 @@ class Pubstream extends \Zotlabs\Web\Controller { $sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG)); } - $net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : ''); + $net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : ''); $net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : ''); $abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " "; @@ -196,13 +190,13 @@ class Pubstream extends \Zotlabs\Web\Controller { //logger('update: ' . $update . ' load: ' . $load); if($update) { - - $ordering = "commented"; - + + $ordering = get_config('system', 'pubstream_ordering', 'commented'); + if($load) { if($mid) { $r = q("SELECT parent AS item_id FROM item - left join abook on item.author_xchan = abook.abook_xchan + left join abook on item.author_xchan = abook.abook_xchan $net_query WHERE mid = '%s' $uids $item_normal and (abook.abook_blocked = 0 or abook.abook_flags is null) @@ -212,7 +206,7 @@ class Pubstream extends \Zotlabs\Web\Controller { } else { // Fetch a page full of parent items for this page - $r = q("SELECT item.id AS item_id FROM item + $r = dbq("SELECT item.id AS item_id FROM item left join abook on ( item.author_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids and item.item_thread_top = 1 $item_normal @@ -234,7 +228,7 @@ class Pubstream extends \Zotlabs\Web\Controller { ); } else { - $r = q("SELECT parent AS item_id FROM item + $r = dbq("SELECT parent AS item_id FROM item left join abook on item.author_xchan = abook.abook_xchan $net_query WHERE true $uids $item_normal_update @@ -247,20 +241,19 @@ class Pubstream extends \Zotlabs\Web\Controller { // Then fetch all the children of the parents that are on this page $parents_str = ''; - + if($r) { - + $parents_str = ids_to_querystr($r,'item_id'); - - $items = q("SELECT item.*, item.id AS item_id FROM item + + $items = dbq("SELECT item.*, item.id AS item_id FROM item WHERE true $uids $item_normal - AND item.parent IN ( %s ) - $sql_extra ", - dbesc($parents_str) + AND item.parent IN ( $parents_str ) + $sql_extra" ); - + // use effective_uid param of xchan_query to help sort out comment permission - // for sys_channel owned items. + // for sys_channel owned items. xchan_query($items,true,(($sys) ? local_channel() : 0)); $items = fetch_post_tags($items,true); @@ -269,9 +262,9 @@ class Pubstream extends \Zotlabs\Web\Controller { else { $items = array(); } - + } - + // fake it $mode = (($hashtags) ? 'search' : 'pubstream'); @@ -279,13 +272,13 @@ class Pubstream extends \Zotlabs\Web\Controller { if($mid) $o .= '<div id="content-complete"></div>'; - + if(($items) && (! $update)) $o .= alt_pager(count($items)); $_SESSION['loadtime'] = datetime_convert(); return $o; - + } } diff --git a/Zotlabs/Module/Randprof.php b/Zotlabs/Module/Randprof.php index c38b07ead..731d3aece 100644 --- a/Zotlabs/Module/Randprof.php +++ b/Zotlabs/Module/Randprof.php @@ -15,7 +15,7 @@ class Randprof extends \Zotlabs\Web\Controller { $x = random_profile(); if($x) goaway(chanlink_hash($x)); - + /** FIXME this doesn't work at the moment as a fallback */ goaway(z_root() . '/profile'); } @@ -25,13 +25,11 @@ class Randprof extends \Zotlabs\Web\Controller { if(! Apps::system_app_installed(local_channel(), 'Random Channel')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Random Channel App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Visit a random channel in the $Projectname network'); - return $o; + $papp = Apps::get_papp('Random Channel'); + return Apps::app_render($papp, 'module'); } } } - + } diff --git a/Zotlabs/Module/Rate.php b/Zotlabs/Module/Rate.php deleted file mode 100644 index d29c370fc..000000000 --- a/Zotlabs/Module/Rate.php +++ /dev/null @@ -1,174 +0,0 @@ -<?php -namespace Zotlabs\Module; - - - -use Zotlabs\Lib\Crypto; - -class Rate extends \Zotlabs\Web\Controller { - - function init() { - - if(! local_channel()) - return; - - $channel = \App::get_channel(); - - $target = $_REQUEST['target']; - if(! $target) - return; - - \App::$data['target'] = $target; - - if($target) { - $r = q("SELECT * FROM xchan where xchan_hash like '%s' LIMIT 1", - dbesc($target) - ); - if($r) { - \App::$poi = $r[0]; - } - else { - $r = q("select * from site where site_url like '%s' and site_type = %d", - dbesc('%' . $target), - intval(SITE_TYPE_ZOT) - ); - if($r) { - \App::$data['site'] = $r[0]; - \App::$data['site']['site_url'] = strtolower($r[0]['site_url']); - } - } - } - - - return; - - } - - - function post() { - - if(! local_channel()) - return; - - if(! \App::$data['target']) - return; - - if(! $_REQUEST['execute']) - return; - - $channel = \App::get_channel(); - - $rating = intval($_POST['rating']); - if($rating < (-10)) - $rating = (-10); - if($rating > 10) - $rating = 10; - - $rating_text = trim(escape_tags($_REQUEST['rating_text'])); - - $signed = \App::$data['target'] . '.' . $rating . '.' . $rating_text; - - $sig = base64url_encode(Crypto::sign($signed,$channel['channel_prvkey'])); - - $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", - dbesc($channel['channel_hash']), - dbesc(\App::$data['target']) - ); - - if($z) { - $record = $z[0]['xlink_id']; - $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s' - where xlink_id = %d", - intval($rating), - dbesc($rating_text), - dbesc($sig), - dbesc(datetime_convert()), - intval($record) - ); - } - else { - $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", - dbesc($channel['channel_hash']), - dbesc(\App::$data['target']), - intval($rating), - dbesc($rating_text), - dbesc($sig), - dbesc(datetime_convert()) - ); - $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", - dbesc($channel['channel_hash']), - dbesc(\App::$data['target']) - ); - if($z) - $record = $z[0]['xlink_id']; - } - - if($record) { - \Zotlabs\Daemon\Master::Summon(array('Ratenotif','rating',$record)); - } - - } - - function get() { - - if(! local_channel()) { - notice( t('Permission denied.') . EOL); - return; - } - - // if(! \App::$data['target']) { - // notice( t('No recipients.') . EOL); - // return; - // } - - $rating_enabled = get_config('system','rating_enabled'); - if(! $rating_enabled) { - notice('Ratings are disabled on this site.'); - return; - } - - $channel = \App::get_channel(); - - $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1", - dbesc($channel['channel_hash']), - dbesc(\App::$data['target']) - ); - if($r) { - \App::$data['xlink'] = $r[0]; - $rating_val = $r[0]['xlink_rating']; - $rating_text = $r[0]['xlink_rating_text']; - } - else { - $rating_val = 0; - $rating_text = ''; - } - - if($rating_enabled) { - $rating = replace_macros(get_markup_template('rating_slider.tpl'),array( - '$min' => -10, - '$val' => $rating_val - )); - } - else { - $rating = false; - } - - $o = replace_macros(get_markup_template('rating_form.tpl'),array( - '$header' => t('Rating'), - '$website' => t('Website:'), - '$site' => ((\App::$data['site']) ? '<a href="' . \App::$data['site']['site_url'] . '" >' . \App::$data['site']['site_url'] . '</a>' : ''), - 'target' => \App::$data['target'], - '$tgt_name' => ((\App::$poi && \App::$poi['xchan_name']) ? \App::$poi['xchan_name'] : sprintf( t('Remote Channel [%s] (not yet known on this site)'), substr(\App::$data['target'],0,16))), - '$lbl_rating' => t('Rating (this information is public)'), - '$lbl_rating_txt' => t('Optionally explain your rating (this information is public)'), - '$rating_txt' => $rating_text, - '$rating' => $rating, - '$rating_val' => $rating_val, - '$slide' => $slide, - '$submit' => t('Submit') - )); - - return $o; - - } -} diff --git a/Zotlabs/Module/Ratings.php b/Zotlabs/Module/Ratings.php deleted file mode 100644 index 055b16ca3..000000000 --- a/Zotlabs/Module/Ratings.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -namespace Zotlabs\Module; - -require_once('include/dir_fns.php'); - - -class Ratings extends \Zotlabs\Web\Controller { - - function init() { - - if(observer_prohibited()) { - return; - } - - if(local_channel()) - load_contact_links(local_channel()); - - $dirmode = intval(get_config('system','directory_mode')); - - $x = find_upstream_directory($dirmode); - if($x) - $url = $x['url']; - - $rating_enabled = get_config('system','rating_enabled'); - - if(! $rating_enabled) - return; - - if(argc() > 1) - $hash = argv(1); - - if(! $hash) { - notice('Must supply a channel identififier.'); - return; - } - - $results = false; - - $x = z_fetch_url($url . '/ratingsearch/' . urlencode($hash)); - - - if($x['success']) - $results = json_decode($x['body'],true); - - - if((! $results) || (! $results['success'])) { - - notice('No results.'); - return; - } - - if(array_key_exists('xchan_hash',$results['target'])) - \App::$poi = $results['target']; - - $friends = array(); - $others = array(); - - if($results['ratings']) { - foreach($results['ratings'] as $n) { - if(is_array(\App::$contacts) && array_key_exists($n['xchan_hash'],\App::$contacts)) - $friends[] = $n; - else - $others[] = $n; - } - } - - \App::$data = array('target' => $results['target'], 'results' => array_merge($friends,$others)); - - if(! \App::$data['results']) { - notice( t('No ratings') . EOL); - } - - return; - } - - - - - - function get() { - - if(observer_prohibited()) { - notice( t('Public access denied.') . EOL); - return; - } - - $rating_enabled = get_config('system','rating_enabled'); - - if(! $rating_enabled) - return; - - $site_target = ((array_key_exists('target',\App::$data) && array_key_exists('site_url',\App::$data['target'])) ? - '<a href="' . \App::$data['target']['site_url'] . '" >' . \App::$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' => \App::$data['results'] - )); - - return $o; - } - - -} diff --git a/Zotlabs/Module/Ratingsearch.php b/Zotlabs/Module/Ratingsearch.php deleted file mode 100644 index dcbfd6a9b..000000000 --- a/Zotlabs/Module/Ratingsearch.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -namespace Zotlabs\Module; - - - -class Ratingsearch extends \Zotlabs\Web\Controller { - - function init() { - - $ret = array('success' => false); - - $dirmode = intval(get_config('system','directory_mode')); - - if($dirmode == DIRECTORY_MODE_NORMAL) { - $ret['message'] = 'This site is not a directory server.'; - json_return_and_die($ret); - } - - if(argc() > 1) - $hash = argv(1); - - if(! $hash) { - $ret['message'] = 'No channel identifier'; - json_return_and_die($ret); - } - - if(strpos($hash,'@')) { - $r = q("select * from hubloc where hubloc_addr = '%s' limit 1", - dbesc($hash) - ); - if($r) - $hash = $r[0]['hubloc_hash']; - } - - $p = q("select * from xchan where xchan_hash like '%s'", - dbesc($hash . '%') - ); - - if($p) - $target = $p[0]['xchan_hash']; - else { - $p = q("select * from site where site_url like '%s' and site_type = %d ", - dbesc('%' . $hash), - intval(SITE_TYPE_ZOT) - ); - 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 - and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 - order by xchan_name asc", - dbesc($target) - ); - - if($r) { - $ret['ratings'] = $r; - } - else - $ret['ratings'] = array(); - - json_return_and_die($ret); - - } - - -} diff --git a/Zotlabs/Module/Rbmark.php b/Zotlabs/Module/Rbmark.php index 226cef69e..87b774495 100644 --- a/Zotlabs/Module/Rbmark.php +++ b/Zotlabs/Module/Rbmark.php @@ -6,12 +6,11 @@ require_once('include/crypto.php'); require_once('include/items.php'); require_once('include/taxonomy.php'); require_once('include/conversation.php'); -require_once('include/zot.php'); require_once('include/bookmarks.php'); /** * remote bookmark - * + * * https://yoursite/rbmark?f=&title=&url=&private=&remote_return= * * This can be called via either GET or POST, use POST for long body content as suhosin often limits GET parameter length @@ -31,45 +30,45 @@ class Rbmark extends \Zotlabs\Web\Controller { function post() { if($_POST['submit'] !== t('Save')) return; - + logger('rbmark_post: ' . print_r($_REQUEST,true)); - + $channel = \App::get_channel(); - + $t = array('url' => escape_tags($_REQUEST['url']),'term' => escape_tags($_REQUEST['title'])); bookmark_add($channel,$channel,$t,((x($_REQUEST,'private')) ? intval($_REQUEST['private']) : 0), array('menu_id' => ((x($_REQUEST,'menu_id')) ? intval($_REQUEST['menu_id']) : 0), 'menu_name' => ((x($_REQUEST,'menu_name')) ? escape_tags($_REQUEST['menu_name']) : ''), 'ischat' => ((x($_REQUEST['ischat'])) ? intval($_REQUEST['ischat']) : 0) )); - + goaway(z_root() . '/bookmarks'); - + } - - + + function get() { - + $o = ''; - + if(! local_channel()) { - + // The login procedure is going to bugger our $_REQUEST variables // so save them in the session. - + if(array_key_exists('url',$_REQUEST)) { $_SESSION['bookmark'] = $_REQUEST; } return login(); } - + // If we have saved rbmark session variables, but nothing in the current $_REQUEST, recover the saved variables - + if((! array_key_exists('url',$_REQUEST)) && (array_key_exists('bookmark',$_SESSION))) { $_REQUEST = $_SESSION['bookmark']; unset($_SESSION['bookmark']); } - + if($_REQUEST['remote_return']) { $_SESSION['remote_return'] = $_REQUEST['remote_return']; } @@ -78,12 +77,12 @@ class Rbmark extends \Zotlabs\Web\Controller { goaway($_SESSION['remote_return']); goaway(z_root() . '/bookmarks'); } - + $channel = \App::get_channel(); - - + + $m = menu_list($channel['channel_id'],'',MENU_BOOKMARK); - + $menus = array(); if($m) { $menus = array(0 => ''); @@ -92,10 +91,10 @@ class Rbmark extends \Zotlabs\Web\Controller { } } $menu_select = array('menu_id',t('Select a bookmark folder'),false,'',$menus); - - + + $o .= replace_macros(get_markup_template('rbmark.tpl'), array( - + '$header' => t('Save Bookmark'), '$url' => array('url',t('URL of bookmark'),escape_tags($_REQUEST['url'])), '$title' => array('title',t('Description'),escape_tags($_REQUEST['title'])), @@ -104,18 +103,18 @@ class Rbmark extends \Zotlabs\Web\Controller { '$submit' => t('Save'), '$menu_name' => array('menu_name',t('Or enter new bookmark folder name'),'',''), '$menus' => $menu_select - + )); - - - - - - + + + + + + return $o; - + } - - - + + + } diff --git a/Zotlabs/Module/Regate.php b/Zotlabs/Module/Regate.php index 379195461..33bb8d957 100644 --- a/Zotlabs/Module/Regate.php +++ b/Zotlabs/Module/Regate.php @@ -2,6 +2,9 @@ namespace Zotlabs\Module; +use Zotlabs\Lib\Connect; +use Zotlabs\Daemon\Master; + require_once('include/security.php'); /** @@ -184,7 +187,24 @@ class Regate extends \Zotlabs\Web\Controller { $new_channel = auto_channel_create($cra['account']['account_id']); if($new_channel['success']) { + $channel_id = $new_channel['channel']['channel_id']; + + // If we have an inviter, connect. + if ($didx === 'i' && intval($r['reg_byc'])) { + $invite_channel = channelx_by_n($r['reg_byc']); + if ($invite_channel) { + $f = Connect::connect($new_channel['channel'], $invite_channel['xchan_addr']); + if ($f['success']) { + $can_view_stream = intval(get_abconfig($channel_id, $f['abook']['abook_xchan'], 'their_perms', 'view_stream')); + // If we can view their stream, pull in some posts + if ($can_view_stream) { + Master::Summon(['Onepoll', $f['abook']['abook_id']]); + } + } + } + } + change_channel($channel_id); $nextpage = 'profiles/' . $channel_id; $msg_code = 'ZAR1239I'; diff --git a/Zotlabs/Module/Removeme.php b/Zotlabs/Module/Removeme.php index 876d61ca6..4d475ead6 100644 --- a/Zotlabs/Module/Removeme.php +++ b/Zotlabs/Module/Removeme.php @@ -5,67 +5,67 @@ namespace Zotlabs\Module; class Removeme extends \Zotlabs\Web\Controller { function post() { - + if(! local_channel()) return; - + if($_SESSION['delegate']) return; - + if((! x($_POST,'qxz_password')) || (! strlen(trim($_POST['qxz_password'])))) return; - + if((! x($_POST,'verify')) || (! strlen(trim($_POST['verify'])))) return; - + if($_POST['verify'] !== $_SESSION['remove_account_verify']) return; - - + + $account = \App::get_account(); - - + + $x = account_verify_password($account['account_email'],$_POST['qxz_password']); if(! ($x && $x['account'])) return; - + if($account['account_password_changed'] > NULL_DATE) { $d1 = datetime_convert('UTC','UTC','now - 48 hours'); - if($account['account_password_changed'] > d1) { + if($account['account_password_changed'] > $d1) { notice( t('Channel removals are not allowed within 48 hours of changing the account password.') . EOL); return; } } - + $global_remove = 0; //intval($_POST['global']); channel_remove(local_channel(),1 - $global_remove,true); - + } - - + + function get() { - + if(! local_channel()) goaway(z_root()); - + $hash = random_string(); - + $_SESSION['remove_account_verify'] = $hash; - + $tpl = get_markup_template('removeme.tpl'); $o .= replace_macros($tpl, array( '$basedir' => z_root(), '$hash' => $hash, - '$title' => t('Remove This Channel'), - '$desc' => [ t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!') ], + '$title' => t('Remove Channel'), + '$desc' => [ t('WARNING: '), t('This channel will be permanently removed. '), t('This action can not be undone!') ], '$passwd' => t('Please enter your password for verification:'), // '$global' => [ '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'), [ t('No'),t('Yes') ] ], '$submit' => t('Remove Channel') )); - - return $o; - + + return $o; + } - + } diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php index 031270845..013817597 100644 --- a/Zotlabs/Module/Rpost.php +++ b/Zotlabs/Module/Rpost.php @@ -1,12 +1,13 @@ <?php namespace Zotlabs\Module; /** @file */ +use Zotlabs\Lib\Libzot; + require_once('include/acl_selectors.php'); require_once('include/crypto.php'); require_once('include/items.php'); require_once('include/taxonomy.php'); require_once('include/conversation.php'); -require_once('include/zot.php'); /** * remote post @@ -42,7 +43,7 @@ class Rpost extends \Zotlabs\Web\Controller { // by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin // blocks them. - $url = get_rpost_path(\App::get_observer()); + $url = Libzot::get_rpost_path(\App::get_observer()); // make sure we're not looping to our own hub if(($url) && (! stristr($url, \App::get_hostname()))) { foreach($_GET as $key => $arg) { @@ -65,6 +66,73 @@ class Rpost extends \Zotlabs\Web\Controller { nav_set_selected('Post'); + if (local_channel() && array_key_exists('userfile',$_FILES)) { + + $channel = App::get_channel(); + $observer = App::get_observer(); + + $def_album = get_pconfig($channel['channel_id'],'system','photo_path'); + $def_attach = get_pconfig($channel['channel_id'],'system','attach_path'); + + $r = attach_store($channel, (($observer) ? $observer['xchan_hash'] : ''), '', [ + 'source' => 'editor', + 'visible' => 0, + 'album' => $def_album, + 'directory' => $def_attach, + 'flags' => 1, // indicates temporary permissions are created + 'allow_cid' => '<' . $channel['channel_hash'] . '>' + ]); + + if (! $r['success']) { + notice( $r['message'] . EOL); + } + + $s = EMPTY_STR; + + if (intval($r['data']['is_photo'])) { + $s .= "\n\n" . $r['body'] . "\n\n"; + } + + $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']; + + if (strpos($r['data']['filetype'],'video') === 0) { + $s .= "\n\n" . '[zvideo]' . $url . '[/zvideo]' . "\n\n"; + } + + if (strpos($r['data']['filetype'],'audio') === 0) { + $s .= "\n\n" . '[zaudio]' . $url . '[/zaudio]' . "\n\n"; + } + + if ($r['data']['filetype'] === 'image/svg+xml') { + $x = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); + if ($x) { + $bb = svg2bb($x); + if ($bb) { + $s .= "\n\n" . $bb; + } + else { + logger('empty return from svgbb'); + } + } + else { + logger('unable to read svg data file: ' . 'store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); + } + } + + if ($r['data']['filetype'] === 'text/calendar') { + $content = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); + if ($content) { + $ev = ical_to_ev($content); + if ($ev) { + $s .= "\n\n" . format_event_bbcode($ev[0]) . "\n\n"; + } + } + } + + $s .= "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n"; + $_REQUEST['body'] = ((array_key_exists('body',$_REQUEST)) ? $_REQUEST['body'] . $s : $s); + } + // If we have saved rpost session variables, but nothing in the current $_REQUEST, recover the saved variables if((! array_key_exists('body',$_REQUEST)) && (array_key_exists('rpost',$_SESSION))) { diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php index 2ad79e3f6..fdc251b07 100644 --- a/Zotlabs/Module/Search.php +++ b/Zotlabs/Module/Search.php @@ -3,9 +3,11 @@ namespace Zotlabs\Module; use App; +use Zotlabs\Lib\Libzot; use Zotlabs\Lib\Activity; use Zotlabs\Lib\ActivityStreams; use Zotlabs\Web\Controller; +use Zotlabs\Lib\Zotfinger; class Search extends Controller { @@ -25,10 +27,11 @@ class Search extends Controller { nav_set_selected('Search'); - require_once("include/bbcode.php"); - require_once('include/security.php'); + require_once('include/bbcode.php'); require_once('include/conversation.php'); require_once('include/items.php'); + require_once('include/security.php'); + $format = (($_REQUEST['format']) ? $_REQUEST['format'] : ''); if ($format !== '') { @@ -38,11 +41,9 @@ class Search extends Controller { $observer = App::get_observer(); $observer_hash = (($observer) ? $observer['xchan_hash'] : ''); - $o = '<div id="live-search"></div>' . "\r\n"; + $o = '<div class="generic-content-wrapper-styled">' . "\r\n"; - $o .= '<div class="generic-content-wrapper-styled">' . "\r\n"; - - $o .= '<h3>' . t('Search') . '</h3>'; + $o .= '<h2>' . t('Search') . '</h2>'; if (x(App::$data, 'search')) $search = trim(App::$data['search']); @@ -58,26 +59,31 @@ class Search extends Controller { $o .= search($search, 'search-box', '/search', ((local_channel()) ? true : false)); if (local_channel() && strpos($search, 'https://') === 0 && !$update && !$load) { - $j = Activity::fetch(punify($search), App::get_channel()); - if ($j) { - $AS = new ActivityStreams($j); - if ($AS->is_valid()) { - // check if is_an_actor, otherwise import activity - if (is_array($AS->obj) && !ActivityStreams::is_an_actor($AS->obj)) { - $item = Activity::decode_note($AS); - if ($item) { - logger('parsed_item: ' . print_r($item, true), LOGGER_DATA); - Activity::store(App::get_channel(), $observer_hash, $AS, $item, true, true); - goaway(z_root() . '/display/' . gen_link_id($item['mid'])); - } + if (strpos($search, 'b64.') !== false) { + if (strpos($search, '?') !== false) { + $search = strtok($search, '?'); + } + + $search = unpack_link_id(basename($search)); + } + + $f = Libzot::fetch_conversation(App::get_channel(), punify($search), true); + + if ($f) { + $mid = $f[0]['message_id']; + foreach ($f as $m) { + if (strpos($search, $m['message_id']) === 0) { + $mid = $m['message_id']; + break; } } + + goaway(z_root() . '/hq/' . gen_link_id($mid)); } else { - // try other fetch providers (e.g. diaspora) + // try other fetch providers (e.g. diaspora, pubcrawl) $hookdata = [ - 'channel' => App::get_channel(), - 'data' => $search + 'url' => punify($search) ]; call_hooks('fetch_provider', $hookdata); } @@ -87,21 +93,21 @@ class Search extends Controller { $tag = true; $search = substr($search, 1); } - if (strpos($search, '@') === 0) { + elseif(strpos($search, '@') === 0) { $search = substr($search, 1); goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search); } - if (strpos($search, '!') === 0) { + elseif(strpos($search, '!') === 0) { $search = substr($search, 1); goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search); } - if (strpos($search, '?') === 0) { + elseif(strpos($search, '?') === 0) { $search = substr($search, 1); goaway(z_root() . '/help' . '?f=1&navsearch=1&search=' . $search); } // look for a naked webbie - if (strpos($search,'@') !== false && strpos($search,'http') !== 0) { + if (strpos($search, '@') !== false && strpos($search, 'http') !== 0) { goaway(z_root() . '/directory' . '?f=1&navsearch=1&search=' . $search); } @@ -216,7 +222,7 @@ class Search extends Controller { } if ($r) { $str = ids_to_querystr($r, 'item_id'); - $r = q("select *, id as item_id from item where id in ( " . $str . ") order by created desc "); + $r = dbq("select *, id as item_id from item where id in ( " . $str . ") order by created desc"); } } else { @@ -234,7 +240,7 @@ class Search extends Controller { $items = []; } - if ($format == 'json') { + if ($format === 'json') { $result = []; require_once('include/conversation.php'); foreach ($items as $item) { diff --git a/Zotlabs/Module/Settings.php b/Zotlabs/Module/Settings.php index 79031c98f..624cbb0c1 100644 --- a/Zotlabs/Module/Settings.php +++ b/Zotlabs/Module/Settings.php @@ -1,7 +1,6 @@ <?php namespace Zotlabs\Module; /** @file */ -require_once('include/zot.php'); require_once('include/security.php'); class Settings extends \Zotlabs\Web\Controller { @@ -11,68 +10,68 @@ class Settings extends \Zotlabs\Web\Controller { function init() { if(! local_channel()) return; - + if($_SESSION['delegate']) return; - + \App::$profile_uid = local_channel(); - + // default is channel settings in the absence of other arguments - + if(argc() == 1) { // We are setting these values - don't use the argc(), argv() functions here \App::$argc = 2; \App::$argv[] = 'channel'; - } + } $this->sm = new \Zotlabs\Web\SubModule(); } - - + + function post() { - + if(! local_channel()) return; - + if($_SESSION['delegate']) return; - + // logger('mod_settings: ' . print_r($_REQUEST,true)); - + if(argc() > 1) { if($this->sm->call('post') !== false) { return; } } - + goaway(z_root() . '/settings' ); return; // NOTREACHED } - - - + + + function get() { - + nav_set_selected('Settings'); - + if((! local_channel()) || ($_SESSION['delegate'])) { notice( t('Permission denied.') . EOL ); return login(); } - - + + $channel = \App::get_channel(); if($channel) head_set_icon($channel['xchan_photo_s']); - + $o = $this->sm->call('get'); if($o !== false) return $o; $o = ''; - - } + + } } diff --git a/Zotlabs/Module/Settings/Calendar.php b/Zotlabs/Module/Settings/Calendar.php index ab85eb450..65240c635 100644 --- a/Zotlabs/Module/Settings/Calendar.php +++ b/Zotlabs/Module/Settings/Calendar.php @@ -11,14 +11,14 @@ class Calendar { $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -34,14 +34,14 @@ class Calendar { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Calendar Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 2eed1efc9..840efc162 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -2,6 +2,10 @@ namespace Zotlabs\Module\Settings; +use App; +use Zotlabs\Access\PermissionLimits; +use Zotlabs\Access\PermissionRoles; +use Zotlabs\Daemon\Master; use Zotlabs\Lib\Apps; use Zotlabs\Lib\Libsync; @@ -10,597 +14,279 @@ require_once('include/selectors.php'); class Channel { - function post() { - $channel = \App::get_channel(); - check_form_security_token_redirectOnErr('/settings', 'settings'); - call_hooks('settings_post', $_POST); - - $set_perms = ''; - - $role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : ''); - $oldrole = get_pconfig(local_channel(),'system','permissions_role'); - - // This mapping can be removed after 3.4 release - if($oldrole === 'social_party') { - $oldrole = 'social_federation'; - } - - if(($role != $oldrole) || ($role === 'custom')) { - - if($role === 'custom') { - $hide_presence = (((x($_POST,'hide_presence')) && (intval($_POST['hide_presence']) == 1)) ? 1: 0); - $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0); - $def_group = ((x($_POST,'group-selection')) ? notags(trim($_POST['group-selection'])) : ''); - $r = q("update channel set channel_default_group = '%s' where channel_id = %d", - dbesc($def_group), - intval(local_channel()) - ); - - $global_perms = \Zotlabs\Access\Permissions::Perms(); - - foreach($global_perms as $k => $v) { - \Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,intval($_POST[$k])); - } - $acl = new \Zotlabs\Access\AccessList($channel); - $acl->set_from_array($_POST); - $x = $acl->get(); - - $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s', - channel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d", - dbesc($x['allow_cid']), - dbesc($x['allow_gid']), - dbesc($x['deny_cid']), - dbesc($x['deny_gid']), - intval(local_channel()) - ); - } - else { - $role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($_POST['permissions_role']); - if(! $role_permissions) { - notice('Permissions category could not be found.'); - return; - } - $hide_presence = 1 - (intval($role_permissions['online'])); - if($role_permissions['default_collection']) { - $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1", - intval(local_channel()), - dbesc( t('Friends') ) - ); - if(! $r) { - require_once('include/group.php'); - group_add(local_channel(), t('Friends')); - group_add_member(local_channel(),t('Friends'),$channel['channel_hash']); - $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1", - intval(local_channel()), - dbesc( t('Friends') ) - ); - } - if($r) { - q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d", - dbesc($r[0]['hash']), - dbesc('<' . $r[0]['hash'] . '>'), - intval(local_channel()) - ); - } - else { - notice( sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL); - return; - } - } - // no default collection - else { - q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '', - channel_deny_cid = '' where channel_id = %d", - intval(local_channel()) - ); - } - if($role_permissions['perms_connect']) { - $x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']); - foreach($x as $k => $v) { - set_abconfig(local_channel(),$channel['channel_hash'],'my_perms',$k, $v); - if($role_permissions['perms_auto']) { - set_pconfig(local_channel(),'autoperms',$k,$v); - } - else { - del_pconfig(local_channel(),'autoperms',$k); - } - } - } - - if($role_permissions['limits']) { - foreach($role_permissions['limits'] as $k => $v) { - \Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,$v); - } - } - if(array_key_exists('directory_publish',$role_permissions)) { - $publish = intval($role_permissions['directory_publish']); - } - } - - set_pconfig(local_channel(),'system','hide_online_status',$hide_presence); - set_pconfig(local_channel(),'system','permissions_role',$role); - } - - $username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : ''); - $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : ''); - $defloc = ((x($_POST,'defloc')) ? notags(trim($_POST['defloc'])) : ''); - $openid = ((x($_POST,'openid_url')) ? notags(trim($_POST['openid_url'])) : ''); - $maxreq = ((x($_POST,'maxreq')) ? intval($_POST['maxreq']) : 0); - $expire = ((x($_POST,'expire')) ? intval($_POST['expire']) : 0); - $evdays = ((x($_POST,'evdays')) ? intval($_POST['evdays']) : 3); - $photo_path = ((x($_POST,'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : ''); - $attach_path = ((x($_POST,'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : ''); - - $expire_items = ((x($_POST,'expire_items')) ? intval($_POST['expire_items']) : 0); - $expire_starred = ((x($_POST,'expire_starred')) ? intval($_POST['expire_starred']) : 0); - $expire_photos = ((x($_POST,'expire_photos'))? intval($_POST['expire_photos']) : 0); - $expire_network_only = ((x($_POST,'expire_network_only'))? intval($_POST['expire_network_only']) : 0); - - $allow_location = (((x($_POST,'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1: 0); - - $blocktags = (((x($_POST,'blocktags')) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted! - $unkmail = (((x($_POST,'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0); - $cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0); - $suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0); - $autoperms = ((x($_POST,'autoperms')) ? intval($_POST['autoperms']) : 0); - - $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0); - $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0); - $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0); - $adult = (($_POST['adult'] == 1) ? 1 : 0); - $defpermcat = ((x($_POST,'defpermcat')) ? notags(trim($_POST['defpermcat'])) : 'default'); - - $mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : ''); - - $pageflags = $channel['channel_pageflags']; - $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0); - if($adult != $existing_adult) + $channel = App::get_channel(); + $role = ((x($_POST, 'permissions_role')) ? notags(trim($_POST['permissions_role'])) : ''); + $timezone = ((x($_POST, 'timezone_select')) ? notags(trim($_POST['timezone_select'])) : ''); + $defloc = ((x($_POST, 'defloc')) ? notags(trim($_POST['defloc'])) : ''); + $evdays = ((x($_POST, 'evdays')) ? intval($_POST['evdays']) : 3); + $photo_path = ((x($_POST, 'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : ''); + $attach_path = ((x($_POST, 'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : ''); + $allow_location = (((x($_POST, 'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1 : 0); + $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1 : 0); + $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1 : 0); + $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1 : 0); + $adult = (($_POST['adult'] == 1) ? 1 : 0); + $mailhost = ((array_key_exists('mailhost', $_POST)) ? notags(trim($_POST['mailhost'])) : ''); + $pageflags = $channel['channel_pageflags']; + $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0); + $expire = ((x($_POST, 'expire')) ? intval($_POST['expire']) : 0); + $incl = ((x($_POST['message_filter_incl'])) ? htmlspecialchars_decode(trim($_POST['message_filter_incl']), ENT_QUOTES) : ''); + $excl = ((x($_POST['message_filter_excl'])) ? htmlspecialchars_decode(trim($_POST['message_filter_excl']), ENT_QUOTES) : ''); + + if ($adult != $existing_adult) { $pageflags = ($pageflags ^ PAGE_ADULT); - - + } + $notify = 0; - - if(x($_POST,'notify1')) + if (x($_POST, 'notify1')) $notify += intval($_POST['notify1']); - if(x($_POST,'notify2')) + if (x($_POST, 'notify2')) $notify += intval($_POST['notify2']); - if(x($_POST,'notify3')) + if (x($_POST, 'notify3')) $notify += intval($_POST['notify3']); - if(x($_POST,'notify4')) + if (x($_POST, 'notify4')) $notify += intval($_POST['notify4']); - if(x($_POST,'notify5')) + if (x($_POST, 'notify5')) $notify += intval($_POST['notify5']); - if(x($_POST,'notify6')) + if (x($_POST, 'notify6')) $notify += intval($_POST['notify6']); - if(x($_POST,'notify7')) + if (x($_POST, 'notify7')) $notify += intval($_POST['notify7']); - if(x($_POST,'notify8')) + if (x($_POST, 'notify8')) $notify += intval($_POST['notify8']); - - + + $vnotify = 0; - - if(x($_POST,'vnotify1')) + if (x($_POST, 'vnotify1')) $vnotify += intval($_POST['vnotify1']); - if(x($_POST,'vnotify2')) + if (x($_POST, 'vnotify2')) $vnotify += intval($_POST['vnotify2']); - if(x($_POST,'vnotify3')) + if (x($_POST, 'vnotify3')) $vnotify += intval($_POST['vnotify3']); - if(x($_POST,'vnotify4')) + if (x($_POST, 'vnotify4')) $vnotify += intval($_POST['vnotify4']); - if(x($_POST,'vnotify5')) + if (x($_POST, 'vnotify5')) $vnotify += intval($_POST['vnotify5']); - if(x($_POST,'vnotify6')) + if (x($_POST, 'vnotify6')) $vnotify += intval($_POST['vnotify6']); - if(x($_POST,'vnotify7')) + if (x($_POST, 'vnotify7')) $vnotify += intval($_POST['vnotify7']); - if(x($_POST,'vnotify8')) + if (x($_POST, 'vnotify8')) $vnotify += intval($_POST['vnotify8']); - if(x($_POST,'vnotify9')) + if (x($_POST, 'vnotify9')) $vnotify += intval($_POST['vnotify9']); - if(x($_POST,'vnotify10')) + if (x($_POST, 'vnotify10')) $vnotify += intval($_POST['vnotify10']); - if(x($_POST,'vnotify11') && is_site_admin()) + if (x($_POST, 'vnotify11') && is_site_admin()) $vnotify += intval($_POST['vnotify11']); - if(x($_POST,'vnotify12')) + if (x($_POST, 'vnotify12')) $vnotify += intval($_POST['vnotify12']); - if(x($_POST,'vnotify13')) + if (x($_POST, 'vnotify13')) $vnotify += intval($_POST['vnotify13']); - if(x($_POST,'vnotify14')) + if (x($_POST, 'vnotify14')) $vnotify += intval($_POST['vnotify14']); - if(x($_POST,'vnotify15')) + if (x($_POST, 'vnotify15')) $vnotify += intval($_POST['vnotify15']); - - $always_show_in_notices = x($_POST,'always_show_in_notices') ? 1 : 0; - - $err = ''; - - $name_change = false; - - if($username != $channel['channel_name']) { - $name_change = true; - require_once('include/channel.php'); - $err = validate_channelname($username); - if($err) { - notice($err); - return; - } - } - - if($timezone != $channel['channel_timezone']) { - if(strlen($timezone)) + + $always_show_in_notices = ((x($_POST, 'always_show_in_notices')) ? 1 : 0); + $update_notices_per_parent = ((x($_POST, 'update_notices_per_parent')) ? 1 : 0); + + if ($timezone !== $channel['channel_timezone']) { + if (strlen($timezone)) date_default_timezone_set($timezone); } - - set_pconfig(local_channel(),'system','use_browser_location',$allow_location); - set_pconfig(local_channel(),'system','suggestme', $suggestme); - set_pconfig(local_channel(),'system','post_newfriend', $post_newfriend); - set_pconfig(local_channel(),'system','post_joingroup', $post_joingroup); - set_pconfig(local_channel(),'system','post_profilechange', $post_profilechange); - set_pconfig(local_channel(),'system','blocktags',$blocktags); - set_pconfig(local_channel(),'system','vnotify',$vnotify); - set_pconfig(local_channel(),'system','always_show_in_notices',$always_show_in_notices); - set_pconfig(local_channel(),'system','evdays',$evdays); - set_pconfig(local_channel(),'system','photo_path',$photo_path); - set_pconfig(local_channel(),'system','attach_path',$attach_path); - set_pconfig(local_channel(),'system','default_permcat',$defpermcat); - set_pconfig(local_channel(),'system','email_notify_host',$mailhost); - set_pconfig(local_channel(),'system','autoperms',$autoperms); - - $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d", - dbesc($username), + + if (!$role) { + notice(t('Please select a channel role') . EOL); + return; + } + + if ($role !== get_pconfig(local_channel(), 'system', 'permissions_role')) { + $role_permissions = PermissionRoles::role_perms($_POST['permissions_role']); + + if (isset($role_permissions['limits'])) { + foreach ($role_permissions['limits'] as $k => $v) { + PermissionLimits::Set(local_channel(), $k, $v); + } + } + + set_pconfig(local_channel(), 'system', 'group_actor', 0); + if (isset($role_permissions['channel_type']) && $role_permissions['channel_type'] === 'group') { + set_pconfig(local_channel(), 'system', 'group_actor', 1); + } + } + + set_pconfig(local_channel(), 'system', 'permissions_role', $role); + set_pconfig(local_channel(), 'system', 'use_browser_location', $allow_location); + set_pconfig(local_channel(), 'system', 'post_newfriend', $post_newfriend); + set_pconfig(local_channel(), 'system', 'post_joingroup', $post_joingroup); + set_pconfig(local_channel(), 'system', 'post_profilechange', $post_profilechange); + set_pconfig(local_channel(), 'system', 'vnotify', $vnotify); + set_pconfig(local_channel(), 'system', 'always_show_in_notices', $always_show_in_notices); + set_pconfig(local_channel(), 'system', 'update_notices_per_parent', $update_notices_per_parent); + set_pconfig(local_channel(), 'system', 'evdays', $evdays); + set_pconfig(local_channel(), 'system', 'photo_path', $photo_path); + set_pconfig(local_channel(), 'system', 'attach_path', $attach_path); + set_pconfig(local_channel(), 'system', 'email_notify_host', $mailhost); + set_pconfig(local_channel(), 'system', 'message_filter_incl', $incl); + set_pconfig(local_channel(), 'system', 'message_filter_excl', $excl); + + $r = q("update channel set channel_pageflags = %d, channel_timezone = '%s', + channel_location = '%s', channel_notifyflags = %d, channel_expire_days = %d + where channel_id = %d", intval($pageflags), dbesc($timezone), dbesc($defloc), intval($notify), - intval($unkmail), - intval($maxreq), intval($expire), intval(local_channel()) - ); - if($r) - info( t('Settings updated.') . EOL); - - if(! is_null($publish)) { - $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d", - intval($publish), - intval(local_channel()) - ); - } - - if($name_change) { - // change name on all associated xchans by matching the url - $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_url = '%s'", - dbesc($username), - dbesc(datetime_convert()), - dbesc(z_root() . '/channel/' . $channel['channel_address']) - ); - $r = q("update profile set fullname = '%s' where uid = %d and is_default = 1", - dbesc($username), - intval($channel['channel_id']) - ); - } - - \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel())); - + ); + if ($r) + info(t('Settings updated.') . EOL); + + Master::Summon(['Directory', local_channel()]); Libsync::build_sync_packet(); - - - if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) { - + + if ($email_changed && App::$config['system']['register_policy'] == REGISTER_VERIFY) { + // FIXME - set to un-verified, blocked and redirect to logout // Q: Why? Are we verifying people or email addresses? // A: the policy is to verify email addresses } - - goaway(z_root() . '/settings' ); + + goaway(z_root() . '/settings'); return; // NOTREACHED } - + function get() { - - require_once('include/acl_selectors.php'); - require_once('include/permissions.php'); + load_pconfig(local_channel()); - $yes_no = array(t('No'),t('Yes')); - - - $p = q("SELECT * FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1", - intval(local_channel()) - ); - if(count($p)) - $profile = $p[0]; - - load_pconfig(local_channel(),'expire'); - - $channel = \App::get_channel(); - - $global_perms = \Zotlabs\Access\Permissions::Perms(); - - $permiss = array(); - - $perm_opts = array( - array( t('Nobody except yourself'), 0), - array( t('Only those you specifically allow'), PERMS_SPECIFIC), - array( t('Approved connections'), PERMS_CONTACTS), - array( t('Any connections'), PERMS_PENDING), - array( t('Anybody on this website'), PERMS_SITE), - array( t('Anybody in this network'), PERMS_NETWORK), - array( t('Anybody authenticated'), PERMS_AUTHED), - array( t('Anybody on the internet'), PERMS_PUBLIC) - ); - - $limits = \Zotlabs\Access\PermissionLimits::Get(local_channel()); - $anon_comments = get_config('system','anonymous_comments',true); - - foreach($global_perms as $k => $perm) { - $options = array(); - $can_be_public = ((strstr($k,'view') || ($k === 'post_comments' && $anon_comments)) ? true : false); - foreach($perm_opts as $opt) { - if($opt[1] == PERMS_PUBLIC && (! $can_be_public)) - continue; - $options[$opt[1]] = $opt[0]; - } - $permiss[] = array($k,$perm,$limits[$k],'',$options); - } - - // logger('permiss: ' . print_r($permiss,true)); - - $username = $channel['channel_name']; - $nickname = $channel['channel_address']; - $timezone = $channel['channel_timezone']; - $notify = $channel['channel_notifyflags']; - $defloc = $channel['channel_location']; - - $maxreq = $channel['channel_max_friend_req']; - $expire = $channel['channel_expire_days']; - $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT); - $sys_expire = get_config('system','default_expire_days'); - -// $unkmail = \App::$user['unkmail']; -// $cntunkmail = \App::$user['cntunkmail']; - - $hide_presence = intval(get_pconfig(local_channel(), 'system','hide_online_status')); - - - $expire_items = get_pconfig(local_channel(), 'expire','items'); - $expire_items = (($expire_items===false)? '1' : $expire_items); // default if not set: 1 - - $expire_notes = get_pconfig(local_channel(), 'expire','notes'); - $expire_notes = (($expire_notes===false)? '1' : $expire_notes); // default if not set: 1 - - $expire_starred = get_pconfig(local_channel(), 'expire','starred'); - $expire_starred = (($expire_starred===false)? '1' : $expire_starred); // default if not set: 1 - - $expire_photos = get_pconfig(local_channel(), 'expire','photos'); - $expire_photos = (($expire_photos===false)? '0' : $expire_photos); // default if not set: 0 - - $expire_network_only = get_pconfig(local_channel(), 'expire','network_only'); - $expire_network_only = (($expire_network_only===false)? '0' : $expire_network_only); // default if not set: 0 - - - $suggestme = get_pconfig(local_channel(), 'system','suggestme'); - $suggestme = (($suggestme===false)? '0': $suggestme); // default if not set: 0 - - $post_newfriend = get_pconfig(local_channel(), 'system','post_newfriend'); - $post_newfriend = (($post_newfriend===false)? '0': $post_newfriend); // default if not set: 0 - - $post_joingroup = get_pconfig(local_channel(), 'system','post_joingroup'); - $post_joingroup = (($post_joingroup===false)? '0': $post_joingroup); // default if not set: 0 - - $post_profilechange = get_pconfig(local_channel(), 'system','post_profilechange'); - $post_profilechange = (($post_profilechange===false)? '0': $post_profilechange); // default if not set: 0 - - $blocktags = get_pconfig(local_channel(),'system','blocktags'); - $blocktags = (($blocktags===false) ? '0' : $blocktags); - - $timezone = date_default_timezone_get(); - - $opt_tpl = get_markup_template("field_checkbox.tpl"); - if(get_config('system','publish_all')) { - $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />'; - } - else { - $profile_in_dir = replace_macros($opt_tpl,array( - '$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no), - )); - } - - $suggestme = replace_macros($opt_tpl,array( - '$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no), - - )); - - $subdir = ((strlen(\App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : ''); - - $webbie = $nickname . '@' . \App::get_hostname(); - $intl_nickname = unpunify($nickname) . '@' . unpunify(\App::get_hostname()); - - - $tpl_addr = get_markup_template("settings_nick_set.tpl"); - - $prof_addr = replace_macros($tpl_addr,array( - '$desc' => t('Your channel address is'), + $channel = App::get_channel(); + $nickname = $channel['channel_address']; + $timezone = $channel['channel_timezone']; + $notify = $channel['channel_notifyflags']; + $defloc = $channel['channel_location']; + $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT); + $post_newfriend = get_pconfig(local_channel(), 'system', 'post_newfriend'); + $post_newfriend = (($post_newfriend === false) ? '0' : $post_newfriend); // default if not set: 0 + $post_joingroup = get_pconfig(local_channel(), 'system', 'post_joingroup'); + $post_joingroup = (($post_joingroup === false) ? '0' : $post_joingroup); // default if not set: 0 + $post_profilechange = get_pconfig(local_channel(), 'system', 'post_profilechange'); + $post_profilechange = (($post_profilechange === false) ? '0' : $post_profilechange); // default if not set: 0 + $subdir = ((strlen(App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : ''); + $webbie = $nickname . '@' . App::get_hostname(); + $intl_nickname = unpunify($nickname) . '@' . unpunify(App::get_hostname()); + $disable_discover_tab = intval(get_config('system', 'disable_discover_tab', 1)) == 1; + $site_firehose = intval(get_config('system', 'site_firehose', 0)) == 1; + + $expire = $channel['channel_expire_days']; + $sys_expire = get_config('system', 'default_expire_days'); + + $tpl_addr = get_markup_template("settings_nick_set.tpl"); + $prof_addr = replace_macros($tpl_addr, [ + '$desc' => t('Your channel address is'), '$nickname' => (($intl_nickname === $webbie) ? $webbie : $intl_nickname . ' (' . $webbie . ')'), - '$subdir' => $subdir, - '$davdesc' => t('Your files/photos are accessible via WebDAV at'), - '$davpath' => z_root() . '/dav/' . $nickname, - '$basepath' => \App::get_hostname() - )); + '$subdir' => $subdir, + '$davdesc' => t('Your files/photos are accessible via WebDAV at'), + '$davpath' => z_root() . '/dav/' . $nickname, + '$basepath' => App::get_hostname() + ]); + $evdays = get_pconfig(local_channel(), 'system', 'evdays'); + if (!$evdays) + $evdays = 3; + $always_show_in_notices = get_pconfig(local_channel(), 'system', 'always_show_in_notices'); + $update_notices_per_parent = get_pconfig(local_channel(), 'system', 'update_notices_per_parent', 1); - $pcat = new \Zotlabs\Lib\Permcat(local_channel()); - $pcatlist = $pcat->listing(); - $permcats = []; - if($pcatlist) { - foreach($pcatlist as $pc) { - $permcats[$pc['name']] = $pc['localname']; - } + $vnotify = get_pconfig(local_channel(), 'system', 'vnotify'); + if ($vnotify === false) + $vnotify = (-1); + + $perm_roles = PermissionRoles::channel_roles(); + $permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role'); + + if (!in_array($permissions_role, ['public', 'personal', 'group', 'custom'])) { + notice(t('Please select a channel role') . EOL); + array_unshift($perm_roles , ''); } - $default_permcat = get_pconfig(local_channel(),'system','default_permcat','default'); + $plugin = ['basic' => '', 'notify' => '']; + call_hooks('channel_settings', $plugin); + + $yes_no = [t('No'), t('Yes')]; - $stpl = get_markup_template('settings.tpl'); - - $acl = new \Zotlabs\Access\AccessList($channel); - $perm_defaults = $acl->get(); - - require_once('include/group.php'); - $group_select = mini_group_select(local_channel(),$channel['channel_default_group']); - - $evdays = get_pconfig(local_channel(),'system','evdays'); - if(! $evdays) - $evdays = 3; - - $permissions_role = get_pconfig(local_channel(),'system','permissions_role'); - if(! $permissions_role) - $permissions_role = 'custom'; - // compatibility mapping - can be removed after 3.4 release - if($permissions_role === 'social_party') - $permissions_role = 'social_federation'; - - if(in_array($permissions_role,['forum','repository'])) - $autoperms = replace_macros(get_markup_template('field_checkbox.tpl'), [ - '$field' => [ 'autoperms',t('Automatic membership approval'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no ]]); - else - $autoperms = '<input type="hidden" name="autoperms" value="' . intval(get_pconfig(local_channel(),'system','autoperms')) . '" />'; - - $permissions_set = (($permissions_role != 'custom') ? true : false); - - $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); - - $vnotify = get_pconfig(local_channel(),'system','vnotify'); - $always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices'); - if($vnotify === false) - $vnotify = (-1); + $o = replace_macros($stpl, [ + '$ptitle' => t('Channel Settings'), + '$submit' => t('Submit'), + '$baseurl' => z_root(), + '$uid' => local_channel(), + '$form_security_token' => get_form_security_token("settings"), + '$role' => ['permissions_role', t('Channel role'), $permissions_role, '', $perm_roles], + '$nickname_block' => $prof_addr, + '$h_basic' => t('Basic Settings'), + '$timezone' => ['timezone_select', t('Channel timezone:'), $timezone, '', get_timezones()], + '$defloc' => ['defloc', t('Default post location:'), $defloc, t('Geographical location to display on your posts')], + '$allowloc' => ['allow_location', t('Use browser location'), ((get_pconfig(local_channel(), 'system', 'use_browser_location')) ? 1 : ''), '', $yes_no], + '$adult' => ['adult', t('Adult content'), $adult_flag, t('This channel frequently or regularly publishes adult content'), $yes_no], + '$maxreq' => ['maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']), t('May reduce spam activity')], + '$h_not' => t('Notification Settings'), + '$activity_options' => t('By default post a status message when:'), + '$post_newfriend' => ['post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no], + '$post_joingroup' => ['post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no], + '$post_profilechange' => ['post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no], + '$lbl_not' => t('Send a notification email when:'), + '$notify1' => ['notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no], + '$notify2' => ['notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no], + '$notify3' => ['notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no], + '$notify4' => ['notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no], + '$notify5' => ['notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no], + '$notify6' => ['notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no], + '$notify7' => ['notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no], + '$notify8' => ['notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no], + '$notify9' => ['notify9', t('Someone likes your post/comment'), ($notify & NOTIFY_LIKE), NOTIFY_LIKE, '', $yes_no], + '$lbl_vnot' => t('Show visual notifications including:'), + '$vnotify1' => ['vnotify1', t('Unseen stream activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no], + '$vnotify2' => ['vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no], + '$vnotify3' => ['vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no], + '$vnotify4' => ['vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no], + '$vnotify5' => ['vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no], + '$vnotify6' => ['vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no], + '$vnotify7' => ['vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no], + '$vnotify8' => ['vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no], + '$vnotify9' => ['vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no], + '$vnotify10' => ['vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no], + '$vnotify11' => ((is_site_admin()) ? ['vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no] : []), + '$vnotify12' => ['vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no], + '$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? [] : ['vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no]), + '$vnotify14' => ['vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no], + '$vnotify15' => ['vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no], + '$mailhost' => ['mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(), 'system', 'email_notify_host', App::get_hostname()), sprintf(t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'), App::get_hostname())], + '$always_show_in_notices' => ['always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no], + '$update_notices_per_parent' => ['update_notices_per_parent', t('Mark all notices of the thread read if a notice is clicked'), $update_notices_per_parent, 1, t('If no, only the clicked notice will be marked read'), $yes_no], + '$desktop_notifications_info' => t('Desktop notifications are unavailable because the required browser permission has not been granted'), + '$desktop_notifications_request' => t('Grant permission'), + '$evdays' => ['evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')], + '$basic_addon' => $plugin['basic'], + '$notify_addon' => $plugin['notify'], + '$photo_path' => ['photo_path', t('Default photo upload folder'), get_pconfig(local_channel(), 'system', 'photo_path'), t('%Y - current year, %m - current month')], + '$attach_path' => ['attach_path', t('Default file upload folder'), get_pconfig(local_channel(), 'system', 'attach_path'), t('%Y - current year, %m - current month')], + '$removeme' => t('Remove Channel'), + '$removechannel' => t('Remove this channel.'), + '$expire' => ['expire', t('Expire other channel content after this many days'), $expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf(t('This website expires after %d days.'), intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')], + '$message_filter_excl' => ['message_filter_excl', t('Do not import posts with this text'), get_pconfig(local_channel(), 'system', 'message_filter_excl', ''), t('Words one per line or #tags, $categories, /patterns/, lang=xx, lang!=xx - leave blank to import all posts')], + '$message_filter_incl' => ['message_filter_incl', t('Only import posts with this text'), get_pconfig(local_channel(), 'system', 'message_filter_incl', ''), t('Words one per line or #tags, $categories, /patterns/, lang=xx, lang!=xx - leave blank to import all posts')] + ]); + + call_hooks('settings_form', $o); - $plugin = [ 'basic' => '', 'security' => '', 'notify' => '' ]; - call_hooks('channel_settings',$plugin); - - $disable_discover_tab = intval(get_config('system','disable_discover_tab',1)) == 1; - $site_firehose = intval(get_config('system','site_firehose',0)) == 1; - - - $o .= replace_macros($stpl,array( - '$ptitle' => t('Channel Settings'), - - '$submit' => t('Submit'), - '$baseurl' => z_root(), - '$uid' => local_channel(), - '$form_security_token' => get_form_security_token("settings"), - '$nickname_block' => $prof_addr, - '$h_basic' => t('Basic Settings'), - '$username' => array('username', t('Full Name:'), $username,''), - '$email' => array('email', t('Email Address:'), $email, ''), - '$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()), - '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')), - '$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no), - - '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no), - - '$h_prv' => t('Security and Privacy Settings'), - '$permissions_set' => $permissions_set, - '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'), - - '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no), - - '$lbl_pmacro' => t('Simple Privacy Settings:'), - '$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'), - '$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'), - '$pmacro1' => t('Private - <em>default private, never open or public</em>'), - '$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'), - '$permiss_arr' => $permiss, - '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no), - - '$lbl_p2macro' => t('Channel Permission Limits'), - - '$expire' => array('expire',t('Expire other channel content after this many days'),$expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf( t('This website expires after %d days.'),intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')), - '$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']) , t('May reduce spam activity')), - '$permissions' => t('Default Privacy Group'), - '$permdesc' => t("\x28click to open/close\x29"), - '$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))), - - '$allow_cid' => acl2json($perm_defaults['allow_cid']), - '$allow_gid' => acl2json($perm_defaults['allow_gid']), - '$deny_cid' => acl2json($perm_defaults['deny_cid']), - '$deny_gid' => acl2json($perm_defaults['deny_gid']), - '$suggestme' => $suggestme, - '$group_select' => $group_select, - '$role' => array('permissions_role' , t('Channel role and privacy'), $permissions_role, '', $perm_roles), - '$defpermcat' => [ 'defpermcat', t('Default permissions category'), $default_permcat, '', $permcats ], - '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'), - '$profile_in_dir' => $profile_in_dir, - '$hide_friends' => $hide_friends, - '$hide_wall' => $hide_wall, - '$unkmail' => $unkmail, - '$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']) ,t("Useful to reduce spamming")), - - '$autoperms' => $autoperms, - '$h_not' => t('Notification Settings'), - '$activity_options' => t('By default post a status message when:'), - '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no), - '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no), - '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no), - '$lbl_not' => t('Send a notification email when:'), - '$notify1' => array('notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no), - '$notify2' => array('notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no), - '$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no), - '$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no), - '$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no), - '$notify6' => array('notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no), - '$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no), - '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no), - - '$notify9' => array('notify9', t('Someone likes your post/comment'), ($notify & NOTIFY_LIKE), NOTIFY_LIKE, '', $yes_no), - - - '$lbl_vnot' => t('Show visual notifications including:'), - - '$vnotify1' => array('vnotify1', t('Unseen stream 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' => ((is_site_admin()) ? array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no) : array()), - '$vnotify12' => array('vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no), - '$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? array() : array('vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no)), - '$vnotify14' => array('vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no), - '$vnotify15' => array('vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no), - '$mailhost' => [ 'mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(),'system','email_notify_host',\App::get_hostname()), sprintf( t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'),\App::get_hostname()) ], - '$always_show_in_notices' => array('always_show_in_notices', t('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')), - '$basic_addon' => $plugin['basic'], - '$sec_addon' => $plugin['security'], - '$notify_addon' => $plugin['notify'], - - '$h_advn' => t('Advanced Account/Page Type Settings'), - '$h_descadvn' => t('Change the behaviour of this account for special situations'), - '$pagetype' => $pagetype, - '$lbl_misc' => t('Miscellaneous Settings'), - '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')), - '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')), - '$removeme' => t('Remove Channel'), - '$removechannel' => t('Remove this channel.'), - )); - - call_hooks('settings_form',$o); - - //$o .= '</form>' . "\r\n"; - return $o; } } diff --git a/Zotlabs/Module/Settings/Channel_home.php b/Zotlabs/Module/Settings/Channel_home.php index e8faa7fb2..470dbe4c3 100644 --- a/Zotlabs/Module/Settings/Channel_home.php +++ b/Zotlabs/Module/Settings/Channel_home.php @@ -13,7 +13,7 @@ class Channel_home { $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); @@ -25,10 +25,10 @@ class Channel_home { $channel_menu = ((x($_POST['channel_menu'])) ? htmlspecialchars_decode(trim($_POST['channel_menu']),ENT_QUOTES) : ''); set_pconfig(local_channel(),'system','channel_menu',$channel_menu); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -82,7 +82,7 @@ class Channel_home { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Channel Home Settings'), @@ -90,7 +90,7 @@ class Channel_home { '$extra_settings_html' => $extra_settings_html, '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Connections.php b/Zotlabs/Module/Settings/Connections.php index 4369deb27..52a95a3d1 100644 --- a/Zotlabs/Module/Settings/Connections.php +++ b/Zotlabs/Module/Settings/Connections.php @@ -11,14 +11,14 @@ class Connections { $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -34,14 +34,14 @@ class Connections { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Connections Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Directory.php b/Zotlabs/Module/Settings/Directory.php index d1dd0677e..09ea61f60 100644 --- a/Zotlabs/Module/Settings/Directory.php +++ b/Zotlabs/Module/Settings/Directory.php @@ -11,14 +11,14 @@ class Directory { $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -34,14 +34,14 @@ class Directory { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Directory Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php index cade0a529..11181907b 100644 --- a/Zotlabs/Module/Settings/Display.php +++ b/Zotlabs/Module/Settings/Display.php @@ -24,7 +24,6 @@ class Display { $preload_images = ((x($_POST,'preload_images')) ? intval($_POST['preload_images']) : 0); - $channel_menu = ((x($_POST,'channel_menu')) ? intval($_POST['channel_menu']) : 0); $user_scalable = ((x($_POST,'user_scalable')) ? intval($_POST['user_scalable']) : 0); $nosmile = ((x($_POST,'nosmile')) ? intval($_POST['nosmile']) : 0); $title_tosource = ((x($_POST,'title_tosource')) ? intval($_POST['title_tosource']) : 0); @@ -46,7 +45,6 @@ class Display { set_pconfig(local_channel(),'system','itemspage', $itemspage); set_pconfig(local_channel(),'system','no_smilies',1-intval($nosmile)); set_pconfig(local_channel(),'system','title_tosource',$title_tosource); - set_pconfig(local_channel(),'system','channel_menu', $channel_menu); set_pconfig(local_channel(),'system','start_menu', $start_menu); $newschema = ''; @@ -197,7 +195,6 @@ class Display { '$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 30 items')), '$nosmile' => array('nosmile', t("Show emoticons (smilies) as images"), 1-intval($nosmile), '', $yes_no), - '$channel_menu' => [ 'channel_menu', t('Provide channel menu in navigation bar'), get_pconfig(local_channel(),'system','channel_menu',get_config('system','channel_menu',0)), t('Default: channel menu located in app menu'),$yes_no ], '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no), '$theme_config' => $theme_config, '$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no] diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php index cf6dd2807..85c3e69ae 100644 --- a/Zotlabs/Module/Settings/Editor.php +++ b/Zotlabs/Module/Settings/Editor.php @@ -11,14 +11,14 @@ class Editor { $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -34,14 +34,14 @@ class Editor { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Editor Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Events.php b/Zotlabs/Module/Settings/Events.php index ab393c932..0a0e3516c 100644 --- a/Zotlabs/Module/Settings/Events.php +++ b/Zotlabs/Module/Settings/Events.php @@ -11,14 +11,14 @@ class Events { $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -34,14 +34,14 @@ class Events { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Events Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php index cbc494cf8..6fb57eafb 100644 --- a/Zotlabs/Module/Settings/Manage.php +++ b/Zotlabs/Module/Settings/Manage.php @@ -12,14 +12,14 @@ class Manage { $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -35,14 +35,14 @@ class Manage { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Channel Manager Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index 9f5bdb2e5..eae963a25 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -21,10 +21,10 @@ class Network { $network_divmore_height = 50; set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -53,7 +53,7 @@ class Network { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Stream Settings'), @@ -61,7 +61,7 @@ class Network { '$extra_settings_html' => $extra_settings_html, '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Photos.php b/Zotlabs/Module/Settings/Photos.php index 8195d660b..f68c8847b 100644 --- a/Zotlabs/Module/Settings/Photos.php +++ b/Zotlabs/Module/Settings/Photos.php @@ -7,18 +7,18 @@ use Zotlabs\Lib\Libsync; class Photos { function post() { - + $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -34,14 +34,14 @@ class Photos { $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Photos Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Settings/Privacy.php b/Zotlabs/Module/Settings/Privacy.php new file mode 100644 index 000000000..847bb3b8f --- /dev/null +++ b/Zotlabs/Module/Settings/Privacy.php @@ -0,0 +1,127 @@ +<?php + +namespace Zotlabs\Module\Settings; + +use App; +use Zotlabs\Access\PermissionLimits; +use Zotlabs\Access\Permissions; +use Zotlabs\Daemon\Master; +use Zotlabs\Lib\Group; +use Zotlabs\Lib\Libsync; + +class Privacy { + + function post() { + + check_form_security_token_redirectOnErr('/settings/privacy', 'settings'); + call_hooks('settings_post', $_POST); + + $index_opt_out = (((x($_POST, 'index_opt_out')) && (intval($_POST['index_opt_out']) == 1)) ? 1 : 0); + set_pconfig(local_channel(), 'system', 'index_opt_out', $index_opt_out); + + $autoperms = (((x($_POST, 'autoperms')) && (intval($_POST['autoperms']) == 1)) ? 1 : 0); + set_pconfig(local_channel(), 'system', 'autoperms', $autoperms); + + $role = get_pconfig(local_channel(), 'system', 'permissions_role'); + if ($role === 'custom') { + + $global_perms = Permissions::Perms(); + + foreach ($global_perms as $k => $v) { + PermissionLimits::Set(local_channel(), $k, intval($_POST[$k])); + } + + $group_actor = (((x($_POST, 'group_actor')) && (intval($_POST['group_actor']) == 1)) ? 1 : 0); + set_pconfig(local_channel(), 'system', 'group_actor', $group_actor); + + } + + info(t('Privacy settings updated.') . EOL); + Master::Summon(['Directory', local_channel()]); + Libsync::build_sync_packet(); + + goaway(z_root() . '/settings/privacy'); + return; // NOTREACHED + } + + function get() { + + load_pconfig(local_channel()); + + $channel = App::get_channel(); + $global_perms = Permissions::Perms(); + $permiss = []; + + $perm_opts = [ + [t('Only me'), 0], + [t('Only those you specifically allow'), PERMS_SPECIFIC], + [t('Approved connections'), PERMS_CONTACTS], + [t('Any connections'), PERMS_PENDING], + [t('Anybody on this website'), PERMS_SITE], + [t('Anybody in this network'), PERMS_NETWORK], + [t('Anybody authenticated'), PERMS_AUTHED], + [t('Anybody on the internet'), PERMS_PUBLIC] + ]; + + $help = [ + 'view_stream', + 'view_wiki', + 'view_pages', + 'view_storage' + ]; + + $help_txt = t('Advise: set to "Anybody on the internet" and use privacy groups to restrict access'); + $limits = PermissionLimits::Get(local_channel()); + $anon_comments = get_config('system', 'anonymous_comments', true); + + foreach ($global_perms as $k => $perm) { + $options = []; + $can_be_public = (strstr($k, 'view') || ($k === 'post_comments' && $anon_comments)); + + foreach ($perm_opts as $opt) { + if ($opt[1] == PERMS_PUBLIC && (!$can_be_public)) + continue; + + $options[$opt[1]] = $opt[0]; + } + + $permiss[] = [ + $k, + $perm, + $limits[$k], + ((in_array($k, $help)) ? $help_txt : ''), + $options + ]; + } + + //logger('permiss: ' . print_r($permiss,true)); + + $autoperms = get_pconfig(local_channel(), 'system', 'autoperms'); + $index_opt_out = get_pconfig(local_channel(), 'system', 'index_opt_out'); + $group_actor = get_pconfig(local_channel(), 'system', 'group_actor'); + + $permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role', 'custom'); + $permission_limits = ($permissions_role === 'custom'); + + $stpl = get_markup_template('settings_privacy.tpl'); + + $o = replace_macros($stpl, [ + '$ptitle' => t('Privacy Settings'), + '$submit' => t('Submit'), + '$form_security_token' => get_form_security_token("settings"), + '$permission_limits' => $permission_limits, + '$permiss_arr' => $permiss, + '$permission_limits_label' => t('Advanced configuration'), + '$permission_limits_warning' => [ + t('Proceed with caution'), + t('Changing advanced configuration settings can impact your, and your contacts channels functionality and security.'), + t('Accept the risk and continue') + ], + '$autoperms' => ['autoperms', t('Automatically approve new contacts'), $autoperms, '', [t('No'), t('Yes')]], + '$index_opt_out' => ['index_opt_out', t('Opt-out of search engine indexing'), $index_opt_out, '', [t('No'), t('Yes')]], + '$group_actor' => ['group_actor', t('Group actor'), $group_actor, t('Allow this channel to act as a forum'), [t('No'), t('Yes')]] + ]); + + return $o; + } +} diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php index 67b03e04f..0ff2dfb6d 100644 --- a/Zotlabs/Module/Settings/Profiles.php +++ b/Zotlabs/Module/Settings/Profiles.php @@ -13,17 +13,17 @@ class Profiles { $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); $profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : ''); set_pconfig(local_channel(),'system','profile_assign',$profile_assign); - + Libsync::build_sync_packet(); - if($_POST['rpath']) + if(isset($_POST['rpath']) && is_local_url($_POST['rpath'])) goaway($_POST['rpath']); return; @@ -38,12 +38,12 @@ class Profiles { $extra_settings_html = ''; if(feature_enabled(local_channel(),'multi_profiles')) - $extra_settings_html = contact_profile_assign(get_pconfig(local_channel(),'system','profile_assign','')); + $extra_settings_html = contact_profile_assign(get_pconfig(local_channel(),'system','profile_assign',''), t('Default profile for new contacts')); $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( - '$rpath' => $rpath, + '$rpath' => escape_url($rpath), '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Profiles Settings'), @@ -51,7 +51,7 @@ class Profiles { '$extra_settings_html' => $extra_settings_html, '$submit' => t('Submit') )); - + return $o; } diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index ca8c19600..f068cbef8 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -69,17 +69,22 @@ class Setup extends \Zotlabs\Web\Controller { $dbpass = ((isset($_POST['dbpass'])) ? trim($_POST['dbpass']) : ''); $dbdata = ((isset($_POST['dbdata'])) ? trim($_POST['dbdata']) : ''); $dbtype = ((isset($_POST['dbtype'])) ? intval(trim($_POST['dbtype'])) : 0); + $phpath = ((isset($_POST['phpath'])) ? trim($_POST['phpath']) : ''); $adminmail = ((isset($_POST['adminmail'])) ? trim($_POST['adminmail']) : ''); $siteurl = ((isset($_POST['siteurl'])) ? trim($_POST['siteurl']) : ''); + if (empty($db_charset)) { + $db_charset = ((intval($dbtype) === 0) ? 'utf8mb4' : 'UTF8'); + } + // $siteurl should not have a trailing slash $siteurl = rtrim($siteurl,'/'); require_once('include/dba/dba_driver.php'); - $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true); + $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, $db_charset, true); if(! \DBA::$dba->connected) { echo 'Database Connect failed: ' . \DBA::$dba->error; @@ -94,11 +99,16 @@ class Setup extends \Zotlabs\Web\Controller { $dbpass = ((isset($_POST['dbpass'])) ? trim($_POST['dbpass']) : ''); $dbdata = ((isset($_POST['dbdata'])) ? trim($_POST['dbdata']) : ''); $dbtype = ((isset($_POST['dbtype'])) ? intval(trim($_POST['dbtype'])) : 0); + $phpath = ((isset($_POST['phpath'])) ? trim($_POST['phpath']) : ''); $timezone = ((isset($_POST['timezone'])) ? trim($_POST['timezone']) : ''); $adminmail = ((isset($_POST['adminmail'])) ? trim($_POST['adminmail']) : ''); $siteurl = ((isset($_POST['siteurl'])) ? trim($_POST['siteurl']) : ''); + if (empty($db_charset)) { + $db_charset = ((intval($dbtype) === 0) ? 'utf8mb4' : 'UTF8'); + } + if($siteurl != z_root()) { $test = z_fetch_url($siteurl."/setup/testrewrite"); if((! $test['success']) || ($test['body'] != 'ok')) { @@ -112,7 +122,7 @@ class Setup extends \Zotlabs\Web\Controller { if(! isset(\DBA::$dba->connected)) { // connect to db - $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true); + $db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, $db_charset, true); } if(! isset(\DBA::$dba->connected)) { diff --git a/Zotlabs/Module/Sources.php b/Zotlabs/Module/Sources.php index e535f6ebf..ef665e727 100644 --- a/Zotlabs/Module/Sources.php +++ b/Zotlabs/Module/Sources.php @@ -13,7 +13,7 @@ class Sources extends Controller { if(! Apps::system_app_installed(local_channel(), 'Channel Sources')) return; - + $source = intval($_REQUEST['source']); $xchan = escape_tags($_REQUEST['xchan']); $abook = intval($_REQUEST['abook']); @@ -22,21 +22,21 @@ class Sources extends Controller { $frequency = $_REQUEST['frequency']; $name = escape_tags($_REQUEST['name']); $tags = escape_tags($_REQUEST['tags']); - + $channel = \App::get_channel(); - + if($name == '*') $xchan = '*'; - + if($abook) { $r = q("select abook_xchan from abook where abook_id = %d and abook_channel = %d limit 1", intval($abook), intval(local_channel()) ); - if($r) + if($r) $xchan = $r[0]['abook_xchan']; } - + if(! $xchan) { notice ( t('Failed to create source. No channel selected.') . EOL); return; @@ -69,27 +69,25 @@ class Sources extends Controller { if($r) { info( t('Source updated.') . EOL); } - + } } - - + + function get() { if(! local_channel()) { notice( t('Permission denied.') . EOL); return; } - + if(! Apps::system_app_installed(local_channel(), 'Channel Sources')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Sources App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Automatically import channel content from other channels or feeds'); - return $o; + $papp = Apps::get_papp('Channel Sources'); + return Apps::app_render($papp, 'module'); } - + // list sources if(argc() == 1) { $r = q("select source.*, xchan.* from source left join xchan on src_xchan = xchan_hash where src_channel_id = %d", @@ -111,23 +109,23 @@ class Sources extends Controller { )); return $o; } - + if(argc() == 2 && argv(1) === 'new') { // TODO add the words 'or RSS feed' and corresponding code to manage feeds and frequency - + $o = replace_macros(get_markup_template('sources_new.tpl'), array( '$title' => t('New Source'), '$desc' => t('Import all or selected content from the following channel into this channel and distribute it according to your channel settings.'), '$words' => array( 'words', t('Only import content with these words (one per line)'),'',t('Leave blank to import all public content')), '$name' => array( 'name', t('Channel Name'), '', '', '', 'autocomplete="off"'), '$tags' => array('tags', t('Add the following categories to posts imported from this source (comma separated)'),'',t('Optional')), - '$resend' => [ 'resend', t('Resend posts with this channel as author'), 0, t('Copyrights may apply'), [ t('No'), t('Yes') ]], + '$resend' => [ 'resend', t('Resend posts with this channel as author'), 0, t('Copyrights may apply'), [ t('No'), t('Yes') ]], '$submit' => t('Submit') )); return $o; - + } - + if(argc() == 2 && intval(argv(1))) { // edit source $r = q("select source.*, xchan.* from source left join xchan on src_xchan = xchan_hash where src_id = %d and src_channel_id = %d limit 1", @@ -144,9 +142,9 @@ class Sources extends Controller { notice( t('Source not found.') . EOL); return ''; } - + $r[0]['src_patt'] = htmlspecialchars($r[0]['src_patt'], ENT_QUOTES,'UTF-8'); - + $o = replace_macros(get_markup_template('sources_edit.tpl'), array( '$title' => t('Edit Source'), '$drop' => t('Delete Source'), @@ -156,15 +154,15 @@ class Sources extends Controller { '$xchan' => $r[0]['src_xchan'], '$abook' => $x[0]['abook_id'], '$tags' => array('tags', t('Add the following categories to posts imported from this source (comma separated)'),$r[0]['src_tag'],t('Optional')), - '$resend' => [ 'resend', t('Resend posts with this channel as author'), get_abconfig(local_channel(), $r[0]['xchan_hash'],'system','rself'), t('Copyrights may apply'), [ t('No'), t('Yes') ]], + '$resend' => [ 'resend', t('Resend posts with this channel as author'), get_abconfig(local_channel(), $r[0]['xchan_hash'],'system','rself'), t('Copyrights may apply'), [ t('No'), t('Yes') ]], '$name' => array( 'name', t('Channel Name'), $r[0]['xchan_name'], ''), '$submit' => t('Submit') )); return $o; - + } - + if(argc() == 3 && intval(argv(1)) && argv(2) === 'drop') { $r = q("select * from source where src_id = %d and src_channel_id = %d limit 1", intval(argv(1)), @@ -182,12 +180,12 @@ class Sources extends Controller { info( t('Source removed') . EOL); else notice( t('Unable to remove source.') . EOL); - + goaway(z_root() . '/sources'); - + } - + // shouldn't get here. - + } } diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php index 6f3df299f..3dab3d465 100644 --- a/Zotlabs/Module/Sse.php +++ b/Zotlabs/Module/Sse.php @@ -34,6 +34,7 @@ class Sse extends Controller { self::$uid = local_channel(); self::$ob_hash = get_observer_hash(); self::$sse_id = false; + self::$vnotify = -1; if(! self::$ob_hash) { if(session_id()) { @@ -45,7 +46,9 @@ class Sse extends Controller { } } - self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify'); + if (self::$uid) { + self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify'); + } $sleep_seconds = 3; @@ -94,6 +97,14 @@ class Sse extends Controller { $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []); $lock = XConfig::Get(self::$ob_hash, 'sse', 'lock'); + // We do not have the local_channel in the addon. + // Reset pubs here if the app is not installed. + if (self::$uid && (!(self::$vnotify & VNOTIFY_PUBS) || !Apps::system_app_installed(self::$uid, 'Public Stream'))) { + $result['pubs']['count'] = 0; + $result['pubs']['notifications'] = []; + $result['pubs']['offset'] = -1; + } + if($result && !$lock) { echo "event: notifications\n"; echo 'data: ' . json_encode($result); diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php index 109b043ad..3a13b0a6f 100644 --- a/Zotlabs/Module/Sse_bs.php +++ b/Zotlabs/Module/Sse_bs.php @@ -37,7 +37,7 @@ class Sse_bs extends Controller { self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify', -1); self::$evdays = intval(get_pconfig(self::$uid, 'system', 'evdays')); - self::$limit = 50; + self::$limit = 30; self::$offset = 0; self::$xchans = ''; @@ -55,10 +55,13 @@ class Sse_bs extends Controller { self::$xchans = ids_to_querystr($x, 'xchan_hash', true); } - if(intval(argv(2)) > 0) + if(intval(argv(2)) > 0) { self::$offset = argv(2); - else + } + else { $_SESSION['sse_loadtime'] = datetime_convert(); + } + $network = false; $dm = false; @@ -100,7 +103,6 @@ class Sse_bs extends Controller { self::bs_forums(), self::bs_pubs($pubs), self::bs_files(), - self::bs_mail(), self::bs_all_events(), self::bs_register(), self::bs_info_notice() @@ -122,7 +124,7 @@ class Sse_bs extends Controller { $str = ''; foreach($arr as $a) { - $mids[] = '\'' . dbesc(@base64url_decode(substr($a,4))) . '\''; + $mids[] = '\'' . dbesc(unpack_link_id($a)) . '\''; } $str = implode(',', $mids); @@ -371,7 +373,7 @@ class Sse_bs extends Controller { $result['pubs']['notifications'] = []; $result['pubs']['count'] = 0; - if(! (self::$vnotify & VNOTIFY_PUBS)) { + if(! (self::$vnotify & VNOTIFY_PUBS) || !Apps::system_app_installed(self::$uid, 'Public Stream')) { $result['pubs']['offset'] = -1; return $result; } @@ -558,7 +560,7 @@ class Sse_bs extends Controller { $b64mids = []; foreach($mids as $mid) - $b64mids[] = 'b64.' . base64url_encode($mid); + $b64mids[] = gen_link_id($mid); $forums[$x]['notify_link'] = z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id']; $forums[$x]['name'] = $forums[$x]['xchan_name']; @@ -634,36 +636,6 @@ class Sse_bs extends Controller { } - function bs_mail() { - - $result['mail']['notifications'] = []; - $result['mail']['count'] = 0; - $result['mail']['offset'] = -1; - - if(! self::$uid) - return $result; - - if(! (self::$vnotify & VNOTIFY_MAIL)) - return $result; - - $r = q("select mail.*, xchan.* from mail left join xchan on xchan_hash = from_xchan - where channel_id = %d and mail_seen = 0 and mail_deleted = 0 - and from_xchan != '%s' order by created desc", - intval(self::$uid), - dbesc(self::$ob_hash) - ); - - if($r) { - foreach($r as $rr) { - $result['mail']['notifications'][] = Enotify::format_mail($rr); - } - $result['mail']['count'] = count($r); - } - - return $result; - - } - function bs_all_events() { $result['all_events']['notifications'] = []; diff --git a/Zotlabs/Module/Suggest.php b/Zotlabs/Module/Suggest.php index 0ed6ea8d7..22822bb87 100644 --- a/Zotlabs/Module/Suggest.php +++ b/Zotlabs/Module/Suggest.php @@ -36,10 +36,8 @@ class Suggest extends \Zotlabs\Web\Controller { if(! Apps::system_app_installed(local_channel(), 'Suggest Channels')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Suggest Channels App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Suggestions for channels in the $Projectname network you might be interested in'); - return $o; + $papp = Apps::get_papp('Suggest Channels'); + return Apps::app_render($papp, 'module'); } $o = ''; diff --git a/Zotlabs/Module/Tokens.php b/Zotlabs/Module/Tokens.php index 1ba41dcc5..a41003f6b 100644 --- a/Zotlabs/Module/Tokens.php +++ b/Zotlabs/Module/Tokens.php @@ -5,6 +5,11 @@ namespace Zotlabs\Module; use App; use Zotlabs\Web\Controller; use Zotlabs\Lib\Apps; +use Zotlabs\Lib\AccessList; +use Zotlabs\Lib\Permcat; +use Zotlabs\Lib\Libsync; + +require_once('include/security.php'); class Tokens extends Controller { @@ -13,15 +18,65 @@ class Tokens extends Controller { if(! local_channel()) return; - if(! Apps::system_app_installed(local_channel(), 'Guest Access')) - return; - $channel = App::get_channel(); + if(! Apps::system_app_installed($channel['channel_id'], 'Guest Access')) + return; + check_form_security_token_redirectOnErr('tokens', 'tokens'); + + if(isset($_POST['delete'])) { + $r = q("select * from atoken where atoken_id = %d and atoken_uid = %d", + intval($_POST['atoken_id']), + intval(local_channel()) + ); + + if (!$r) { + return; + } + + $atoken = $r[0]; + $atoken_xchan = substr($channel['channel_hash'], 0, 16) . '.' . $atoken['atoken_guid']; + + $atoken['deleted'] = true; + + $r = q("SELECT abook.*, xchan.* + FROM abook left join xchan on abook_xchan = xchan_hash + WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1", + intval($channel['channel_id']), + dbesc($atoken_xchan) + ); + + if (!$r) { + return; + } + + $clone = $r[0]; + + unset($clone['abook_id']); + unset($clone['abook_account']); + unset($clone['abook_channel']); + $clone['deleted'] = true; + + $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); + if ($abconfig) { + $clone['abconfig'] = $abconfig; + } + + atoken_delete($atoken['atoken_id']); + Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ], 'atoken' => [ $atoken ] ], true); + + return; + } + $token_errs = 0; if(array_key_exists('token',$_POST)) { $atoken_id = (($_POST['atoken_id']) ? intval($_POST['atoken_id']) : 0); + + if (! $atoken_id) { + $atoken_guid = new_uuid(); + } + $name = trim(escape_tags($_POST['name'])); $token = trim($_POST['token']); if((! $name) || (! $token)) @@ -30,10 +85,10 @@ class Tokens extends Controller { $expires = datetime_convert(date_default_timezone_get(),'UTC',$_POST['expires']); else $expires = NULL_DATE; - $max_atokens = service_class_fetch(local_channel(),'access_tokens'); + $max_atokens = service_class_fetch($channel['channel_id'],'access_tokens'); if($max_atokens) { $r = q("select count(atoken_id) as total where atoken_uid = %d", - intval(local_channel()) + intval($channel['channel_id']) ); if($r && intval($r[0]['total']) >= $max_tokens) { notice( sprintf( t('This channel is limited to %d tokens'), $max_tokens) . EOL); @@ -45,8 +100,19 @@ class Tokens extends Controller { notice( t('Name and Password are required.') . EOL); return; } + + $old_atok = q("select * from atoken where atoken_uid = %d and atoken_name = '%s'", + intval($channel['channel_id']), + dbesc($name) + ); + + if ($old_atok) { + $old_atok = $old_atok[0]; + $old_xchan = atoken_xchan($old_atok); + } + if($atoken_id) { - $r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s' + $r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s' where atoken_id = %d and atoken_uid = %d", dbesc($name), dbesc($token), @@ -56,8 +122,9 @@ class Tokens extends Controller { ); } else { - $r = q("insert into atoken ( atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires ) - values ( %d, %d, '%s', '%s', '%s' ) ", + $r = q("insert into atoken (atoken_guid, atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires ) + values ('%s', %d, %d, '%s', '%s', '%s' ) ", + dbesc($atoken_guid), intval($channel['channel_account_id']), intval($channel['channel_id']), dbesc($name), @@ -66,26 +133,89 @@ class Tokens extends Controller { ); } - $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $name; + $atok = q("select * from atoken where atoken_uid = %d and atoken_name = '%s'", + intval($channel['channel_id']), + dbesc($name) + ); + + if ($atok) { + $xchan = atoken_xchan($atok[0]); + atoken_create_xchan($xchan); + $atoken_xchan = $xchan['xchan_hash']; + if ($old_atok && $old_xchan) { + $r = q("update xchan set xchan_name = '%s' where xchan_hash = '%s'", + dbesc($xchan['xchan_name']), + dbesc($old_xchan['xchan_hash']) + ); + } + } + - $all_perms = \Zotlabs\Access\Permissions::Perms(); + if (! $atoken_id) { - if($all_perms) { - foreach($all_perms as $perm => $desc) { - if(array_key_exists('perms_' . $perm, $_POST)) { - set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,intval($_POST['perms_' . $perm])); - } - else { - set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,0); + // If this is a new token, create a new abook record + + $closeness = get_pconfig($channel['channel_id'], 'system', 'new_abook_closeness',80); + $profile_assign = get_pconfig($channel['channel_id'], 'system', 'profile_assign', ''); + + $r = abook_store_lowlevel( + [ + 'abook_account' => $channel['channel_account_id'], + 'abook_channel' => $channel['channel_id'], + 'abook_closeness' => intval($closeness), + 'abook_xchan' => $atoken_xchan, + 'abook_profile' => $profile_assign, + 'abook_feed' => 0, + 'abook_created' => datetime_convert(), + 'abook_updated' => datetime_convert(), + 'abook_instance' => z_root(), + ] + ); + + if (! $r) { + logger('abook creation failed'); + } + + /** If there is a default group for this channel, add this connection to it */ + if ($channel['channel_default_group']) { + $g = AccessList::by_hash($channel['channel_id'], $channel['channel_default_group']); + if ($g) { + AccessList::member_add($channel['channel_id'], '', $atoken_xchan,$g['id']); } } } - + + $role = ((array_key_exists('permcat', $_POST)) ? escape_tags($_POST['permcat']) : ''); + \Zotlabs\Lib\Permcat::assign($channel, $role, [$atoken_xchan]); + + $r = q("SELECT abook.*, xchan.* + FROM abook left join xchan on abook_xchan = xchan_hash + WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1", + intval($channel['chnnel_id']), + dbesc($atoken_xchan) + ); + + if (! $r) { + return; + } + + $clone = $r[0]; + + unset($clone['abook_id']); + unset($clone['abook_account']); + unset($clone['abook_channel']); + + $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); + if ($abconfig) { + $clone['abconfig'] = $abconfig; + } + + Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ], 'atoken' => $atok ], true); info( t('Token saved.') . EOL); return; } - + function get() { @@ -95,16 +225,17 @@ class Tokens extends Controller { if(! Apps::system_app_installed(local_channel(), 'Guest Access')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Guest Access App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Create access tokens so that non-members can access private content'); - return $o; + $papp = Apps::get_papp('Guest Access'); + return Apps::app_render($papp, 'module'); } + nav_set_selected('Guest Access'); + $channel = App::get_channel(); $atoken = null; $atoken_xchan = ''; + $atoken_abook = []; if(argc() > 1) { $id = argv(1); @@ -116,78 +247,54 @@ class Tokens extends Controller { if($atoken) { $atoken = $atoken[0]; - $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_name']; - } - - if($atoken && argc() > 2 && argv(2) === 'drop') { - atoken_delete($id); - $atoken = null; - $atoken_xchan = ''; - } - } - - $t = q("select * from atoken where atoken_uid = %d", - intval(local_channel()) - ); - - $desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content.'); - - $desc2 = t('You may also provide <em>dropbox</em> style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:'); + $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_guid']; - $global_perms = \Zotlabs\Access\Permissions::Perms(); - $their_perms = []; - - $existing = get_all_perms(local_channel(),(($atoken_xchan) ? $atoken_xchan : ''),false); + $atoken_abook = q("select * from abook where abook_channel = %d and abook_xchan = '%s'", + intval(local_channel()), + dbesc($atoken_xchan) + ); - if($atoken_xchan) { - $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", - intval(local_channel()), - dbesc($atoken_xchan) - ); - if($theirs) { - foreach($theirs as $t) { - $their_perms[$t['k']] = $t['v']; - } + $atoken_abook = $atoken_abook[0]; } } - foreach($global_perms as $k => $v) { - $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k); -//fixme - $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k); + $desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in privacy groups and visitors may login using these credentials to access private content.'); - if($existing[$k]) - $thisperm = "1"; + $pcat = new Permcat(local_channel()); + $pcatlist = $pcat->listing(); + $default_role = get_pconfig(local_channel(), 'system', 'default_permcat'); + $current_permcat = (($atoken_abook) ? $atoken_abook['abook_role'] : $default_role); - $perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited); + $roles_dict = []; + foreach ($pcatlist as $role) { + $roles_dict[$role['name']] = $role['localname']; } + if (!$current_permcat) { + notice(t('Please select a role for this guest!') . EOL); + $permcats[] = ''; + } + if ($pcatlist) { + foreach ($pcatlist as $pc) { + $permcats[$pc['name']] = $pc['localname']; + } + } $tpl = get_markup_template("tokens.tpl"); $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("tokens"), - '$title' => t('Guest Access Tokens'), - '$desc' => $desc, - '$desc2' => $desc2, - '$tokens' => $t, + '$form_security_token' => get_form_security_token('tokens'), + '$permcat' => ['permcat', t('Select a role for this guest'), $current_permcat, '', $permcats], + '$title' => t('Guest Access'), + '$desc' => $desc, '$atoken' => $atoken, - '$url1' => z_root() . '/channel/' . $channel['channel_address'], - '$url2' => z_root() . '/photos/' . $channel['channel_address'], '$name' => array('name', t('Login Name') . ' <span class="required">*</span>', (($atoken) ? $atoken['atoken_name'] : ''),''), - '$token'=> array('token', t('Login Password') . ' <span class="required">*</span>',(($atoken) ? $atoken['atoken_token'] : autoname(8)), ''), + '$token'=> array('token', t('Login Password') . ' <span class="required">*</span>',(($atoken) ? $atoken['atoken_token'] : new_token()), ''), '$expires'=> array('expires', t('Expires (yyyy-mm-dd)'), (($atoken['atoken_expires'] && $atoken['atoken_expires'] > NULL_DATE) ? datetime_convert('UTC',date_default_timezone_get(),$atoken['atoken_expires']) : ''), ''), - '$them' => t('Their Settings'), - '$me' => t('My Settings'), - '$perms' => $perms, - '$inherited' => t('inherited'), - '$notself' => 1, - '$self' => 0, - '$permlbl' => t('Individual Permissions'), - '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'), - '$submit' => t('Submit') + '$submit' => t('Submit'), + '$delete' => t('Delete') )); return $o; } - + } diff --git a/Zotlabs/Module/Uexport.php b/Zotlabs/Module/Uexport.php index 55c316317..870c42802 100644 --- a/Zotlabs/Module/Uexport.php +++ b/Zotlabs/Module/Uexport.php @@ -2,89 +2,199 @@ namespace Zotlabs\Module; use App; +use ZipArchive; use Zotlabs\Lib\Apps; use Zotlabs\Web\Controller; class Uexport extends Controller { function init() { - if(! local_channel()) - killme(); + if(! local_channel()) { + return; + } - if(! Apps::system_app_installed(local_channel(), 'Channel Export')) + if(! Apps::system_app_installed(local_channel(), 'Channel Export')) { return; + } if(argc() > 1) { - $sections = (($_REQUEST['sections']) ? explode(',',$_REQUEST['sections']) : ''); $zap_compat = (($_REQUEST['zap_compat']) ? intval($_REQUEST['zap_compat']) : false); - $channel = App::get_channel(); + $year = null; + $month = null; if(argc() > 1 && intval(argv(1)) > 1900) { $year = intval(argv(1)); } - + if(argc() > 2 && intval(argv(2)) > 0 && intval(argv(2)) <= 12) { $month = intval(argv(2)); } - - header('content-type: application/json'); - header('content-disposition: attachment; filename="' . $channel['channel_address'] . (($year) ? '-' . $year : '') . (($month) ? '-' . $month : '') . (($_REQUEST['sections']) ? '-' . $_REQUEST['sections'] : '') . '.json"' ); - - if($year) { - echo json_encode(identity_export_year(local_channel(),$year,$month, $zap_compat)); + + $sections = []; + $section = ''; + if(argc() > 1 && ctype_lower(argv(1))) { + $section = argv(1); + } + + switch ($section) { + case 'channel': + $sections = get_default_export_sections(); + break; + case 'chatrooms': + $sections = ['chatrooms']; + break; + case 'events': + $sections = ['events']; + break; + case 'webpages': + $sections = ['webpages']; + break; + case 'wikis': + $sections = ['wikis']; + break; + case 'custom': + default: + $custom_sections = ['channel', 'connections', 'config', 'apps', 'chatrooms', 'events', 'webpages', 'wikis']; + $raw_sections = (($_REQUEST['sections']) ? explode(',', $_REQUEST['sections']) : ''); + if ($raw_sections) { + foreach ($raw_sections as $raw_section) { + if(in_array($raw_section, $custom_sections)) { + $sections[] = $raw_section; + } + } + } + } + + if ($sections) { + + $export = json_encode(identity_basic_export(local_channel(), $sections, $zap_compat)); + + header('Content-Type: application/json'); + header('Content-Disposition: attachment; filename="' . $channel['channel_address'] . '-' . implode('-', $sections) . '.json"'); + header('Content-Length: ' . strlen($export)); + + echo $export; + + killme(); + } + elseif ($year && !$month) { + $zip_dir = 'store/[data]/' . $channel['channel_address'] . '/tmp'; + if (!is_dir($zip_dir)) + mkdir($zip_dir, STORAGE_DEFAULT_PERMISSIONS, true); + + $zip_file = $channel['channel_address'] . '-' . $year . '.zip'; + $zip_path = $zip_dir . '/' . $zip_file; + $zip_content_available = false; + $zip = new ZipArchive(); + + if ($zip->open($zip_path, ZipArchive::CREATE) === true) { + $month = 1; + while ($month <= 12) { + $name = $channel['channel_address'] . '-' . $year . '-' . $month . '.json'; + $content = conv_item_export_year(local_channel(), $year, $month, $zap_compat); + if(isset($content['item'])) { + $zip_content_available = true; + $zip->addFromString($name, json_encode($content)); + } + $month++; + } + $zip->setCompressionName($zip_path, ZipArchive::CM_STORE); + $zip->close(); + } + if (!$zip_content_available) { + unlink($zip_path); + notice(t('No content available for year') . ' ' . $year . EOL); + goaway('/uexport'); + } + + header('Content-Type: application/zip'); + header('Content-Disposition: attachment; filename="' . $zip_file . '"'); + header('Content-Length: ' . filesize($zip_path)); + + $istream = fopen($zip_path, 'rb'); + $ostream = fopen('php://output', 'wb'); + if ($istream && $ostream) { + pipe_streams($istream, $ostream); + fclose($istream); + fclose($ostream); + } + + unlink($zip_path); killme(); } - - if(argc() > 1 && argv(1) === 'basic') { - echo json_encode(identity_basic_export(local_channel(),$sections, $zap_compat)); + elseif ($year && $month) { + $export = json_encode(conv_item_export_year(local_channel(), $year, $month, $zap_compat)); + + header('Content-Type: application/json'); + header('Content-Disposition: attachment; filename="' . $channel['channel_address'] . '-' . $year . '-' . $month . '.json"'); + header('Content-Length: ' . strlen($export)); + + echo $export; + killme(); } - - // Warning: this option may consume a lot of memory - - if(argc() > 1 && argv(1) === 'complete') { - $sections = get_default_export_sections(); - $sections[] = 'items'; - echo json_encode(identity_basic_export(local_channel(),$sections, $zap_compat)); + else { killme(); } } } - + function get() { + if(! local_channel()) { + return; + } + if(! Apps::system_app_installed(local_channel(), 'Channel Export')) { //Do not display any associated widgets at this point App::$pdl = ''; + $papp = Apps::get_papp('Channel Export'); + return Apps::app_render($papp, 'module'); + } + + $account = App::get_account(); + $year_start = datetime_convert('UTC', date_default_timezone_get(), $account['account_created'], 'Y'); + $year_end = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y'); + $years = []; - $o = '<b>' . t('Channel Export App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Export your channel'); - return $o; + while ($year_start <= $year_end) { + $years[] = $year_start; + $year_start++; } - - $y = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); - - $yearurl = z_root() . '/uexport/' . $y; - $janurl = z_root() . '/uexport/' . $y . '/1'; - $impurl = '/import_items'; + + $item_import_url = '/import_items'; + $channel_import_url = '/import'; + $o = replace_macros(get_markup_template('uexport.tpl'), array( '$title' => t('Export Channel'), - '$basictitle' => t('Export Channel'), - '$basic' => t('Export your basic channel information to a file. This acts as a backup of your connections, permissions, profile and basic data, which can be used to import your data to a new server hub, but does not contain your content.'), - '$fulltitle' => t('Export Content'), - '$full' => t('Export your channel information and recent content to a JSON backup that can be restored or imported to another server hub. This backs up all of your connections, permissions, profile data and several months of posts. This file may be VERY large. Please be patient - it may take several minutes for this download to begin.'), - - '$by_year' => t('Export your posts from a given year.'), - - '$extra' => t('You may also export your posts and conversations for a particular year or month. Adjust the date in your browser location bar to select other dates. If the export fails (possibly due to memory exhaustion on your server hub), please try again selecting a more limited date range.'), - '$extra2' => sprintf( t('To select all posts for a given year, such as this year, visit <a href="%1$s">%2$s</a>'),$yearurl,$yearurl), - '$extra3' => sprintf( t('To select all posts for a given month, such as January of this year, visit <a href="%1$s">%2$s</a>'),$janurl,$janurl), - '$extra4' => sprintf( t('These content files may be imported or restored by visiting <a href="%1$s">%2$s</a> on any site containing your channel. For best results please import or restore these in date order (oldest first).'),$impurl,$impurl) - + + '$channel_title' => t('Export channel'), + '$channel_info' => t('This will export your identity and social graph into a file which can be used to import your channel to a new hub.'), + + '$years' => $years, + '$content_title' => t('Export content'), + '$content_info' => t('This will export your posts, direct messages, articles and cards per month stored into a zip file per year. Months with no posts will be dismissed.'), + + '$wikis_title' => t('Export wikis'), + '$wikis_info' => t('This will export your wikis and wiki pages.'), + + '$webpages_title' => t('Export webpages'), + '$webpages_info' => t('This will export your webpages and menus.'), + + '$events_title' => t('Export channel calendar'), + '$events_info' => t('This will export your channel calendar events and associated items. CalDAV calendars are not included.'), + + '$chatrooms_title' => t('Export chatrooms'), + '$chatrooms_info' => t('This will export your chatrooms. Chat history is dismissed.'), + + '$items_extra_info' => sprintf( t('This export can be imported or restored by visiting <a href="%1$s">%2$s</a> on any site containing your channel.'), $item_import_url, $item_import_url), )); - return $o; + return $o; } - + + + + } diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php index a0c293ddf..d54f61c36 100644 --- a/Zotlabs/Module/Viewconnections.php +++ b/Zotlabs/Module/Viewconnections.php @@ -6,7 +6,7 @@ require_once('include/selectors.php'); class Viewconnections extends \Zotlabs\Web\Controller { function init() { - + if(observer_prohibited()) { return; } @@ -16,58 +16,58 @@ class Viewconnections extends \Zotlabs\Web\Controller { } } - + function get() { - + if(observer_prohibited()) { notice( t('Public access denied.') . EOL); return; } - + if(((! count(\App::$profile)) || (\App::$profile['hide_friends']))) { notice( t('Permission denied.') . EOL); return; - } - + } + if(! perm_is_allowed(\App::$profile['uid'], get_observer_hash(),'view_contacts')) { notice( t('Permission denied.') . EOL); return; - } - + } + if(! $_REQUEST['aj']) $_SESSION['return_url'] = \App::$query_string; - - + + $is_owner = ((local_channel() && local_channel() == \App::$profile['uid']) ? true : false); - - $abook_flags = " and abook_pending = 0 and abook_self = 0 "; + + $abook_flags = " and abook_pending = 0 and abook_self = 0 and abook_blocked = 0 and abook_ignored = 0 "; $sql_extra = ''; - + if(! $is_owner) { $abook_flags .= " and abook_hidden = 0 "; $sql_extra = " and xchan_hidden = 0 "; } - + $r = q("SELECT count(*) as total FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra ", intval(\App::$profile['uid']) ); if($r) { \App::set_pager_total($r[0]['total']); } - + $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra order by xchan_name LIMIT %d OFFSET %d ", intval(\App::$profile['uid']), intval(\App::$pager['itemspage']), intval(\App::$pager['start']) ); - + if((! $r) && (! $_REQUEST['aj'])) { info( t('No connections.') . EOL ); return $o; } - + $contacts = array(); - + foreach($r as $rr) { $oneway = false; @@ -103,7 +103,7 @@ class Viewconnections extends \Zotlabs\Web\Controller { 'id' => $rr['abook_id'], 'archived' => (intval($rr['abook_archived']) ? true : false), 'img_hover' => sprintf( t('Visit %s\'s profile [%s]'), $rr['xchan_name'], $rr['xchan_url']), - 'thumb' => $rr['xchan_photo_m'], + 'thumb' => $rr['xchan_photo_m'], 'name' => substr($rr['xchan_name'],0,20), 'username' => $rr['xchan_addr'], 'link' => $url, @@ -137,11 +137,11 @@ class Viewconnections extends \Zotlabs\Web\Controller { // '$paginate' => paginate($a), )); } - + if(! $contacts) $o .= '<div id="content-complete"></div>'; - + return $o; } - + } diff --git a/Zotlabs/Module/Vote.php b/Zotlabs/Module/Vote.php index d67a6f176..4f909d33d 100644 --- a/Zotlabs/Module/Vote.php +++ b/Zotlabs/Module/Vote.php @@ -24,7 +24,7 @@ class Vote extends Controller { $fetch = null; $id = argv(1); $response = $_REQUEST['answer']; - + if ($id) { $fetch = q("select * from item where id = %d limit 1", intval($id) @@ -42,7 +42,7 @@ class Vote extends Controller { } $valid = false; - + if ($obj['oneOf']) { foreach($obj['oneOf'] as $selection) { // logger('selection: ' . $selection); @@ -80,7 +80,6 @@ class Vote extends Controller { $item = []; - $item['aid'] = $channel['channel_account_id']; $item['uid'] = $channel['channel_id']; $item['item_origin'] = 1; @@ -95,11 +94,8 @@ class Vote extends Controller { $item['owner_xchan'] = $fetch[0]['author_xchan']; $item['allow_cid'] = '<' . $fetch[0]['author_xchan'] . '>'; $item['item_private'] = 1; - - $item['obj_type'] = 'Note'; $item['author'] = channelx_by_n($channel['channel_id']); - $item['obj'] = Activity::encode_item($item); // now reset the placeholders @@ -108,17 +104,15 @@ class Vote extends Controller { $item['obj_type'] = 'Answer'; unset($item['author']); - $x = item_store($item); - retain_item($fetch[0]['id']); if($x['success']) { $itemid = $x['item_id']; Master::Summon( [ 'Notifier', 'like', $itemid ] ); } - + $r = q("select * from item where id = %d", intval($itemid) ); @@ -128,6 +122,7 @@ class Vote extends Controller { Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]); } } + $ret['success'] = true; $ret['message'] = t('Response submitted. Updates may not appear instantly.'); json_return_and_die($ret); diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index 787ed5850..bc47484be 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -15,26 +15,26 @@ require_once('include/acl_selectors.php'); class Webpages extends Controller { function init() { - + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { $sys = get_sys_channel(); if($sys && intval($sys['channel_id'])) { App::$is_sys = true; } } - + if(argc() > 1) $which = argv(1); else return; - + profile_load($which); - + } - - + + function get() { - + if(! App::$profile) { notice( t('Requested profile is not available.') . EOL ); App::$error = 404; @@ -44,22 +44,20 @@ class Webpages extends Controller { if(! Apps::system_app_installed(App::$profile_uid, 'Webpages')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Webpages App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Provide managed web pages on your channel'); - return $o; + $papp = Apps::get_papp('Webpages'); + return Apps::app_render($papp, 'module'); } nav_set_selected('Webpages'); $which = argv(1); - + $_SESSION['return_url'] = App::$query_string; - + $uid = local_channel(); $owner = 0; $observer = App::get_observer(); - + $channel = App::get_channel(); switch ($_SESSION['action']) { @@ -74,7 +72,7 @@ class Webpages extends Controller { '$blocks' => $_SESSION['blocks'], )); return $o; - + case 'importselected': $_SESSION['action'] = null; break; @@ -85,7 +83,7 @@ class Webpages extends Controller { break; } require_once('include/import.php'); - + $pages = get_webpage_elements($channel, 'pages'); $layouts = get_webpage_elements($channel, 'layouts'); $blocks = get_webpage_elements($channel, 'blocks'); @@ -99,13 +97,13 @@ class Webpages extends Controller { )); $_SESSION['export'] = null; return $o; - + default : $_SESSION['action'] = null; break; } - - + + if(App::$is_sys && is_site_admin()) { $sys = get_sys_channel(); if($sys && intval($sys['channel_id'])) { @@ -114,7 +112,7 @@ class Webpages extends Controller { $observer = $sys; } } - + if(! $owner) { // Figure out who the page owner is. $r = q("select channel_id from channel where channel_address = '%s'", @@ -124,24 +122,24 @@ class Webpages extends Controller { $owner = intval($r[0]['channel_id']); } } - + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); - + $perms = get_all_perms($owner,$ob_hash); - + if(! $perms['write_pages']) { notice( t('Permission denied.') . EOL); return; } - + $mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype')); - + $layout = (($_REQUEST['layout']) ? $_REQUEST['layout'] : get_pconfig($owner,'system','page_layout')); - + // 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. + // 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 == App::$profile_uid)) { $channel = App::get_channel(); } @@ -156,12 +154,12 @@ class Webpages extends Controller { else { $channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; } - + $is_owner = ($uid && $uid == $owner); $o = ''; - + $x = array( 'webpage' => ITEM_TYPE_WEBPAGE, 'is_owner' => true, @@ -183,23 +181,23 @@ class Webpages extends Controller { 'bbco_autocomplete' => 'bbcode', 'bbcode' => true ); - + if($_REQUEST['title']) $x['title'] = $_REQUEST['title']; if($_REQUEST['body']) $x['body'] = $_REQUEST['body']; if($_REQUEST['pagetitle']) $x['pagetitle'] = $_REQUEST['pagetitle']; - - - // Get a list of webpages. We can't display all them because endless scroll makes that unusable, + + + // 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. - - + + $sql_extra = item_permissions_sql($owner); - - $r = q("select * from iconfig left join item on iconfig.iid = item.id - where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item_type = %d + + $r = q("select * from iconfig left join item on iconfig.iid = item.id + where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item_type = %d $sql_extra order by item.created desc", intval($owner), intval(ITEM_TYPE_WEBPAGE) @@ -211,14 +209,13 @@ class Webpages extends Controller { $editor = status_editor($a,$x,false,'Webpages'); $pages = null; - + if($r) { $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'], @@ -243,11 +240,11 @@ class Webpages extends Controller { ); } } - - + + //Build the base URL for edit links $url = z_root() . '/editwebpage/' . $which; - + $o .= replace_macros(get_markup_template('webpagelist.tpl'), array( '$listtitle' => t('Webpages'), '$baseurl' => $url, @@ -266,19 +263,19 @@ class Webpages extends Controller { '$created_txt' => t('Created'), '$edited_txt' => t('Edited') )); - + return $o; } - + function post() { $action = $_REQUEST['action']; if( $action ){ switch ($action) { case 'scan': - + // the state of this variable tracks whether website files have been scanned (null, true, false) - $cloud = null; - + $cloud = null; + // Website files are to be imported from an uploaded zip file if(($_FILES) && array_key_exists('zip_file',$_FILES) && isset($_POST['w_upload'])) { $source = $_FILES["zip_file"]["tmp_name"]; @@ -306,8 +303,8 @@ class Webpages extends Controller { } else { notice( t('Error opening zip file') . EOL); return null; - } - } + } + } // Website files are to be imported from the channel cloud files if (($_POST) && array_key_exists('path',$_POST) && isset($_POST['cloudsubmit'])) { @@ -321,7 +318,7 @@ class Webpages extends Controller { $cloud = true; } - + // If the website files were uploaded or specified in the cloud files, then $cloud // should be either true or false if ($cloud !== null) { @@ -345,24 +342,24 @@ class Webpages extends Controller { notice( t('No webpage elements detected.') . EOL); $_SESSION['action'] = null; } - + } - + // If the website elements were imported from a zip file, delete the temporary decompressed files if ($cloud === false && $website && $elements) { $_SESSION['tempimportpath'] = $website; //rrmdir($website); // Delete the temporary decompressed files } - + break; - + case 'importselected': require_once('include/import.php'); $channel = App::get_channel(); - + // Import layout first so that pages that reference new layouts will find - // the mid of layout items in the database - + // the mid of layout items in the database + // Obtain the user-selected layouts to import and import them $checkedlayouts = $_POST['layout']; $layouts = []; @@ -380,7 +377,7 @@ class Webpages extends Controller { } } $_SESSION['import_layouts'] = $layouts; - + // Obtain the user-selected blocks to import and import them $checkedblocks = $_POST['block']; $blocks = []; @@ -398,7 +395,7 @@ class Webpages extends Controller { } } $_SESSION['import_blocks'] = $blocks; - + // Obtain the user-selected pages to import and import them $checkedpages = $_POST['page']; $pages = []; @@ -424,9 +421,9 @@ class Webpages extends Controller { unset($_SESSION['tempimportpath']); } break; - + case 'exportzipfile': - + if(isset($_POST['w_download'])) { $_SESSION['action'] = 'export_select_list'; $_SESSION['export'] = 'zipfile'; @@ -436,45 +433,45 @@ class Webpages extends Controller { $filename = 'website.zip'; } $_SESSION['zipfilename'] = $filename; - + } - + break; - + case 'exportcloud': if(isset($_POST['exportcloudpath']) && $_POST['exportcloudpath'] !== '') { $_SESSION['action'] = 'export_select_list'; $_SESSION['export'] = 'cloud'; $_SESSION['exportcloudpath'] = filter_var($_POST['exportcloudpath'], FILTER_SANITIZE_ENCODED); } - + break; - + case 'cloud': case 'zipfile': - + $channel = App::get_channel(); - + $tmp_folder_name = random_string(10); $zip_folder_name = random_string(10); $zip_filename = $_SESSION['zipfilename']; $tmp_folderpath = '/tmp/' . $tmp_folder_name; $zip_folderpath = '/tmp/' . $zip_folder_name; - if (!mkdir($zip_folderpath, 0770, false)) { + if (!mkdir($zip_folderpath, 0770, false)) { logger('Error creating zip file export folder: ' . $zip_folderpath, LOGGER_NORMAL); json_return_and_die(array('message' => 'Error creating zip file export folder')); } $zip_filepath = '/tmp/' . $zip_folder_name . '/' . $zip_filename; - + $checkedblocks = $_POST['block']; $blocks = []; if (!empty($checkedblocks)) { foreach ($checkedblocks as $mid) { - $b = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig - left join item on item.id = iconfig.iid + $b = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig + left join item on item.id = iconfig.iid where mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK' order by iconfig.v asc limit 1", dbesc($mid), - intval($channel['channel_id']) + intval($channel['channel_id']) ); if($b) { $b = $b[0]; @@ -514,25 +511,25 @@ class Webpages extends Controller { $block_filepath = $tmp_blockfolder . '/' . $block_filename; $blockinfo['json']['contentfile'] = $block_filename; $block_jsonpath = $tmp_blockfolder . '/block.json'; - if (!is_dir($tmp_blockfolder) && !mkdir($tmp_blockfolder, 0770, true)) { + if (!is_dir($tmp_blockfolder) && !mkdir($tmp_blockfolder, 0770, true)) { logger('Error creating temp export folder: ' . $tmp_blockfolder, LOGGER_NORMAL); json_return_and_die(array('message' => 'Error creating temp export folder')); } file_put_contents($block_filepath, $blockinfo['body']); - file_put_contents($block_jsonpath, json_encode($blockinfo['json'], JSON_UNESCAPED_SLASHES)); + file_put_contents($block_jsonpath, json_encode($blockinfo['json'], JSON_UNESCAPED_SLASHES)); } } } - + $checkedlayouts = $_POST['layout']; $layouts = []; if (!empty($checkedlayouts)) { foreach ($checkedlayouts as $mid) { - $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig - left join item on item.id = iconfig.iid + $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig + left join item on item.id = iconfig.iid where mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' order by iconfig.v asc limit 1", dbesc($mid), - intval($channel['channel_id']) + intval($channel['channel_id']) ); if($l) { $l = $l[0]; @@ -558,38 +555,38 @@ class Webpages extends Controller { $layout_filepath = $tmp_layoutfolder . '/' . $layout_filename; $layoutinfo['json']['contentfile'] = $layout_filename; $layout_jsonpath = $tmp_layoutfolder . '/layout.json'; - if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) { + if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) { logger('Error creating temp export folder: ' . $tmp_layoutfolder, LOGGER_NORMAL); json_return_and_die(array('message' => 'Error creating temp export folder')); } file_put_contents($layout_filepath, $layoutinfo['body']); - file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES)); + file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES)); } } } - + $checkedpages = $_POST['page']; $pages = []; if (!empty($checkedpages)) { foreach ($checkedpages as $mid) { - - $p = q("select * from iconfig left join item on iconfig.iid = item.id + + $p = q("select * from iconfig left join item on iconfig.iid = item.id where item.uid = %d and item.mid = '%s' and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item_type = %d", intval($channel['channel_id']), dbesc($mid), intval(ITEM_TYPE_WEBPAGE) ); - + if($p) { foreach ($p as $pp) { // Get the associated layout $layoutinfo = array(); if($pp['layout_mid']) { - $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig - left join item on item.id = iconfig.iid + $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig + left join item on item.id = iconfig.iid where mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' order by iconfig.v asc limit 1", dbesc($pp['layout_mid']), - intval($channel['channel_id']) + intval($channel['channel_id']) ); if($l) { $l = $l[0]; @@ -614,12 +611,12 @@ class Webpages extends Controller { $layout_filepath = $tmp_layoutfolder . '/' . $layout_filename; $layoutinfo['json']['contentfile'] = $layout_filename; $layout_jsonpath = $tmp_layoutfolder . '/layout.json'; - if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) { + if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) { logger('Error creating temp export folder: ' . $tmp_layoutfolder, LOGGER_NORMAL); json_return_and_die(array('message' => 'Error creating temp export folder')); } file_put_contents($layout_filepath, $layoutinfo['body']); - file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES)); + file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES)); } } switch ($pp['mimetype']) { @@ -660,14 +657,14 @@ class Webpages extends Controller { $page_filepath = $tmp_pagefolder . '/' . $page_filename; $page_jsonpath = $tmp_pagefolder . '/page.json'; $pageinfo['json']['contentfile'] = $page_filename; - if (!is_dir($tmp_pagefolder) && !mkdir($tmp_pagefolder, 0770, true)) { + if (!is_dir($tmp_pagefolder) && !mkdir($tmp_pagefolder, 0770, true)) { logger('Error creating temp export folder: ' . $tmp_pagefolder, LOGGER_NORMAL); json_return_and_die(array('message' => 'Error creating temp export folder')); } file_put_contents($page_filepath, $pageinfo['body']); file_put_contents($page_jsonpath, json_encode($pageinfo['json'], JSON_UNESCAPED_SLASHES)); } - } + } } } if($action === 'zipfile') { @@ -686,23 +683,23 @@ class Webpages extends Controller { if(!$dirpath) { $x = attach_mkdirp($channel, $channel['channel_hash'], array('pathname' => $cloudpath)); $folder_hash = (($x['success']) ? $x['data']['hash'] : ''); - + if (!$x['success']) { logger('Failed to create cloud file folder', LOGGER_NORMAL); } $dirpath = get_dirpath_by_cloudpath($channel, $cloudpath); if (!is_dir($dirpath)) { logger('Failed to create cloud file folder', LOGGER_NORMAL); - } + } } - + $success = copy_folder_to_cloudfiles($channel, $channel['channel_hash'], $tmp_folderpath, $cloudpath); } } if(!$success) { logger('Error exporting webpage elements', LOGGER_NORMAL); } - + rrmdir($zip_folderpath); rrmdir($tmp_folderpath); // delete temporary files killme(); @@ -710,9 +707,9 @@ class Webpages extends Controller { default : break; } - + } - + } - + } diff --git a/Zotlabs/Module/Well_known.php b/Zotlabs/Module/Well_known.php index 0d7b222b8..af59b76e0 100644 --- a/Zotlabs/Module/Well_known.php +++ b/Zotlabs/Module/Well_known.php @@ -5,36 +5,28 @@ namespace Zotlabs\Module; class Well_known extends \Zotlabs\Web\Controller { function init(){ - + if(argc() > 1) { - + $arr = array('server' => $_SERVER, 'request' => $_REQUEST); call_hooks('well_known', $arr); - - + + if(! check_siteallowed($_SERVER['REMOTE_ADDR'])) { logger('well_known: site not allowed. ' . $_SERVER['REMOTE_ADDR']); killme(); } - + // from php.net re: REMOTE_HOST: - // Note: Your web server must be configured to create this variable. For example in Apache - // you'll need HostnameLookups On inside httpd.conf for it to exist. See also gethostbyaddr(). - + // Note: Your web server must be configured to create this variable. For example in Apache + // you'll need HostnameLookups On inside httpd.conf for it to exist. See also gethostbyaddr(). + if(get_config('system','siteallowed_remote_host') && (! check_siteallowed($_SERVER['REMOTE_HOST']))) { logger('well_known: site not allowed. ' . $_SERVER['REMOTE_HOST']); killme(); } - + switch(argv(1)) { - case 'zot-info': - \App::$argc -= 1; - array_shift(\App::$argv); - \App::$argv[0] = 'zfinger'; - $module = new \Zotlabs\Module\Zfinger(); - $module->init(); - break; - case 'webfinger': \App::$argc -= 1; array_shift(\App::$argv); @@ -42,7 +34,7 @@ class Well_known extends \Zotlabs\Web\Controller { $module = new \Zotlabs\Module\Wfinger(); $module->init(); break; - + case 'host-meta': \App::$argc -= 1; array_shift(\App::$argv); @@ -63,7 +55,7 @@ class Well_known extends \Zotlabs\Web\Controller { case 'dnt-policy.txt': echo file_get_contents('doc/dnt-policy.txt'); killme(); - + case 'caldav': case 'carddav': if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') { @@ -73,16 +65,16 @@ class Well_known extends \Zotlabs\Web\Controller { default: if(file_exists(\App::$cmd)) { - echo file_get_contents(\App::$cmd); + echo file_get_contents(\App::$cmd); killme(); } elseif(file_exists(\App::$cmd . '.php')) require_once(\App::$cmd . '.php'); break; - + } } - + http_status_exit(404); } } diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php index 46da7f007..6d0e78587 100644 --- a/Zotlabs/Module/Wfinger.php +++ b/Zotlabs/Module/Wfinger.php @@ -1,8 +1,6 @@ <?php namespace Zotlabs\Module; -require_once('include/zot.php'); - use Zotlabs\Lib\Keyutils; use Zotlabs\Lib\Libzot; @@ -21,7 +19,7 @@ class Wfinger extends \Zotlabs\Web\Controller { elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443)) $scheme = 'https'; elseif(x($_SERVER,'HTTP_X_FORWARDED_PROTO') && ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) - $scheme = 'https'; + $scheme = 'https'; $zot = intval($_REQUEST['zot']); @@ -69,25 +67,21 @@ class Wfinger extends \Zotlabs\Web\Controller { $channel = substr($channel,1); $channel = substr($channel,0,-1); $pchan = true; - $r = q("select * from pchan left join xchan on pchan_hash = xchan_hash + $r = q("select * from pchan left join xchan on pchan_hash = xchan_hash where pchan_guid = '%s' limit 1", dbesc($channel) ); if($r) { - $r[0] = pchan_to_chan($r[0]); + $r = pchan_to_chan($r[0]); } } else { - $r = q("select * from channel left join xchan on channel_hash = xchan_hash - where channel_address = '%s' limit 1", - dbesc($channel) - ); + $r = channelx_by_nick($channel); } } header('Access-Control-Allow-Origin: *'); - if($root_resource) { $result['subject'] = $resource; $result['properties'] = [ @@ -109,15 +103,15 @@ class Wfinger extends \Zotlabs\Web\Controller { if($resource && $r) { $h = q("select hubloc_addr from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0", - dbesc($r[0]['channel_hash']) + dbesc($r['channel_hash']) ); $result['subject'] = $resource; $aliases = array( - z_root() . (($pchan) ? '/pchan/' : '/channel/') . $r[0]['channel_address'], - z_root() . '/~' . $r[0]['channel_address'], - z_root() . '/@' . $r[0]['channel_address'] + z_root() . (($pchan) ? '/pchan/' : '/channel/') . $r['channel_address'], + z_root() . '/~' . $r['channel_address'], + z_root() . '/@' . $r['channel_address'] ); if($h) { @@ -129,10 +123,10 @@ class Wfinger extends \Zotlabs\Web\Controller { $result['aliases'] = []; $result['properties'] = [ - 'http://webfinger.net/ns/name' => $r[0]['channel_name'], - 'http://xmlns.com/foaf/0.1/name' => $r[0]['channel_name'], - 'https://w3id.org/security/v1#publicKeyPem' => $r[0]['xchan_pubkey'], - 'http://purl.org/zot/federation' => 'zot6,zot' + 'http://webfinger.net/ns/name' => $r['channel_name'], + 'http://xmlns.com/foaf/0.1/name' => $r['channel_name'], + 'https://w3id.org/security/v1#publicKeyPem' => $r['xchan_pubkey'], + 'http://purl.org/zot/federation' => 'zot6' ]; foreach($aliases as $alias) @@ -145,18 +139,18 @@ class Wfinger extends \Zotlabs\Web\Controller { [ 'rel' => 'http://webfinger.net/rel/avatar', - 'type' => $r[0]['xchan_photo_mimetype'], - 'href' => $r[0]['xchan_photo_l'] + 'type' => $r['xchan_photo_mimetype'], + 'href' => $r['xchan_photo_l'] ], [ 'rel' => 'http://webfinger.net/rel/profile-page', - 'href' => $r[0]['xchan_url'], + 'href' => $r['xchan_url'], ], [ 'rel' => 'magic-public-key', - 'href' => 'data:application/magic-public-key,' . Keyutils::salmonKey($r[0]['channel_pubkey']), + 'href' => 'data:application/magic-public-key,' . Keyutils::salmonKey($r['channel_pubkey']), ] ]; @@ -169,14 +163,14 @@ class Wfinger extends \Zotlabs\Web\Controller { [ 'rel' => 'http://webfinger.net/rel/avatar', - 'type' => $r[0]['xchan_photo_mimetype'], - 'href' => $r[0]['xchan_photo_l'] + 'type' => $r['xchan_photo_mimetype'], + 'href' => $r['xchan_photo_l'] ], [ 'rel' => 'http://microformats.org/profile/hcard', 'type' => 'text/html', - 'href' => z_root() . '/hcard/' . $r[0]['channel_address'] + 'href' => z_root() . '/hcard/' . $r['channel_address'] ], [ @@ -186,18 +180,12 @@ class Wfinger extends \Zotlabs\Web\Controller { [ 'rel' => 'http://webfinger.net/rel/profile-page', - 'href' => z_root() . '/profile/' . $r[0]['channel_address'], - ], - - [ - 'rel' => 'http://schemas.google.com/g/2010#updates-from', - 'type' => 'application/atom+xml', - 'href' => z_root() . '/ofeed/' . $r[0]['channel_address'] + 'href' => z_root() . '/profile/' . $r['channel_address'], ], [ 'rel' => 'http://webfinger.net/rel/blog', - 'href' => z_root() . '/channel/' . $r[0]['channel_address'], + 'href' => z_root() . '/channel/' . $r['channel_address'], ], [ @@ -208,12 +196,7 @@ class Wfinger extends \Zotlabs\Web\Controller { [ 'rel' => 'http://purl.org/zot/protocol/6.0', 'type' => 'application/x-zot+json', - 'href' => channel_url($r[0]) - ], - - [ - 'rel' => 'http://purl.org/zot/protocol', - 'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'], + 'href' => channel_url($r) ], [ @@ -224,14 +207,14 @@ class Wfinger extends \Zotlabs\Web\Controller { [ 'rel' => 'magic-public-key', - 'href' => 'data:application/magic-public-key,' . Keyutils::salmonKey($r[0]['channel_pubkey']), + 'href' => 'data:application/magic-public-key,' . Keyutils::salmonKey($r['channel_pubkey']), ] ]; } if($zot) { // get a zotinfo packet and return it with webfinger - $result['zot'] = Libzot::zotinfo( [ 'address' => $r[0]['xchan_addr'] ]); + $result['zot'] = Libzot::zotinfo( [ 'address' => $r['xchan_addr'] ]); } } @@ -240,7 +223,7 @@ class Wfinger extends \Zotlabs\Web\Controller { killme(); } - $arr = [ 'channel' => $r[0], 'pchan' => $pchan, 'request' => $_REQUEST, 'result' => $result ]; + $arr = [ 'channel' => $r, 'pchan' => $pchan, 'request' => $_REQUEST, 'result' => $result ]; call_hooks('webfinger',$arr); json_return_and_die($arr['result'],'application/jrd+json'); diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 04c1dbeaa..3d0c07492 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -48,10 +48,8 @@ class Wiki extends Controller { if(! Apps::system_app_installed(App::$profile_uid, 'Wiki')) { //Do not display any associated widgets at this point App::$pdl = ''; - - $o = '<b>' . t('Wiki App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Provide a wiki for your channel'); - return $o; + $papp = Apps::get_papp('Wiki'); + return Apps::app_render($papp, 'module'); } @@ -68,7 +66,7 @@ class Wiki extends Controller { $pageHistory = array(); $local_observer = null; $resource_id = ''; - + // init() should have forced the URL to redirect to /wiki/channel so assume argc() > 1 $nick = argv(1); @@ -98,9 +96,9 @@ class Wiki extends Controller { // Initialize the ACL to the channel default permissions $x = array( - 'lockstate' => (( $owner['channel_allow_cid'] || - $owner['channel_allow_gid'] || - $owner['channel_deny_cid'] || + 'lockstate' => (( $owner['channel_allow_cid'] || + $owner['channel_allow_gid'] || + $owner['channel_deny_cid'] || $owner['channel_deny_gid']) ? 'lock' : 'unlock' ), @@ -113,7 +111,7 @@ class Wiki extends Controller { ); } else { - // Not the channel owner + // Not the channel owner $owner_acl = $x = array(); } @@ -272,10 +270,10 @@ class Wiki extends Controller { if(! $w['resource_id']) { notice(t('Wiki not found') . EOL); goaway(z_root() . '/' . argv(0) . '/' . argv(1)); - } + } $resource_id = $w['resource_id']; - + if(! $wiki_owner) { // Check for observer permissions $observer_hash = get_observer_hash(); @@ -316,7 +314,7 @@ class Wiki extends Controller { 'channel_address' => $owner['channel_address'], 'refresh' => true ]); - //json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true)); + //json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true)); notice( t('Error retrieving page content') . EOL); //goaway(z_root() . '/' . argv(0) . '/' . argv(1) ); $renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName)); @@ -334,7 +332,7 @@ class Wiki extends Controller { $hookinfo = ['content' => $content, 'mimetype' => $mimeType]; call_hooks('wiki_preprocess',$hookinfo); $content = $hookinfo['content']; - + // Render the Markdown-formatted page content in HTML if($mimeType == 'text/bbcode') { $renderedContent = zidify_links(smilies(bbcode($content))); @@ -356,7 +354,7 @@ class Wiki extends Controller { // default: // Strip the extraneous URL components // goaway('/' . argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName) . '/' . $pageUrlName); } - + $wikiModalID = random_string(3); @@ -458,18 +456,18 @@ class Wiki extends Controller { } json_return_and_die(array('html' => $html, 'success' => true)); } - + // Create a new wiki // /wiki/channel/create/wiki if ((argc() > 3) && (argv(2) === 'create') && (argv(3) === 'wiki')) { - // Only the channel owner can create a wiki, at least until we create a + // Only the channel owner can create a wiki, at least until we create a // more detail permissions framework if (local_channel() !== intval($owner['channel_id'])) { goaway('/' . argv(0) . '/' . $nick . '/'); - } - $wiki = array(); + } + $wiki = array(); // backslashes won't work well in the javascript functions $name = str_replace('\\','',$_POST['wikiName']); @@ -478,12 +476,12 @@ class Wiki extends Controller { $wiki['postVisible'] = ((intval($_POST['postVisible'])) ? 1 : 0); $wiki['rawName'] = $name; $wiki['htmlName'] = escape_tags($name); - //$wiki['urlName'] = urlencode(urlencode($name)); + //$wiki['urlName'] = urlencode(urlencode($name)); $wiki['urlName'] = NativeWiki::name_encode($name); $wiki['mimeType'] = $_POST['mimeType']; $wiki['typelock'] = $_POST['typelock']; - if($wiki['urlName'] === '') { + if($wiki['urlName'] === '') { notice( t('Error creating wiki. Invalid name.') . EOL); goaway('/wiki'); return; //not reached @@ -502,7 +500,7 @@ class Wiki extends Controller { $r = NativeWiki::create_wiki($owner, $observer_hash, $wiki, $acl); if($r['success']) { NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']); - $homePage = NativeWikiPage::create_page($owner['channel_id'],$observer_hash,'Home', $r['item']['resource_id'], $wiki['mimeType']); + $homePage = NativeWikiPage::create_page($owner, $observer_hash, 'Home', $r['item']['resource_id'], $wiki['mimeType']); if(! $homePage['success']) { notice( t('Wiki created, but error creating Home page.')); goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName'])); @@ -519,7 +517,7 @@ class Wiki extends Controller { // Update a wiki // /wiki/channel/update/wiki if ((argc() > 3) && (argv(2) === 'update') && (argv(3) === 'wiki')) { - // Only the channel owner can update a wiki, at least until we create a + // Only the channel owner can update a wiki, at least until we create a // more detail permissions framework if (local_channel() !== intval($owner['channel_id'])) { @@ -544,7 +542,7 @@ class Wiki extends Controller { if($wiki['resource_id']) { $arr['resource_id'] = $wiki['resource_id']; - + $acl = new \Zotlabs\Access\AccessList($owner); $acl->set_from_array($_POST); @@ -565,18 +563,18 @@ class Wiki extends Controller { // Delete a wiki if ((argc() > 3) && (argv(2) === 'delete') && (argv(3) === 'wiki')) { - // Only the channel owner can delete a wiki, at least until we create a + // Only the channel owner can delete a wiki, at least until we create a // more detail permissions framework if (local_channel() !== intval($owner['channel_id'])) { logger('Wiki delete permission denied.'); json_return_and_die(array('message' => t('Wiki delete permission denied.'), 'success' => false)); - } - $resource_id = $_POST['resource_id']; + } + $resource_id = $_POST['resource_id']; $deleted = NativeWiki::delete_wiki($owner['channel_id'],$observer_hash,$resource_id); if ($deleted['success']) { NativeWiki::sync_a_wiki_item($owner['channel_id'], 0, $resource_id); json_return_and_die(array('message' => '', 'success' => true)); - } + } else { logger('Error deleting wiki: ' . $resource_id . ' ' . $deleted['message']); json_return_and_die(array('message' => t('Error deleting wiki'), 'success' => false)); @@ -589,14 +587,14 @@ class Wiki extends Controller { $mimetype = $_POST['mimetype']; - $resource_id = $_POST['resource_id']; + $resource_id = $_POST['resource_id']; // Determine if observer has permission to create a page - - $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash, $mimetype); + + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied. ' . EOL); - json_return_and_die(array('success' => false)); + json_return_and_die(array('success' => false)); } $name = isset($_POST['pageName']) ? $_POST['pageName'] : $_POST['missingPageName']; //Get new page name @@ -608,12 +606,12 @@ class Wiki extends Controller { json_return_and_die(array('message' => 'Error creating page. Invalid name (' . print_r($_POST,true) . ').', 'success' => false)); } - $page = NativeWikiPage::create_page($owner['channel_id'],$observer_hash, $name, $resource_id, $mimetype); + $page = NativeWikiPage::create_page($owner, $observer_hash, $name, $resource_id, $mimetype); if($page['item_id']) { $commit = NativeWikiPage::commit([ - 'commit_msg' => t('New page created'), - 'resource_id' => $resource_id, + 'commit_msg' => t('New page created'), + 'resource_id' => $resource_id, 'channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'pageUrlName' => $name @@ -622,10 +620,10 @@ class Wiki extends Controller { NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id); //json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']), 'success' => true)); json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . $page['wiki']['urlName'] . '/' . $page['page']['urlName'], 'success' => true)); - } + } else { json_return_and_die(array('message' => 'Error making git commit','url' => '/' . argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($page['wiki']['urlName']) . '/' . NativeWiki::name_encode($page['page']['urlName']),'success' => false)); - } + } } @@ -633,8 +631,8 @@ class Wiki extends Controller { logger('Error creating page'); json_return_and_die(array('message' => 'Error creating page.', 'success' => false)); } - } - + } + // Fetch page list for a wiki if((argc() === 5) && (argv(2) === 'get') && (argv(3) === 'page') && (argv(4) === 'list')) { $resource_id = $_POST['resource_id']; // resource_id for wiki in db @@ -642,7 +640,7 @@ class Wiki extends Controller { $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(!$perms['read']) { logger('Wiki read permission denied.' . EOL); - json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false)); + json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false)); } // @FIXME - we shouldn't invoke this if it isn't in the PDL or has been over-ridden @@ -655,17 +653,17 @@ class Wiki extends Controller { 'channel_address' => $owner['channel_address'], 'refresh' => true ]); - json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true)); + json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true)); } - + // Save a page if ((argc() === 4) && (argv(2) === 'save') && (argv(3) === 'page')) { - - $resource_id = $_POST['resource_id']; + + $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; $pageHtmlName = escape_tags($_POST['name']); $content = $_POST['content']; //Get new content - $commitMsg = $_POST['commitMsg']; + $commitMsg = $_POST['commitMsg']; if ($commitMsg === '') { $commitMsg = 'Updated ' . $pageHtmlName; } @@ -674,7 +672,7 @@ class Wiki extends Controller { $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied. ' . EOL); - json_return_and_die(array('success' => false)); + json_return_and_die(array('success' => false)); } $saved = NativeWikiPage::save_page([ @@ -687,9 +685,9 @@ class Wiki extends Controller { if($saved['success']) { $commit = NativeWikiPage::commit([ - 'commit_msg' => $commitMsg, + 'commit_msg' => $commitMsg, 'pageUrlName' => $pageUrlName, - 'resource_id' => $resource_id, + 'resource_id' => $resource_id, 'channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'revision' => (-1) @@ -699,21 +697,21 @@ class Wiki extends Controller { json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true , 'content' => $content)); } else { - json_return_and_die(array('message' => 'Error making git commit','success' => false)); + json_return_and_die(array('message' => 'Error making git commit','success' => false)); } } else { - json_return_and_die(array('message' => 'Error saving page', 'success' => false)); + json_return_and_die(array('message' => 'Error saving page', 'success' => false)); } } - + // Update page history // /wiki/channel/history/page if ((argc() === 4) && (argv(2) === 'history') && (argv(3) === 'page')) { - + $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; - + // Determine if observer has permission to read content $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); @@ -734,7 +732,7 @@ class Wiki extends Controller { // Delete a page if ((argc() === 4) && (argv(2) === 'delete') && (argv(3) === 'page')) { - $resource_id = $_POST['resource_id']; + $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; if ($pageUrlName === 'Home') { @@ -745,13 +743,13 @@ class Wiki extends Controller { // currently just allow page owner if((! local_channel()) || (local_channel() != $owner['channel_id'])) { logger('Wiki write permission denied. ' . EOL); - json_return_and_die(array('success' => false)); + json_return_and_die(array('success' => false)); } $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied. ' . EOL); - json_return_and_die(array('success' => false)); + json_return_and_die(array('success' => false)); } $deleted = NativeWikiPage::delete_page([ @@ -765,14 +763,14 @@ class Wiki extends Controller { json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true)); } else { - json_return_and_die(array('message' => 'Error deleting page', 'success' => false)); + json_return_and_die(array('message' => 'Error deleting page', 'success' => false)); } } - + // Revert a page if ((argc() === 4) && (argv(2) === 'revert') && (argv(3) === 'page')) { - $resource_id = $_POST['resource_id']; + $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; $commitHash = $_POST['commitHash']; @@ -780,7 +778,7 @@ class Wiki extends Controller { $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied.' . EOL); - json_return_and_die(array('success' => false)); + json_return_and_die(array('success' => false)); } $reverted = NativeWikiPage::revert_page([ @@ -791,16 +789,16 @@ class Wiki extends Controller { 'pageUrlName' => $pageUrlName ]); if($reverted['success']) { - json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true)); + json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true)); } else { - json_return_and_die(array('content' => '', 'message' => 'Error reverting page', 'success' => false)); + json_return_and_die(array('content' => '', 'message' => 'Error reverting page', 'success' => false)); } } - + // Compare page revisions if ((argc() === 4) && (argv(2) === 'compare') && (argv(3) === 'page')) { - $resource_id = $_POST['resource_id']; + $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; $compareCommit = $_POST['compareCommit']; $currentCommit = $_POST['currentCommit']; @@ -809,21 +807,21 @@ class Wiki extends Controller { $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(!$perms['read']) { logger('Wiki read permission denied.' . EOL); - json_return_and_die(array('success' => false)); + json_return_and_die(array('success' => false)); } $compare = NativeWikiPage::compare_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'currentCommit' => $currentCommit, 'compareCommit' => $compareCommit, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); if($compare['success']) { $diffHTML = '<table class="text-center" width="100%"><tr><td class="lead" width="50%">' . t('Current Revision') . '</td><td class="lead" width="50%">' . t('Selected Revision') . '</td></tr></table>' . $compare['diff']; - json_return_and_die(array('diff' => $diffHTML, 'message' => '', 'success' => true)); + json_return_and_die(array('diff' => $diffHTML, 'message' => '', 'success' => true)); } else { - json_return_and_die(array('diff' => '', 'message' => 'Error comparing page', 'success' => false)); + json_return_and_die(array('diff' => '', 'message' => 'Error comparing page', 'success' => false)); } } - + // Rename a page if ((argc() === 4) && (argv(2) === 'rename') && (argv(3) === 'page')) { - $resource_id = $_POST['resource_id']; + $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['oldName']; $pageNewName = str_replace('\\','',$_POST['newName']); if ($pageUrlName === 'Home') { @@ -837,7 +835,7 @@ class Wiki extends Controller { $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied. ' . EOL); - json_return_and_die(array('success' => false)); + json_return_and_die(array('success' => false)); } $renamed = NativeWikiPage::rename_page([ @@ -850,8 +848,8 @@ class Wiki extends Controller { if($renamed['success']) { $commit = NativeWikiPage::commit([ 'channel_id' => $owner['channel_id'], - 'commit_msg' => 'Renamed ' . NativeWiki::name_decode($pageUrlName) . ' to ' . $renamed['page']['htmlName'], - 'resource_id' => $resource_id, + 'commit_msg' => 'Renamed ' . NativeWiki::name_decode($pageUrlName) . ' to ' . $renamed['page']['htmlName'], + 'resource_id' => $resource_id, 'observer_hash' => $observer_hash, 'pageUrlName' => $pageNewName ]); @@ -860,16 +858,16 @@ class Wiki extends Controller { json_return_and_die(array('name' => $renamed['page'], 'message' => 'Wiki git repo commit made', 'success' => true)); } else { - json_return_and_die(array('message' => 'Error making git commit','success' => false)); + json_return_and_die(array('message' => 'Error making git commit','success' => false)); } } else { - json_return_and_die(array('message' => 'Error renaming page', 'success' => false)); + json_return_and_die(array('message' => 'Error renaming page', 'success' => false)); } } //notice( t('You must be authenticated.')); json_return_and_die(array('message' => t('You must be authenticated.'), 'success' => false)); - + } } diff --git a/Zotlabs/Module/Xrd.php b/Zotlabs/Module/Xrd.php index 21574eb8d..b7868c2cc 100644 --- a/Zotlabs/Module/Xrd.php +++ b/Zotlabs/Module/Xrd.php @@ -28,19 +28,18 @@ class Xrd extends \Zotlabs\Web\Controller { $name = substr($local,0,strpos($local,'@')); } - $r = q("SELECT * FROM channel WHERE channel_address = '%s' LIMIT 1", - dbesc($name) - ); + $r = channelx_by_nick($name); + if(! $r) killme(); - $salmon_key = Keyutils::salmonKey($r[0]['channel_pubkey']); + $salmon_key = Keyutils::salmonKey($r['channel_pubkey']); header('Access-Control-Allow-Origin: *'); header("Content-type: application/xrd+xml"); - $aliases = array('acct:' . channel_reddress($r[0]), z_root() . '/channel/' . $r[0]['channel_address'], z_root() . '/~' . $r[0]['channel_address']); + $aliases = array('acct:' . channel_reddress($r), z_root() . '/channel/' . $r['channel_address'], z_root() . '/~' . $r['channel_address']); for($x = 0; $x < count($aliases); $x ++) { if($aliases[$x] === $resource) @@ -48,23 +47,23 @@ class Xrd extends \Zotlabs\Web\Controller { } $o = replace_macros(get_markup_template('xrd_person.tpl'), array( - '$nick' => $r[0]['channel_address'], + '$nick' => $r['channel_address'], '$accturi' => $resource, '$subject' => $subject, '$aliases' => $aliases, - '$channel_url' => z_root() . '/channel/' . $r[0]['channel_address'], - '$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'], - '$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'], - '$atom' => z_root() . '/ofeed/' . $r[0]['channel_address'], - '$zot_post' => z_root() . '/post/' . $r[0]['channel_address'], - '$poco_url' => z_root() . '/poco/' . $r[0]['channel_address'], - '$photo' => z_root() . '/photo/profile/l/' . $r[0]['channel_id'], + '$channel_url' => z_root() . '/channel/' . $r['channel_address'], + '$profile_url' => z_root() . '/channel/' . $r['channel_address'], + '$hcard_url' => z_root() . '/hcard/' . $r['channel_address'], + '$atom' => z_root() . '/ofeed/' . $r['channel_address'], + '$zot_post' => z_root() . '/post/' . $r['channel_address'], + '$poco_url' => z_root() . '/poco/' . $r['channel_address'], + '$photo' => z_root() . '/photo/profile/l/' . $r['channel_id'], '$modexp' => 'data:application/magic-public-key,' . $salmon_key, '$subscribe' => z_root() . '/follow?f=&url={uri}', )); - $arr = array('user' => $r[0], 'xml' => $o); + $arr = array('user' => $r, 'xml' => $o); call_hooks('personal_xrd', $arr); echo $arr['xml']; diff --git a/Zotlabs/Module/Zfinger.php b/Zotlabs/Module/Zfinger.php deleted file mode 100644 index ce7117ad8..000000000 --- a/Zotlabs/Module/Zfinger.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -namespace Zotlabs\Module; - -use Zotlabs\Web\HTTPSig; -use Zotlabs\Lib\Libzot; - -class Zfinger extends \Zotlabs\Web\Controller { - - function init() { - - require_once('include/zot.php'); - require_once('include/crypto.php'); - - $x = zotinfo($_REQUEST); - - if($x && $x['guid'] && $x['guid_sig']) { - $chan_hash = make_xchan_hash($x['guid'],$x['guid_sig']); - if($chan_hash) { - $chan = channelx_by_hash($chan_hash); - } - } - - $headers = []; - $headers['Content-Type'] = 'application/json' ; - $ret = json_encode($x); - - if($chan) { - $headers['Digest'] = HTTPSig::generate_digest_header($ret); - $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'], channel_url($chan)); - HTTPSig::set_headers($h); - } - else { - foreach($headers as $k => $v) { - header($k . ': ' . $v); - } - } - - echo $ret; - killme(); - - } - -} diff --git a/Zotlabs/Module/Zotfeed.php b/Zotlabs/Module/Zotfeed.php index e47367036..0b4c3c007 100644 --- a/Zotlabs/Module/Zotfeed.php +++ b/Zotlabs/Module/Zotfeed.php @@ -1,124 +1,22 @@ <?php - namespace Zotlabs\Module; -use App; -use Zotlabs\Lib\Activity; -use Zotlabs\Lib\ActivityStreams; -use Zotlabs\Lib\Config; -use Zotlabs\Lib\ThreadListener; use Zotlabs\Web\Controller; -use Zotlabs\Web\HTTPSig; class Zotfeed extends Controller { - function init() { - if (ActivityStreams::is_as_request()) { - - if (observer_prohibited(true)) { - killme(); - } - - $channel = channelx_by_nick(argv(1)); - if (!$channel) { - killme(); - } - - if (intval($channel['channel_system'])) { - killme(); - } - - $sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR); - if ($sigdata['portable_id'] && $sigdata['header_valid']) { - $portable_id = $sigdata['portable_id']; - if (!check_channelallowed($portable_id)) { - http_status_exit(403, 'Permission denied'); - } - if (!check_siteallowed($sigdata['signer'])) { - http_status_exit(403, 'Permission denied'); - } - observer_auth($portable_id); - } - elseif (Config::get('system', 'require_authenticated_fetch', false)) { - http_status_exit(403, 'Permission denied'); - } - - $observer_hash = get_observer_hash(); - - $params = []; + function post() { - $params['begin'] = ((x($_REQUEST, 'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE); - $params['end'] = ((x($_REQUEST, 'date_end')) ? $_REQUEST['date_end'] : ''); - $params['type'] = 'json'; - $params['pages'] = ((x($_REQUEST, 'pages')) ? intval($_REQUEST['pages']) : 0); - $params['top'] = ((x($_REQUEST, 'top')) ? intval($_REQUEST['top']) : 0); - $params['direction'] = ((x($_REQUEST, 'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); // unimplemented - $params['cat'] = ((x($_REQUEST, 'cat')) ? escape_tags($_REQUEST['cat']) : ''); - $params['compat'] = 1; - - $total = items_fetch( - [ - 'total' => true, - 'wall' => 1, - 'datequery' => $params['end'], - 'datequery2' => $params['begin'], - 'direction' => dbesc($params['direction']), - 'pages' => $params['pages'], - 'order' => dbesc('post'), - 'top' => $params['top'], - 'cat' => $params['cat'], - 'compat' => $params['compat'] - ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module - ); - - if ($total) { - App::set_pager_total($total); - App::set_pager_itemspage(30); - } + } - if (App::$pager['unset'] && $total > 30) { - $ret = Activity::paged_collection_init($total, App::$query_string); - } - else { + function get() { - $items = items_fetch( - [ - 'wall' => 1, - 'datequery' => $params['end'], - 'datequery2' => $params['begin'], - 'records' => intval(App::$pager['itemspage']), - 'start' => intval(App::$pager['start']), - 'direction' => dbesc($params['direction']), - 'pages' => $params['pages'], - 'order' => dbesc('post'), - 'top' => $params['top'], - 'cat' => $params['cat'], - 'compat' => $params['compat'] - ], $channel, $observer_hash, CLIENT_MODE_NORMAL, App::$module - ); + $outbox = new Outbox(); + return $outbox->init(); - if ($items && $observer_hash) { + } - // check to see if this observer is a connection. If not, register any items - // belonging to this channel for notification of deletion/expiration +} - $x = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'", - intval($channel['channel_id']), - dbesc($observer_hash) - ); - if (!$x) { - foreach ($items as $item) { - if (strpos($item['mid'], z_root()) === 0) { - ThreadListener::store($item['mid'], $observer_hash); - } - } - } - } - $ret = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', $total); - } - as_return_and_die($ret, $channel); - } - } -} diff --git a/Zotlabs/Module/Zping.php b/Zotlabs/Module/Zping.php deleted file mode 100644 index d6128fa66..000000000 --- a/Zotlabs/Module/Zping.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php -namespace Zotlabs\Module; /** @file */ - -require_once('include/zot.php'); - - -class Zping extends \Zotlabs\Web\Controller { - - function get() { - - // This is just a test utility function and may go away once we build these tools into - // the address book and directory to do dead site discovery. - - // The response packet include the current URL and key so we can discover if the server - // has been re-installed and clean up (e.g. get rid of) any old hublocs and xchans. - - // Remember to add '/post' to the url - - if(! local_channel()) - return; - - $url = $_REQUEST['url']; - - if(! $url) - return; - - - $m = zot_build_packet(\App::get_channel(),'ping'); - $r = zot_zot($url,$m); - return print_r($r,true); - - } -} |