diff options
author | Mario <mario@mariovavti.com> | 2020-11-05 08:46:42 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2020-11-05 08:46:42 +0000 |
commit | bafbf0416462c6f18c3fb6c8c06a063c8d6fdae6 (patch) | |
tree | 8929845be585b09d0f420621281c5531e1efad3e /Zotlabs/Module | |
parent | 6f93d9848c43019d43ea76c27d42d657ba031cd7 (diff) | |
parent | fdefa101d84dc2a9424eaedbdb003a4c30ec5d01 (diff) | |
download | volse-hubzilla-bafbf0416462c6f18c3fb6c8c06a063c8d6fdae6.tar.gz volse-hubzilla-bafbf0416462c6f18c3fb6c8c06a063c8d6fdae6.tar.bz2 volse-hubzilla-bafbf0416462c6f18c3fb6c8c06a063c8d6fdae6.zip |
Merge branch '5.0RC'5.0
Diffstat (limited to 'Zotlabs/Module')
88 files changed, 3121 insertions, 1639 deletions
diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php index 82c156a9c..e0206bd43 100644 --- a/Zotlabs/Module/Acl.php +++ b/Zotlabs/Module/Acl.php @@ -42,7 +42,7 @@ class Acl extends \Zotlabs\Web\Controller { // $type = - // 'm' => autocomplete private mail recipient (checks post_mail permission) + // 'm' => autocomplete private mail recipient (checks post_mail permission and displays only zot, diaspora, friendica-over-diaspora xchan_network xchan's) // 'a' => autocomplete connections (mod_connections, mod_poke, mod_sources, mod_photos) // 'x' => nav search bar autocomplete (match any xchan) // $_REQUEST['query'] contains autocomplete search text. @@ -286,6 +286,7 @@ class Acl extends \Zotlabs\Web\Controller { 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') $sql_extra3 ORDER BY xchan_name ASC ", intval(local_channel()) diff --git a/Zotlabs/Module/Activity.php b/Zotlabs/Module/Activity.php new file mode 100644 index 000000000..b75f0b245 --- /dev/null +++ b/Zotlabs/Module/Activity.php @@ -0,0 +1,269 @@ +<?php +namespace Zotlabs\Module; + +use Zotlabs\Lib\IConfig; +use Zotlabs\Lib\Enotify; +use Zotlabs\Web\Controller; +use Zotlabs\Daemon\Master; +use Zotlabs\Lib\Activity as ZlibActivity; +use Zotlabs\Lib\ActivityStreams; +use Zotlabs\Lib\LDSignatures; +use Zotlabs\Web\HTTPSig; +use Zotlabs\Lib\Libzot; +use Zotlabs\Lib\ThreadListener; +use App; + + +class Activity extends Controller { + + function init() { + + if (Libzot::is_zot_request()) { + + $item_id = argv(1); + if (! $item_id) + http_status_exit(404, 'Not found'); + + $portable_id = EMPTY_STR; + + $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 "; + + $i = null; + + // do we have the item (at all)? + + $r = q("select * from item where mid = '%s' $item_normal limit 1", + dbesc(z_root() . '/activity/' . $item_id) + ); + + if (! $r) { + http_status_exit(404,'Not found'); + } + + // process an authenticated fetch + + $sigdata = HTTPSig::verify(EMPTY_STR); + if($sigdata['portable_id'] && $sigdata['header_valid']) { + $portable_id = $sigdata['portable_id']; + observer_auth($portable_id); + + // first see if we have a copy of this item's parent owned by the current signer + // include xchans for all zot-like networks - these will have the same guid and public key + + $x = q("select * from xchan where xchan_hash = '%s'", + dbesc($sigdata['portable_id']) + ); + + if ($x) { + $xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ", + dbesc($sigdata['portable_id']), + dbesc($x[0]['xchan_guid']), + dbesc($x[0]['xchan_pubkey']) + ); + + if ($xchans) { + $hashes = ids_to_querystr($xchans,'xchan_hash',true); + $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1", + dbesc($r[0]['parent_mid']) + ); + } + } + } + + // 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 + // with a bias towards those items owned by channels on this site (item_wall = 1) + + $sql_extra = item_permissions_sql(0); + + 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'); + } + + $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 ", + dbesc($parents_str) + ); + + if(! $items) { + http_status_exit(404, 'Not found'); + } + + xchan_query($items,true); + $items = fetch_post_tags($items,true); + + $observer = App::get_observer(); + $parent = $items[0]; + $recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'],'activitypub','recips', []) : []); + $to = (($recips && array_key_exists('to',$recips) && is_array($recips['to'])) ? $recips['to'] : null); + $nitems = []; + foreach($items as $i) { + + $mids = []; + + if(intval($i['item_private'])) { + if(! $observer) { + continue; + } + // ignore private reshare, possibly from hubzilla + if($i['verb'] === 'Announce') { + if(! in_array($i['thr_parent'],$mids)) { + $mids[] = $i['thr_parent']; + } + continue; + } + // also ignore any children of the private reshares + if(in_array($i['thr_parent'],$mids)) { + continue; + } + + if((! $to) || (! in_array($observer['xchan_url'],$to))) { + continue; + } + + } + $nitems[] = $i; + } + + if(! $nitems) + http_status_exit(404, 'Not found'); + + $chan = channelx_by_n($nitems[0]['uid']); + + if(! $chan) + http_status_exit(404, 'Not found'); + + if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream')) + http_status_exit(403, 'Forbidden'); + + $i = ZlibActivity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection'); + if($portable_id) { + ThreadListener::store(z_root() . '/activity/' . $item_id,$portable_id); + } + + if(! $i) + http_status_exit(404, 'Not found'); + + $x = array_merge(['@context' => [ + ACTIVITYSTREAMS_JSONLD_REV, + 'https://w3id.org/security/v1', + z_root() . ZOT_APSCHEMA_REV + ]], $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['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; + $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan)); + HTTPSig::set_headers($h); + echo $ret; + killme(); + + } + + if(ActivityStreams::is_as_request()) { + + $item_id = argv(1); + + if (! $item_id) { + return; + } + + $ob_authorise = false; + $item_uid = 0; + + $bear = ZlibActivity::token_from_request(); + if ($bear) { + logger('bear: ' . $bear, LOGGER_DEBUG); + $t = q("select item.uid, iconfig.v from iconfig left join item on iid = item.id where cat = 'ocap' and item.uuid = '%s'", + dbesc($item_id) + ); + if ($t) { + foreach ($t as $token) { + if ($token['v'] === $bear) { + $ob_authorize = true; + $item_uid = $token['uid']; + break; + } + } + } + } + + $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 + and item.item_delayed = 0 and item.item_blocked = 0 "; + + $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); + } + + // if passed an owner_id of 0 to item_permissions_sql(), we force "guest access" or observer checking + // Give ocap tokens priority + + if ($ob_authorize) { + $sql_extra = " and item.uid = " . intval($token['uid']) . " "; + } + else { + $sql_extra = item_permissions_sql(0); + } + + $r = q("select * from item where uuid = '%s' $item_normal $sql_extra limit 1", + dbesc($item_id) + ); + + if (! $r) { + $r = q("select * from item where uuid = '%s' $item_normal limit 1", + dbesc($item_id) + ); + if($r) { + http_status_exit(403, 'Forbidden'); + } + http_status_exit(404, 'Not found'); + } + + xchan_query($r,true); + $items = fetch_post_tags($r,false); + + $channel = channelx_by_n($items[0]['uid']); + + $x = array_merge( ['@context' => [ + ACTIVITYSTREAMS_JSONLD_REV, + 'https://w3id.org/security/v1', + z_root() . ZOT_APSCHEMA_REV + ]], ZlibActivity::encode_activity($items[0],true)); + + $headers = []; + $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ; + $x['signature'] = LDSignatures::sign($x,$channel); + $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,$channel['channel_prvkey'],channel_url($channel)); + HTTPSig::set_headers($h); + echo $ret; + killme(); + + } + + goaway(z_root() . '/item/' . argv(1)); + + } + +} diff --git a/Zotlabs/Module/Admin/Addons.php b/Zotlabs/Module/Admin/Addons.php index 243eb242f..b67ab7b3a 100644 --- a/Zotlabs/Module/Admin/Addons.php +++ b/Zotlabs/Module/Admin/Addons.php @@ -18,7 +18,7 @@ class Addons { @include_once("addon/" . argv(2) . "/" . argv(2) . ".php"); if(function_exists(argv(2).'_plugin_admin_post')) { $func = argv(2) . '_plugin_admin_post'; - $func($a); + $func(); } goaway(z_root() . '/admin/addons/' . argv(2) ); @@ -332,7 +332,7 @@ class Addons { @require_once("addon/$plugin/$plugin.php"); if(function_exists($plugin.'_plugin_admin')) { $func = $plugin.'_plugin_admin'; - $func($a, $admin_form); + $func($admin_form); } } diff --git a/Zotlabs/Module/Apporder.php b/Zotlabs/Module/Apporder.php index eac1abc2d..313c2df50 100644 --- a/Zotlabs/Module/Apporder.php +++ b/Zotlabs/Module/Apporder.php @@ -34,9 +34,9 @@ class Apporder extends \Zotlabs\Web\Controller { foreach($syslist as $app) { if($l === 'nav_pinned_app') { - $navbar_apps[] = Zlib\Apps::app_render($app,'nav-order'); + $navbar_apps[] = Zlib\Apps::app_render($app,'nav-order-pinned'); } - elseif(strpos($app['categories'],'nav_pinned_app') === false) { + else { $nav_apps[] = Zlib\Apps::app_render($app,'nav-order'); } } diff --git a/Zotlabs/Module/Apschema.php b/Zotlabs/Module/Apschema.php index 756057a8a..6b0325d44 100644 --- a/Zotlabs/Module/Apschema.php +++ b/Zotlabs/Module/Apschema.php @@ -29,7 +29,10 @@ class Apschema extends \Zotlabs\Web\Controller { 'emojiReaction' => 'zot:emojiReaction', 'expires' => 'zot:expires', 'directMessage' => 'zot:directMessage', - + 'schema' => 'http://schema.org#', + 'PropertyValue' => 'schema:PropertyValue', + 'value' => 'schema:value', + 'magicEnv' => [ '@id' => 'zot:magicEnv', '@type' => '@id' diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index 2c43b4764..3f726ebb9 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -149,7 +149,7 @@ class Articles extends Controller { } $itemspage = get_pconfig(local_channel(),'system','itemspage'); - App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10)); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 3f0e93de5..c44f7942b 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -145,7 +145,7 @@ class Cards extends Controller { $itemspage = get_pconfig(local_channel(),'system','itemspage'); - App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10)); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index af40689c1..d7d57664c 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -10,6 +10,7 @@ require_once('include/event.php'); require_once('include/auth.php'); require_once('include/security.php'); +require_once('include/cdav.php'); class Cdav extends Controller { @@ -156,6 +157,79 @@ class Cdav extends Controller { } } + + // Track CDAV updates from remote clients + + $httpmethod = $_SERVER['REQUEST_METHOD']; + + if($httpmethod === 'PUT' || $httpmethod === 'DELETE') { + + $httpuri = $_SERVER['REQUEST_URI']; + + logger("debug: method: " . $httpmethod, LOGGER_DEBUG); + logger("debug: uri: " . $httpuri, LOGGER_DEBUG); + + if(strpos($httpuri, 'cdav/addressbooks')) { + $sync = 'addressbook'; + $cdavtable = 'addressbooks'; + } + elseif(strpos($httpuri, 'cdav/calendars')) { + $sync = 'calendar'; + $cdavtable = 'calendarinstances'; + } + else + $sync = false; + + if($sync) { + + $uri = basename($httpuri); + $httpbody = file_get_contents('php://input'); + + logger("debug: body: " . $httpbody, LOGGER_DEBUG); + + if($x = get_cdav_id($principalUri, explode("/", $httpuri)[4], $cdavtable)) { + + $cdavdata = $this->get_cdav_data($x['id'], $cdavtable); + + $etag = (isset($_SERVER['HTTP_IF_MATCH']) ? $_SERVER['HTTP_IF_MATCH'] : false); + + // delete + if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag) + build_sync_packet($channel['channel_id'], [ + $sync => [ + 'action' => 'delete_card', + 'uri' => $cdavdata['uri'], + 'carduri' => $uri + ] + ]); + else { + if($etag) { + // update + if($cdavdata['etag'] !== $etag) + build_sync_packet($channel['channel_id'], [ + $sync => [ + 'action' => 'update_card', + 'uri' => $cdavdata['uri'], + 'carduri' => $uri, + 'card' => $httpbody + ] + ]); + } + else { + // new + build_sync_packet($channel['channel_id'], [ + $sync => [ + 'action' => 'import', + 'uri' => $cdavdata['uri'], + 'ids' => [ $uri ], + 'card' => $httpbody + ] + ]); + } + } + } + } + } $principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo); @@ -262,6 +336,14 @@ class Cdav extends Controller { // set new calendar to be visible set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1); + + build_sync_packet($channel['channel_id'], [ + 'calendar' => [ + 'action' => 'create', + 'uri' => $calendarUri, + 'properties' => $properties + ] + ]); } //create new calendar object via ajax request @@ -272,6 +354,8 @@ class Cdav extends Controller { if(!cdav_perms($id[0],$calendars,true)) return; + $cdavdata = $this->get_cdav_data($id[0], 'calendarinstances'); + $timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : ''); $tz = (($timezone) ? $timezone : date_default_timezone_get()); @@ -327,9 +411,17 @@ class Cdav extends Controller { $vcalendar->VEVENT->DTSTART['TZID'] = $tz; $calendarData = $vcalendar->serialize(); - $caldavBackend->createCalendarObject($id, $objectUri, $calendarData); + build_sync_packet($channel['channel_id'], [ + 'calendar' => [ + 'action' => 'import', + 'uri' => $cdavdata['uri'], + 'ids' => [ $objectUri ], + 'card' => $calendarData + ] + ]); + killme(); } @@ -341,17 +433,24 @@ class Cdav extends Controller { if(! cdav_perms($id[0],$calendars)) return; + $cdavdata = $this->get_cdav_data($id[0], 'calendarinstances'); + $mutations = [ '{DAV:}displayname' => $_REQUEST['{DAV:}displayname'], '{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color'] ]; $patch = new \Sabre\DAV\PropPatch($mutations); - $caldavBackend->updateCalendar($id, $patch); - $patch->commit(); + build_sync_packet($channel['channel_id'], [ + 'calendar' => [ + 'action' => 'edit', + 'uri' => $cdavdata['uri'], + 'mutations' => $mutations, + ] + ]); } //edit calendar object via ajax request @@ -359,9 +458,11 @@ class Cdav extends Controller { $id = explode(':', $_REQUEST['target']); - if(!cdav_perms($id[0],$calendars,true)) + if(! cdav_perms($id[0],$calendars,true)) return; + $cdavdata = $this->get_cdav_data($id[0], 'calendarinstances'); + $timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : ''); $tz = (($timezone) ? $timezone : date_default_timezone_get()); @@ -407,9 +508,17 @@ class Cdav extends Controller { $vcalendar->VEVENT->LOCATION = $location; $calendarData = $vcalendar->serialize(); - $caldavBackend->updateCalendarObject($id, $uri, $calendarData); + build_sync_packet($channel['channel_id'], [ + 'calendar' => [ + 'action' => 'update_card', + 'uri' => $cdavdata['uri'], + 'carduri' => $uri, + 'card' => $calendarData + ] + ]); + killme(); } @@ -418,13 +527,23 @@ class Cdav extends Controller { $id = explode(':', $_REQUEST['target']); - if(!cdav_perms($id[0],$calendars,true)) + if(! cdav_perms($id[0],$calendars,true)) return; + $cdavdata = $this->get_cdav_data($id[0], 'calendarinstances'); + $uri = $_REQUEST['uri']; $caldavBackend->deleteCalendarObject($id, $uri); + build_sync_packet($channel['channel_id'], [ + 'calendar' => [ + 'action' => 'delete_card', + 'uri' => $cdavdata['uri'], + 'carduri' => $uri + ] + ]); + killme(); } @@ -433,9 +552,11 @@ class Cdav extends Controller { $id = [$_REQUEST['id'][0], $_REQUEST['id'][1]]; - if(!cdav_perms($id[0],$calendars,true)) + if(! cdav_perms($id[0],$calendars,true)) return; + $cdavdata = $this->get_cdav_data($id[0], 'calendarinstances'); + $timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : ''); $tz = (($timezone) ? $timezone : date_default_timezone_get()); @@ -471,9 +592,17 @@ class Cdav extends Controller { unset($vcalendar->VEVENT->DTEND); $calendarData = $vcalendar->serialize(); - $caldavBackend->updateCalendarObject($id, $uri, $calendarData); + build_sync_packet($channel['channel_id'], [ + 'calendar' => [ + 'action' => 'update_card', + 'uri' => $cdavdata['uri'], + 'carduri' => $uri, + 'card' => $calendarData + ] + ]); + killme(); } @@ -523,6 +652,14 @@ class Cdav extends Controller { $properties = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname']]; $carddavBackend->createAddressBook($principalUri, $addressbookUri, $properties); + + build_sync_packet($channel['channel_id'], [ + 'addressbook' => [ + 'action' => 'create', + 'uri' => $addressbookUri, + 'properties' => $properties + ] + ]); } //edit addressbook @@ -533,21 +670,32 @@ class Cdav extends Controller { if(! cdav_perms($id,$addressbooks)) return; + $cdavdata = $this->get_cdav_data($id, 'addressbooks'); + $mutations = [ '{DAV:}displayname' => $_REQUEST['{DAV:}displayname'] ]; $patch = new \Sabre\DAV\PropPatch($mutations); - $carddavBackend->updateAddressBook($id, $patch); - $patch->commit(); + + build_sync_packet($channel['channel_id'], [ + 'addressbook' => [ + 'action' => 'edit', + 'uri' => $cdavdata['uri'], + 'mutations' => $mutations, + ] + ]); } //create addressbook card if($_REQUEST['create'] && $_REQUEST['target'] && $_REQUEST['fn']) { + $id = $_REQUEST['target']; + $cdavdata = $this->get_cdav_data($id, 'addressbooks'); + do { $duplicate = false; $uri = random_string(40) . '.vcf'; @@ -569,86 +717,21 @@ class Cdav extends Controller { 'N' => array_reverse(explode(' ', $fn)) ]); - $org = $_REQUEST['org']; - if($org) { - $vcard->ORG = $org; - } - - $title = $_REQUEST['title']; - if($title) { - $vcard->TITLE = $title; - } - - $tel = $_REQUEST['tel']; - $tel_type = $_REQUEST['tel_type']; - if($tel) { - $i = 0; - foreach($tel as $item) { - if($item) { - $vcard->add('TEL', $item, ['type' => $tel_type[$i]]); - } - $i++; - } - } + $fields = $this->request_to_array($_REQUEST); - $email = $_REQUEST['email']; - $email_type = $_REQUEST['email_type']; - if($email) { - $i = 0; - foreach($email as $item) { - if($item) { - $vcard->add('EMAIL', $item, ['type' => $email_type[$i]]); - } - $i++; - } - } - - $impp = $_REQUEST['impp']; - $impp_type = $_REQUEST['impp_type']; - if($impp) { - $i = 0; - foreach($impp as $item) { - if($item) { - $vcard->add('IMPP', $item, ['type' => $impp_type[$i]]); - } - $i++; - } - } - - $url = $_REQUEST['url']; - $url_type = $_REQUEST['url_type']; - if($url) { - $i = 0; - foreach($url as $item) { - if($item) { - $vcard->add('URL', $item, ['type' => $url_type[$i]]); - } - $i++; - } - } - - $adr = $_REQUEST['adr']; - $adr_type = $_REQUEST['adr_type']; - - if($adr) { - $i = 0; - foreach($adr as $item) { - if($item) { - $vcard->add('ADR', $item, ['type' => $adr_type[$i]]); - } - $i++; - } - } - - $note = $_REQUEST['note']; - if($note) { - $vcard->NOTE = $note; - } + process_cdav_card($fields, $vcard); $cardData = $vcard->serialize(); - $carddavBackend->createCard($id, $uri, $cardData); + build_sync_packet($channel['channel_id'], [ + 'addressbook' => [ + 'action' => 'import', + 'uri' => $cdavdata['uri'], + 'ids' => [ $uri ], + 'card' => $cardData + ] + ]); } //edit addressbook card @@ -656,9 +739,11 @@ class Cdav extends Controller { $id = $_REQUEST['target']; - if(!cdav_perms($id,$addressbooks)) + if(! cdav_perms($id,$addressbooks)) return; + $cdavdata = $this->get_cdav_data($id, 'addressbooks'); + $uri = $_REQUEST['uri']; $object = $carddavBackend->getCard($id, $uri); @@ -670,113 +755,23 @@ class Cdav extends Controller { $vcard->N = array_reverse(explode(' ', $fn)); } - $org = $_REQUEST['org']; - if($org) { - $vcard->ORG = $org; - } - else { - unset($vcard->ORG); - } - - $title = $_REQUEST['title']; - if($title) { - $vcard->TITLE = $title; - } - else { - unset($vcard->TITLE); - } - - $tel = $_REQUEST['tel']; - $tel_type = $_REQUEST['tel_type']; - if($tel) { - $i = 0; - unset($vcard->TEL); - foreach($tel as $item) { - if($item) { - $vcard->add('TEL', $item, ['type' => $tel_type[$i]]); - } - $i++; - } - } - else { - unset($vcard->TEL); - } - - $email = $_REQUEST['email']; - $email_type = $_REQUEST['email_type']; - if($email) { - $i = 0; - unset($vcard->EMAIL); - foreach($email as $item) { - if($item) { - $vcard->add('EMAIL', $item, ['type' => $email_type[$i]]); - } - $i++; - } - } - else { - unset($vcard->EMAIL); - } - - $impp = $_REQUEST['impp']; - $impp_type = $_REQUEST['impp_type']; - if($impp) { - $i = 0; - unset($vcard->IMPP); - foreach($impp as $item) { - if($item) { - $vcard->add('IMPP', $item, ['type' => $impp_type[$i]]); - } - $i++; - } - } - else { - unset($vcard->IMPP); - } - - $url = $_REQUEST['url']; - $url_type = $_REQUEST['url_type']; - if($url) { - $i = 0; - unset($vcard->URL); - foreach($url as $item) { - if($item) { - $vcard->add('URL', $item, ['type' => $url_type[$i]]); - } - $i++; - } - } - else { - unset($vcard->URL); - } - - $adr = $_REQUEST['adr']; - $adr_type = $_REQUEST['adr_type']; - if($adr) { - $i = 0; - unset($vcard->ADR); - foreach($adr as $item) { - if($item) { - $vcard->add('ADR', $item, ['type' => $adr_type[$i]]); - } - $i++; - } - } - else { - unset($vcard->ADR); - } + $fields = $this->request_to_array($_REQUEST); - $note = $_REQUEST['note']; - if($note) { - $vcard->NOTE = $note; - } - else { - unset($vcard->NOTE); - } + process_cdav_card($fields, $vcard, true); $cardData = $vcard->serialize(); $carddavBackend->updateCard($id, $uri, $cardData); + + build_sync_packet($channel['channel_id'], [ + 'addressbook' => [ + 'action' => 'update_card', + 'uri' => $cdavdata['uri'], + 'carduri' => $uri, + 'card' => $cardData + ] + ]); + } //delete addressbook card @@ -784,12 +779,22 @@ class Cdav extends Controller { $id = $_REQUEST['target']; - if(!cdav_perms($id,$addressbooks)) + if(! cdav_perms($id,$addressbooks)) return; + $cdavdata = $this->get_cdav_data($id, 'addressbooks'); + $uri = $_REQUEST['uri']; $carddavBackend->deleteCard($id, $uri); + + build_sync_packet($channel['channel_id'], [ + 'addressbook' => [ + 'action' => 'delete_card', + 'uri' => $cdavdata['uri'], + 'carduri' => $uri + ] + ]); } } @@ -799,6 +804,8 @@ class Cdav extends Controller { $src = $_FILES['userfile']['tmp_name']; if($src) { + + $carddata = @file_get_contents($src); if($_REQUEST['c_upload']) { if($_REQUEST['target'] == 'channel_calendar') { @@ -816,72 +823,38 @@ class Cdav extends Controller { $ext = 'ics'; $table = 'calendarobjects'; $column = 'calendarid'; - $objects = new \Sabre\VObject\Splitter\ICalendar(@file_get_contents($src)); + $sync = 'calendar'; + $objects = new \Sabre\VObject\Splitter\ICalendar($carddata); $profile = \Sabre\VObject\Node::PROFILE_CALDAV; $backend = new \Sabre\CalDAV\Backend\PDO($pdo); + + $cdavdata = $this->get_cdav_data($id, 'calendarinstances'); } if($_REQUEST['a_upload']) { - $id[] = intval($_REQUEST['target']); + $id = intval($_REQUEST['target']); $ext = 'vcf'; $table = 'cards'; $column = 'addressbookid'; - $objects = new \Sabre\VObject\Splitter\VCard(@file_get_contents($src)); + $sync = 'addressbook'; + $objects = new \Sabre\VObject\Splitter\VCard($carddata); $profile = \Sabre\VObject\Node::PROFILE_CARDDAV; $backend = new \Sabre\CardDAV\Backend\PDO($pdo); + + $cdavdata = $this->get_cdav_data($id, 'addressbooks'); } - - while ($object = $objects->getNext()) { - - if($_REQUEST['a_upload']) { - $object = $object->convert(\Sabre\VObject\Document::VCARD40); - } - - $ret = $object->validate($profile & \Sabre\VObject\Node::REPAIR); - - //level 3 Means that the document is invalid, - //level 2 means a warning. A warning means it's valid but it could cause interopability issues, - //level 1 means that there was a problem earlier, but the problem was automatically repaired. - - if($ret[0]['level'] < 3) { - do { - $duplicate = false; - $objectUri = random_string(40) . '.' . $ext; - - $r = q("SELECT uri FROM $table WHERE $column = %d AND uri = '%s' LIMIT 1", - dbesc($id[0]), - dbesc($objectUri) - ); - - if (count($r)) - $duplicate = true; - } while ($duplicate == true); - - if($_REQUEST['c_upload']) { - $backend->createCalendarObject($id, $objectUri, $object->serialize()); - } - - if($_REQUEST['a_upload']) { - $backend->createCard($id[0], $objectUri, $object->serialize()); - } - } - else { - if($_REQUEST['c_upload']) { - notice( '<strong>' . t('INVALID EVENT DISMISSED!') . '</strong>' . EOL . - '<strong>' . t('Summary: ') . '</strong>' . (($object->VEVENT->SUMMARY) ? $object->VEVENT->SUMMARY : t('Unknown')) . EOL . - '<strong>' . t('Date: ') . '</strong>' . (($object->VEVENT->DTSTART) ? $object->VEVENT->DTSTART : t('Unknown')) . EOL . - '<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL - ); - } - - if($_REQUEST['a_upload']) { - notice( '<strong>' . t('INVALID CARD DISMISSED!') . '</strong>' . EOL . - '<strong>' . t('Name: ') . '</strong>' . (($object->FN) ? $object->FN : t('Unknown')) . EOL . - '<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL - ); - } - } - } + + $ids = []; + import_cdav_card($id, $ext, $table, $column, $objects, $profile, $backend, $ids, true); + + build_sync_packet($channel['channel_id'], [ + $sync => [ + 'action' => 'import', + 'uri' => $cdavdata['uri'], + 'ids' => $ids, + 'card' => $carddata + ] + ]); } @unlink($src); } @@ -1190,7 +1163,18 @@ class Cdav extends Controller { if(! cdav_perms($id,$calendars)) killme(); - set_pconfig(local_channel(), 'cdav_calendar' , argv(3), argv(4)); + $cdavdata = $this->get_cdav_data($id, 'calendarinstances'); + + set_pconfig(local_channel(), 'cdav_calendar', $id, argv(4)); + + build_sync_packet(local_channel(), [ + 'calendar' => [ + 'action' => 'switch', + 'uri' => $cdavdata['uri'], + 'switch' => intval(argv(4)) + ] + ]); + killme(); } @@ -1201,7 +1185,18 @@ class Cdav extends Controller { if(! cdav_perms($id[0],$calendars)) killme(); + // get metadata before we delete it + $cdavdata = $this->get_cdav_data($id[0], 'calendarinstances'); + $caldavBackend->deleteCalendar($id); + + build_sync_packet($channel['channel_id'], [ + 'calendar' => [ + 'action' => 'drop', + 'uri' => $cdavdata['uri'] + ] + ]); + killme(); } @@ -1408,7 +1403,19 @@ class Cdav extends Controller { if(! cdav_perms($id,$addressbooks)) return; + // get metadata before we delete it + $cdavdata = $this->get_cdav_data($id, 'addressbooks'); + $carddavBackend->deleteAddressBook($id); + + if($cdavdata) + build_sync_packet($channel['channel_id'], [ + 'addressbook' => [ + 'action' => 'drop', + 'uri' => $cdavdata['uri'] + ] + ]); + killme(); } @@ -1460,4 +1467,36 @@ class Cdav extends Controller { } + function get_cdav_data($id, $table) { + + $r = q("SELECT * FROM $table WHERE id = %d LIMIT 1", + intval($id) + ); + + if(! $r) + return false; + + return $r[0]; + } + + function request_to_array($req) { + + $f = []; + + $f['org'] = $req['org']; + $f['title'] = $req['title']; + $f['tel'] = $req['tel']; + $f['tel_type'] = $req['tel_type']; + $f['email'] = $req['email']; + $f['email_type'] = $req['email_type']; + $f['impp'] = $req['impp']; + $f['impp_type'] = $req['impp_type']; + $f['url'] = $req['url']; + $f['url_type'] = $req['url_type']; + $f['adr'] = $req['adr']; + $f['adr_type'] = $req['adr_type']; + $f['note'] = $req['note']; + + return $f; + } } diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index d975ac1bf..307be048a 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -239,8 +239,12 @@ class Channel extends Controller { /** * Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups */ - - $item_normal = item_normal(); + + $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0 + and item.item_unpublished = 0 and item.item_pending_remove = 0 + and item.item_blocked = 0 "; + if (! $is_owner) + $item_normal .= "and item.item_delayed = 0 "; $item_normal_update = item_normal_update(); $sql_extra = item_permissions_sql(App::$profile['profile_uid']); @@ -330,7 +334,7 @@ class Channel extends Controller { $itemspage = get_pconfig(local_channel(),'system','itemspage'); - App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10)); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); if($noscript_content || $load) { @@ -419,6 +423,7 @@ class Channel extends Controller { '$nouveau' => '0', '$wall' => '1', '$fh' => '0', + '$dm' => '0', '$static' => $static, '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), '$search' => $search, @@ -437,36 +442,11 @@ class Channel extends Controller { } - $update_unseen = ''; - - if($page_mode === 'list') { - - /** - * in "list mode", only mark the parent item and any like activities as "seen". - * We won't distinguish between comment likes and post likes. The important thing - * is that the number of unseen comments will be accurate. The SQL to separate the - * comment likes could also get somewhat hairy. - */ - - if($parents_str) { - $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; - $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; - } - } - else { - if($parents_str) { - $update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )"; - } - } - - if($is_owner && $update_unseen) { - $x = [ 'channel_id' => local_channel(), 'update' => 'unset' ]; - call_hooks('update_unseen',$x); - if($x['update'] === 'unset' || intval($x['update'])) { - $r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d $update_unseen", - intval(local_channel()) - ); - } + // Add pinned content + if(! x($_REQUEST,'mid') && ! $search) { + $pinned = new \Zotlabs\Widget\Pinned; + $r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]); + $o .= $r['html']; } $mode = (($search) ? 'search' : 'channel'); diff --git a/Zotlabs/Module/Channel_calendar.php b/Zotlabs/Module/Channel_calendar.php index 7d75a7e41..ae4afb2f3 100644 --- a/Zotlabs/Module/Channel_calendar.php +++ b/Zotlabs/Module/Channel_calendar.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + require_once('include/conversation.php'); require_once('include/bbcode.php'); require_once('include/datetime.php'); @@ -16,7 +18,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller { if(! local_channel()) return; - + $event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0); $event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : ''); @@ -27,15 +29,19 @@ class Channel_calendar extends \Zotlabs\Web\Controller { if(($xchan) && ($xchan !== get_observer_hash())) return; - $timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : ''); - $tz = (($timezone) ? $timezone : date_default_timezone_get()); - $categories = escape_tags(trim($_POST['categories'])); + // allday events have adjust = 0, normal events have adjust = 1 $adjust = intval($_POST['adjust']); - $start = datetime_convert('UTC', 'UTC', escape_tags($_REQUEST['dtstart'])); - $finish = datetime_convert('UTC', 'UTC', escape_tags($_REQUEST['dtend'])); + $start = datetime_convert((($adjust) ? $tz : 'UTC'), 'UTC', escape_tags($_REQUEST['dtstart'])); + $finish = datetime_convert((($adjust) ? $tz : 'UTC'), 'UTC', escape_tags($_REQUEST['dtend'])); + + $timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : ''); + $tz = (($timezone) ? $timezone : date_default_timezone_get()); + + if(! $adjust) + $tz = 'UTC'; $summary = escape_tags(trim($_POST['summary'])); $desc = escape_tags(trim($_POST['desc'])); @@ -184,7 +190,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller { intval($channel['channel_id']) ); if($z) { - build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z)); + Libsync::build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z)); } } } @@ -337,21 +343,16 @@ class Channel_calendar extends \Zotlabs\Web\Controller { } $events = []; - + if($r) { foreach($r as $rr) { - $tz = get_iconfig($rr, 'event', 'timezone'); - - if(! $tz) - $tz = 'UTC'; - - $start = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c')); + $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($tz, date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c')); + $end = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c')); } $catsenabled = feature_enabled(local_channel(),'categories'); @@ -371,6 +372,11 @@ class Channel_calendar extends \Zotlabs\Web\Controller { $drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'',''); + $tz = get_iconfig($rr, 'event', 'timezone'); + + if(! $tz) + $tz = 'UTC'; + $events[] = array( 'calendar_id' => 'channel_calendar', 'rw' => true, @@ -426,7 +432,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller { if($r) { $sync_event['event_deleted'] = 1; - build_sync_packet(0,array('event' => array($sync_event))); + Libsync::build_sync_packet(0,array('event' => array($sync_event))); $i = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d", dbesc($event_id), @@ -475,7 +481,7 @@ class Channel_calendar extends \Zotlabs\Web\Controller { if($ii) { xchan_query($ii); $sync_item = fetch_post_tags($ii); - build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true)))); + Libsync::build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true)))); } if($complex) { diff --git a/Zotlabs/Module/Chanview.php b/Zotlabs/Module/Chanview.php index 2e653d030..12e1891d4 100644 --- a/Zotlabs/Module/Chanview.php +++ b/Zotlabs/Module/Chanview.php @@ -1,31 +1,35 @@ <?php namespace Zotlabs\Module; -require_once('include/zot.php'); +use App; +use Zotlabs\Lib\Libzot; +use Zotlabs\Lib\Webfinger; +use Zotlabs\Lib\Zotfinger; + class Chanview extends \Zotlabs\Web\Controller { function get() { - $observer = \App::get_observer(); + $observer = App::get_observer(); $xchan = null; $r = null; if($_REQUEST['hash']) { - $r = q("select * from xchan where xchan_hash = '%s' limit 1", + $r = q("select * from xchan where xchan_hash = '%s'", dbesc($_REQUEST['hash']) ); } if($_REQUEST['address']) { - $r = q("select * from xchan where xchan_addr = '%s' limit 1", + $r = q("select * from xchan where xchan_addr = '%s'", dbesc(punify($_REQUEST['address'])) ); } elseif(local_channel() && intval($_REQUEST['cid'])) { $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", intval(local_channel()), intval($_REQUEST['cid']) ); @@ -35,12 +39,12 @@ class Chanview extends \Zotlabs\Web\Controller { // 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 limit 1", + $r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc", dbesc($_REQUEST['url']) ); } if($r) { - \App::$poi = $r[0]; + App::$poi = Libzot::zot_record_preferred($r, 'xchan_network'); } @@ -49,74 +53,63 @@ class Chanview extends \Zotlabs\Web\Controller { // 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) { + if(! App::$poi) { logger('mod_chanview: fallback'); - // This is hackish - construct a zot address from the url - if($_REQUEST['url']) { - if(preg_match('/https?\:\/\/(.*?)(\/channel\/|\/profile\/)(.*?)$/ism',$_REQUEST['url'],$matches)) { - $_REQUEST['address'] = $matches[3] . '@' . $matches[1]; + + if($_REQUEST['address']) { + $href = Webfinger::zot_url(punify($_REQUEST['address'])); + if($href) { + $_REQUEST['url'] = $href; } - logger('mod_chanview: constructed address ' . print_r($matches,true)); } $r = null; - if($_REQUEST['address']) { - $j = \Zotlabs\Zot\Finger::run($_REQUEST['address'],null); - if($j['success']) { - import_xchan($j); - $r = q("select * from xchan where xchan_addr = '%s' limit 1", - dbesc($_REQUEST['address']) + if($_REQUEST['url']) { + + $zf = Zotfinger::exec($_REQUEST['url'], null); + + if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $_REQUEST['url'] && intval($zf['signature']['header_valid'])) { + Libzot::import_xchan($j); + $r = q("select * from xchan where xchan_url = '%s'", + dbesc($_REQUEST['url']) ); if($r) { - \App::$poi = $r[0]; + App::$poi = Libzot::zot_record_preferred($r, 'xchan_network'); } } if(! $r) { - if(discover_by_webbie($_REQUEST['address'])) { - $r = q("select * from xchan where xchan_addr = '%s' limit 1", - dbesc($_REQUEST['address']) + if(discover_by_webbie($_REQUEST['url'])) { + $r = q("select * from xchan where xchan_url = '%s'", + dbesc($_REQUEST['url']) ); if($r) { - \App::$poi = $r[0]; + App::$poi = Libzot::zot_record_preferred($r, 'xchan_network'); } } } } } - if(! \App::$poi) { - - // We don't know who this is, and we can't figure it out from the URL - // On the plus side, there's a good chance we know somebody else at that - // hub so sending them there with a Zid will probably work anyway. - - $url = ($_REQUEST['url']); - if(! $url) { - notice( t('Channel not found.') . EOL); - return; - } - if($observer) - $url = zid($url); - + if(! App::$poi) { + notice( t('Channel not found.') . EOL); + return; } $is_zot = false; $connected = false; - if (\App::$poi) { - $url = \App::$poi['xchan_url']; - if(in_array(\App::$poi['xchan_network'], ['zot', 'zot6'])) { - $is_zot = true; - } - if(local_channel()) { - $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1", - intval(local_channel()), - dbesc(\App::$poi['xchan_hash']) - ); - if($c) - $connected = true; - } + $url = App::$poi['xchan_url']; + if(in_array(App::$poi['xchan_network'], ['zot', 'zot6'])) { + $is_zot = true; + } + if(local_channel()) { + $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1", + intval(local_channel()), + dbesc(App::$poi['xchan_hash']) + ); + if($c) + $connected = true; } // We will load the chanview template if it's a foreign network, diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index db77e2612..28e775f9d 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -7,9 +7,7 @@ use Zotlabs\Lib\Apps; use Zotlabs\Web\Controller; use Zotlabs\Lib\Chatroom; use Zotlabs\Access\AccessList; - - - +use Zotlabs\Lib\Libsync; require_once('include/bookmarks.php'); @@ -80,7 +78,7 @@ class Chat extends Controller { intval(local_channel()) ); - build_sync_packet(0, array('chatroom' => $x)); + Libsync::build_sync_packet(0, array('chatroom' => $x)); if($x) goaway(z_root() . '/chat/' . $channel['channel_address'] . '/' . $x[0]['cr_id']); @@ -199,7 +197,7 @@ class Chat extends Controller { $cipher = get_pconfig(local_channel(),'system','default_cipher'); if(! $cipher) - $cipher = 'aes256'; + $cipher = 'AES-128-CCM'; $o = replace_macros(get_markup_template('chat.tpl'),array( diff --git a/Zotlabs/Module/Connect.php b/Zotlabs/Module/Connect.php index 62d3af840..31da42035 100644 --- a/Zotlabs/Module/Connect.php +++ b/Zotlabs/Module/Connect.php @@ -28,10 +28,6 @@ class Connect extends Controller { $channel_id = App::$data['channel']['channel_id']; - if(! Apps::system_app_installed($channel_id, 'Premium Channel')) { - return; - } - profile_load($which,''); } @@ -42,10 +38,6 @@ class Connect extends Controller { $channel_id = App::$data['channel']['channel_id']; - if(! Apps::system_app_installed($channel_id, 'Premium Channel')) { - return; - } - $edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false); if($edit) { @@ -97,15 +89,6 @@ class Connect extends Controller { $channel_id = App::$data['channel']['channel_id']; - if(! Apps::system_app_installed($channel_id, 'Premium Channel')) { - //Do not display any associated widgets at this point - App::$pdl = ''; - - $o = '<b>' . t('Premium Channel App') . ' (' . t('Not Installed') . '):</b><br>'; - $o .= t('Allows you to set restrictions and terms on those that connect with your channel'); - return $o; - } - $edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false); $text = get_pconfig($channel_id,'system','selltext'); diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index f6133d5f8..7dc301623 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -34,7 +34,7 @@ class Connections extends \Zotlabs\Web\Controller { } nav_set_selected('Connections'); - + $active = false; $blocked = false; $hidden = false; @@ -283,6 +283,28 @@ class Connections extends \Zotlabs\Web\Controller { if(! intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_comments'))) { $oneway = true; } + + $perminfo['connpermcount']=0; + $perminfo['connperms']=t('Accepts').': '; + if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_comments'))) { + $perminfo['connpermcount']++; + $perminfo['connperms'] .= t('Comments'); + } + if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','send_stream'))) { + $perminfo['connpermcount']++; + $perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ; + $perminfo['connperms'] .= t('Stream items'); + } + if(intval(get_abconfig(local_channel(),$rr['xchan_hash'],'their_perms','post_wall'))) { + $perminfo['connpermcount']++; + $perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ; + $perminfo['connperms'] .= t('Wall posts'); + } + + if ($perminfo['connpermcount'] == 0) { + $perminfo['connperms'] .= t('Nothing'); + } + foreach($status as $str) { if(!$str) @@ -323,6 +345,7 @@ class Connections extends \Zotlabs\Web\Controller { 'recent_label' => t('Recent activity'), 'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']) . '&name=' . $rr['xchan_name'], 'oneway' => $oneway, + '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') diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index acd7cb769..0fc807d42 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -7,8 +7,16 @@ namespace Zotlabs\Module; * */ +use App; 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; require_once('include/socgraph.php'); require_once('include/selectors.php'); @@ -16,7 +24,7 @@ require_once('include/group.php'); require_once('include/photos.php'); -class Connedit extends \Zotlabs\Web\Controller { +class Connedit extends Controller { /* @brief Initialize the connection-editor * @@ -36,12 +44,12 @@ class Connedit extends \Zotlabs\Web\Controller { intval(argv(1)) ); if($r) { - \App::$poi = array_shift($r); + App::$poi = array_shift($r); } } - $channel = \App::get_channel(); + $channel = App::get_channel(); if($channel) head_set_icon($channel['xchan_photo_s']); @@ -61,7 +69,7 @@ class Connedit extends \Zotlabs\Web\Controller { if(! $contact_id) return; - $channel = \App::get_channel(); + $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 @@ -140,7 +148,7 @@ class Connedit extends \Zotlabs\Web\Controller { $rating_text = trim(escape_tags($_REQUEST['rating_text'])); - $all_perms = \Zotlabs\Access\Permissions::Perms(); + $all_perms = Permissions::Perms(); if($all_perms) { foreach($all_perms as $perm => $desc) { @@ -212,7 +220,7 @@ class Connedit extends \Zotlabs\Web\Controller { $record = $z[0]['xlink_id']; } if($record) { - \Zotlabs\Daemon\Master::Summon(array('Ratenotif','rating',$record)); + Master::Summon(array('Ratenotif','rating',$record)); } } @@ -227,7 +235,7 @@ class Connedit extends \Zotlabs\Web\Controller { // request. The workaround is to approve the connection, then go back and // adjust permissions as desired. - $p = \Zotlabs\Access\Permissions::connect_perms(local_channel()); + $p = Permissions::connect_perms(local_channel()); $my_perms = $p['perms']; if($my_perms) { foreach($my_perms as $k => $v) { @@ -257,12 +265,12 @@ class Connedit extends \Zotlabs\Web\Controller { else notice( t('Failed to update connection record.') . EOL); - if(! intval(\App::$poi['abook_self'])) { + if(! intval(App::$poi['abook_self'])) { if($new_friend) { - \Zotlabs\Daemon\Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] ); + Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] ); } - \Zotlabs\Daemon\Master::Summon( [ + Master::Summon( [ 'Notifier', (($new_friend) ? 'permission_create' : 'permission_update'), $contact_id @@ -275,7 +283,7 @@ class Connedit extends \Zotlabs\Web\Controller { 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']); + group_add_member(local_channel(),'',App::$poi['abook_xchan'],$g['id']); } // Check if settings permit ("post new friend activity" is allowed, and @@ -299,19 +307,19 @@ class Connedit extends \Zotlabs\Web\Controller { $xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0); $obj = array( 'type' => ACTIVITY_OBJ_PERSON, - 'title' => \App::$poi['xchan_name'], - 'id' => \App::$poi['xchan_hash'], + 'title' => App::$poi['xchan_name'], + 'id' => App::$poi['xchan_hash'], 'link' => array( - array('rel' => 'alternate', 'type' => 'text/html', 'href' => \App::$poi['xchan_url']), - array('rel' => 'photo', 'type' => \App::$poi['xchan_photo_mimetype'], 'href' => \App::$poi['xchan_photo_l']) + array('rel' => 'alternate', 'type' => 'text/html', 'href' => App::$poi['xchan_url']), + array('rel' => 'photo', 'type' => App::$poi['xchan_photo_mimetype'], 'href' => App::$poi['xchan_photo_l']) ), ); $xarr['obj'] = json_encode($obj); $xarr['obj_type'] = ACTIVITY_OBJ_PERSON; - $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]'; + $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]'; - $xarr['body'] .= "\n\n\n" . '[zrl=' . \App::$poi['xchan_url'] . '][zmg=80x80]' . \App::$poi['xchan_photo_m'] . '[/zmg][/zrl]'; + $xarr['body'] .= "\n\n\n" . '[zrl=' . App::$poi['xchan_url'] . '][zmg=80x80]' . App::$poi['xchan_photo_m'] . '[/zmg][/zrl]'; post_activity_item($xarr); @@ -319,7 +327,7 @@ class Connedit extends \Zotlabs\Web\Controller { // pull in a bit of content if there is any to pull in - \Zotlabs\Daemon\Master::Summon(array('Onepoll',$contact_id)); + Master::Summon(array('Onepoll',$contact_id)); } @@ -332,11 +340,11 @@ class Connedit extends \Zotlabs\Web\Controller { intval($contact_id) ); if($r) { - \App::$poi = $r[0]; + App::$poi = $r[0]; } if($new_friend) { - $arr = array('channel_id' => local_channel(), 'abook' => \App::$poi); + $arr = array('channel_id' => local_channel(), 'abook' => App::$poi); call_hooks('accept_follow', $arr); } @@ -356,23 +364,23 @@ class Connedit extends \Zotlabs\Web\Controller { function connedit_clone(&$a) { - if(! \App::$poi) + if(! App::$poi) return; - $channel = \App::get_channel(); + $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", intval(local_channel()), - intval(\App::$poi['abook_id']) + intval(App::$poi['abook_id']) ); if($r) { - \App::$poi = array_shift($r); + App::$poi = array_shift($r); } - $clone = \App::$poi; + $clone = App::$poi; unset($clone['abook_id']); unset($clone['abook_account']); @@ -382,7 +390,7 @@ class Connedit extends \Zotlabs\Web\Controller { if($abconfig) $clone['abconfig'] = $abconfig; - build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone))); + Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone))); } /* @brief Generate content of connection edit page @@ -401,11 +409,11 @@ class Connedit extends \Zotlabs\Web\Controller { } $section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : ''); - $channel = \App::get_channel(); + $channel = App::get_channel(); $yes_no = array(t('No'),t('Yes')); - $connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel()); + $connect_perms = Permissions::connect_perms(local_channel()); $o .= "<script>function connectDefaultShare() { \$('.abook-edit-me').each(function() { @@ -426,7 +434,7 @@ class Connedit extends \Zotlabs\Web\Controller { 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", intval($contact_id), @@ -440,7 +448,7 @@ class Connedit extends \Zotlabs\Web\Controller { if($cmd === 'update') { // pull feed and consume it, which should subscribe to the hub. - \Zotlabs\Daemon\Master::Summon(array('Poller',$contact_id)); + Master::Summon(array('Poller',$contact_id)); goaway(z_root() . '/connedit/' . $contact_id); } @@ -450,7 +458,7 @@ class Connedit extends \Zotlabs\Web\Controller { $recurse = 0; $x = z_fetch_url(zid($url),false,$recurse,['session' => true]); if($x['success']) { - $h = new \Zotlabs\Web\HTTPHeaders($x['header']); + $h = new HTTPHeaders($x['header']); $fields = $h->fetch(); if($fields) { foreach($fields as $y) { @@ -481,17 +489,17 @@ class Connedit extends \Zotlabs\Web\Controller { if($cmd === 'refresh') { if($orig_record[0]['xchan_network'] === 'zot') { - if(! zot_refresh($orig_record[0],\App::get_channel())) + 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())) + 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 - \Zotlabs\Daemon\Master::Summon(array('Notifier','permission_update',$contact_id)); + Master::Summon(array('Notifier','permission_update',$contact_id)); } goaway(z_root() . '/connedit/' . $contact_id); } @@ -549,16 +557,11 @@ class Connedit extends \Zotlabs\Web\Controller { if($cmd === 'drop') { - - // @FIXME - // We need to send either a purge or a refresh packet to the other side (the channel being unfriended). - // The issue is that the abook DB record _may_ get destroyed when we call contact_remove. As the notifier - // runs in the background there could be a race condition preventing this packet from being sent in all - // cases. - // PLACEHOLDER - contact_remove(local_channel(), $orig_record[0]['abook_id']); - build_sync_packet(0 /* use the current local_channel */, + + 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)) @@ -573,13 +576,13 @@ class Connedit extends \Zotlabs\Web\Controller { } } - if(\App::$poi) { + if(App::$poi) { $abook_prev = 0; $abook_next = 0; - $contact_id = \App::$poi['abook_id']; - $contact = \App::$poi; + $contact_id = App::$poi['abook_id']; + $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()) @@ -787,9 +790,9 @@ class Connedit extends \Zotlabs\Web\Controller { $perms = array(); - $channel = \App::get_channel(); + $channel = App::get_channel(); - $global_perms = \Zotlabs\Access\Permissions::Perms(); + $global_perms = Permissions::Perms(); $existing = get_all_perms(local_channel(),$contact['abook_xchan'],false); @@ -821,7 +824,7 @@ class Connedit extends \Zotlabs\Web\Controller { $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k); //fixme - $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k); + $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 @@ -834,7 +837,7 @@ class Connedit extends \Zotlabs\Web\Controller { $perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited); } - $pcat = new \Zotlabs\Lib\Permcat(local_channel()); + $pcat = new Permcat(local_channel()); $pcatlist = $pcat->listing(); $permcats = []; if($pcatlist) { diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php index d97014f9c..dff645f2b 100644 --- a/Zotlabs/Module/Cover_photo.php +++ b/Zotlabs/Module/Cover_photo.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + /* @file cover_photo.php @brief Module-file with functions for handling of cover-photos @@ -66,7 +68,7 @@ class Cover_photo extends \Zotlabs\Web\Controller { $sync = attach_export_data($channel,$r[0]['resource_id']); if($sync) - build_sync_packet($channel['channel_id'],array('file' => array($sync))); + Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); } // Update directory in background @@ -230,7 +232,7 @@ class Cover_photo extends \Zotlabs\Web\Controller { $sync = attach_export_data($channel,$base_image['resource_id']); if($sync) - build_sync_packet($channel['channel_id'],array('file' => array($sync))); + Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); // Update directory in background \Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id'])); @@ -291,14 +293,6 @@ class Cover_photo extends \Zotlabs\Web\Controller { $arr['item_thread_top'] = 1; $arr['item_origin'] = 1; $arr['item_wall'] = 1; - $arr['obj_type'] = ACTIVITY_OBJ_PHOTO; - $arr['verb'] = ACTIVITY_UPDATE; - - $arr['obj'] = json_encode(array( - 'type' => $arr['obj_type'], - 'id' => z_root() . '/photo/' . $photo['resource_id'] . '-7', - 'link' => array('rel' => 'photo', 'type' => $photo['mimetype'], 'href' => z_root() . '/photo/' . $photo['resource_id'] . '-7') - )); if($profile && stripos($profile['gender'],t('female')) !== false) $t = t('%1$s updated her %2$s'); diff --git a/Zotlabs/Module/Dav.php b/Zotlabs/Module/Dav.php index e8ce6a703..adab25e45 100644 --- a/Zotlabs/Module/Dav.php +++ b/Zotlabs/Module/Dav.php @@ -95,7 +95,7 @@ class Dav extends \Zotlabs\Web\Controller { $auth = new \Zotlabs\Storage\BasicAuth(); - $auth->observer = get_observer_hash(); + // $auth->observer = get_observer_hash(); $auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV'); diff --git a/Zotlabs/Module/Defperms.php b/Zotlabs/Module/Defperms.php index 463ecb57a..f2f7c10e5 100644 --- a/Zotlabs/Module/Defperms.php +++ b/Zotlabs/Module/Defperms.php @@ -4,6 +4,7 @@ namespace Zotlabs\Module; use App; use Zotlabs\Lib\Apps; use Zotlabs\Web\Controller; +use Zotlabs\Lib\Libsync; require_once('include/socgraph.php'); require_once('include/selectors.php'); @@ -164,7 +165,7 @@ class Defperms extends Controller { if($abconfig) $clone['abconfig'] = $abconfig; - build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone))); + Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone))); } /* @brief Generate content of connection default permissions page diff --git a/Zotlabs/Module/Dircensor.php b/Zotlabs/Module/Dircensor.php new file mode 100644 index 000000000..0fa65e948 --- /dev/null +++ b/Zotlabs/Module/Dircensor.php @@ -0,0 +1,52 @@ +<?php + +namespace Zotlabs\Module; + +use App; +use Zotlabs\Web\Controller; + + +class Dircensor extends Controller { + + function get() { + if(! is_site_admin()) { + return; + } + + $dirmode = intval(get_config('system','directory_mode')); + + if (! ($dirmode == DIRECTORY_MODE_PRIMARY || $dirmode == DIRECTORY_MODE_STANDALONE)) { + return; + } + + $xchan = argv(1); + if(! $xchan) { + return; + } + + $r = q("select * from xchan where xchan_hash = '%s'", + dbesc($xchan) + ); + + if(! $r) { + return; + } + + $val = (($r[0]['xchan_censored']) ? 0 : 1); + + q("update xchan set xchan_censored = $val where xchan_hash = '%s'", + dbesc($xchan) + ); + + if($val) { + info( t('Entry censored') . EOL); + } + else { + info( t('Entry uncensored') . EOL); + } + + goaway(z_root() . '/directory'); + + } + +} diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php index b043cea40..e1bf0f6cf 100644 --- a/Zotlabs/Module/Directory.php +++ b/Zotlabs/Module/Directory.php @@ -2,15 +2,19 @@ namespace Zotlabs\Module; +use App; +use Zotlabs\Web\Controller; + require_once('include/socgraph.php'); require_once('include/dir_fns.php'); require_once('include/bbcode.php'); +require_once('include/html2plain.php'); -class Directory extends \Zotlabs\Web\Controller { +class Directory extends Controller { function init() { - \App::set_pager_itemspage(60); + App::set_pager_itemspage(30); if(local_channel() && x($_GET,'ignore')) { q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ", @@ -21,7 +25,7 @@ class Directory extends \Zotlabs\Web\Controller { } if(local_channel()) - \App::$profile_uid = local_channel(); + App::$profile_uid = local_channel(); $observer = get_observer_hash(); $global_changed = false; @@ -140,9 +144,15 @@ class Directory extends \Zotlabs\Web\Controller { $dirmode = intval(get_config('system','directory_mode')); + $directory_admin = false; + if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) { $url = z_root() . '/dirsearch'; - } + if (is_site_admin()) { + $directory_admin = true; + } + } + if(! $url) { $directory = find_upstream_directory($dirmode); if((! $directory) || (! array_key_exists('url',$directory)) || (! $directory['url'])) @@ -182,7 +192,7 @@ class Directory extends \Zotlabs\Web\Controller { $query .= '&t=' . $token; if(! $globaldir) - $query .= '&hub=' . \App::get_hostname(); + $query .= '&hub=' . App::get_hostname(); if($search) $query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search); @@ -204,8 +214,8 @@ class Directory extends \Zotlabs\Web\Controller { if($sort_order) $query .= '&order=' . urlencode($sort_order); - if(\App::$pager['page'] != 1) - $query .= '&p=' . \App::$pager['page']; + if(App::$pager['page'] != 1) + $query .= '&p=' . App::$pager['page']; logger('mod_directory: query: ' . $query); @@ -283,12 +293,15 @@ class Directory extends \Zotlabs\Web\Controller { $marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False); $homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False); - $homepageurl = ((x($profile,'homepage') == 1) ? $profile['homepage'] : ''); + $homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : ''); - $hometown = ((x($profile,'hometown') == 1) ? $profile['hometown'] : False); + $hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False); $about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False); - + if ($about && $safe_mode) { + $about = html2plain($about); + } + $keywords = ((x($profile,'keywords')) ? $profile['keywords'] : ''); @@ -343,9 +356,11 @@ class Directory extends \Zotlabs\Web\Controller { 'canrate' => (($rating_enabled && local_channel()) ? true : false), 'pdesc' => $pdesc, 'pdesc_label' => t('Description:'), + 'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] : ''), + 'censor_label' => (($rr['censored']) ? t('Uncensor') : t('Censor')), 'marital' => $marital, 'homepage' => $homepage, - 'homepageurl' => linkify($homepageurl, true), + 'homepageurl' => (($safe_mode) ? $homepageurl : linkify($homepageurl)), 'hometown' => $hometown, 'hometown_label' => t('Hometown:'), 'about' => $about, @@ -387,7 +402,7 @@ class Directory extends \Zotlabs\Web\Controller { ksort($entries); // Sort array by key so that foreach-constructs work as expected if($j['keywords']) { - \App::$data['directory_keywords'] = $j['keywords']; + App::$data['directory_keywords'] = $j['keywords']; } logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA); @@ -438,7 +453,7 @@ class Directory extends \Zotlabs\Web\Controller { echo $o; killme(); } - if(\App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) { + if(App::$pager['page'] == 1 && $j['records'] == 0 && strpos($search,'@')) { goaway(z_root() . '/chanview/?f=&address=' . $search); } info( t("No entries (some entries may be hidden).") . EOL); diff --git a/Zotlabs/Module/Dirsearch.php b/Zotlabs/Module/Dirsearch.php index 92b33df0c..c15b13a90 100644 --- a/Zotlabs/Module/Dirsearch.php +++ b/Zotlabs/Module/Dirsearch.php @@ -1,14 +1,17 @@ <?php namespace Zotlabs\Module; +use App; +use Zotlabs\Web\Controller; + require_once('include/dir_fns.php'); -class Dirsearch extends \Zotlabs\Web\Controller { +class Dirsearch extends Controller { function init() { - \App::set_pager_itemspage(60); + App::set_pager_itemspage(30); } @@ -25,7 +28,8 @@ class Dirsearch extends \Zotlabs\Web\Controller { $ret['message'] = t('This site is not a directory server'); json_return_and_die($ret); } - + + $access_token = $_REQUEST['t']; $token = get_config('system','realm_token'); @@ -286,29 +290,29 @@ class Dirsearch extends \Zotlabs\Web\Controller { else $entry['total_ratings'] = 0; - $entry['name'] = $rr['xchan_name']; - $entry['hash'] = $rr['xchan_hash']; - + $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']; + $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; diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index 5983578b3..3d61d7018 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -47,7 +47,6 @@ class Display extends \Zotlabs\Web\Controller { } $observer_is_owner = false; - $updateable = false; if(local_channel() && (! $update)) { @@ -101,7 +100,7 @@ class Display extends \Zotlabs\Web\Controller { if($decoded) $item_hash = $decoded; - $r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid like '%s' limit 1", + $r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid like '%s' limit 1", dbesc($item_hash . '%') ); @@ -159,14 +158,17 @@ class Display extends \Zotlabs\Web\Controller { } } if($target_item['item_type'] == ITEM_TYPE_CARD) { + $x = q("select * from channel where channel_id = %d limit 1", intval($target_item['uid']) ); + $y = q("select * from iconfig left join item on iconfig.iid = item.id where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'CARD' and item.id = %d limit 1", intval($target_item['uid']), intval($target_item['parent']) ); + if($x && $y) { goaway(z_root() . '/cards/' . $x[0]['channel_address'] . '/' . $y[0]['v']); } @@ -200,7 +202,8 @@ 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['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) @@ -223,6 +226,7 @@ class Display extends \Zotlabs\Web\Controller { '$conv' => '0', '$spam' => '0', '$fh' => '0', + '$dm' => '0', '$nouveau' => '0', '$wall' => '0', '$static' => $static, @@ -269,9 +273,6 @@ class Display extends \Zotlabs\Web\Controller { intval(local_channel()), dbesc($target_item['parent_mid']) ); - if($r) { - $updateable = true; - } } if(! $r) { @@ -313,9 +314,6 @@ class Display extends \Zotlabs\Web\Controller { intval(local_channel()), dbesc($target_item['parent_mid']) ); - if($r) { - $updateable = true; - } } if($r === null) { @@ -427,13 +425,6 @@ class Display extends \Zotlabs\Web\Controller { killme(); } - - if($updateable) { - $x = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 AND uid = %d and parent = %d ", - intval(local_channel()), - intval($r[0]['item_id']) - ); - } $o .= '<div id="content-complete"></div>'; diff --git a/Zotlabs/Module/Embedphotos.php b/Zotlabs/Module/Embedphotos.php index 6a88513dc..9b0884197 100644 --- a/Zotlabs/Module/Embedphotos.php +++ b/Zotlabs/Module/Embedphotos.php @@ -68,6 +68,8 @@ class Embedphotos extends \Zotlabs\Web\Controller { $ext = '.png'; elseif($r[0]['mimetype'] === 'image/gif') $ext = '.gif'; + elseif($r[0]['mimetype'] === 'image/webp') + $exp = '.webp'; else $ext = EMPTY_STR; diff --git a/Zotlabs/Module/Event.php b/Zotlabs/Module/Event.php new file mode 100644 index 000000000..22a1341cc --- /dev/null +++ b/Zotlabs/Module/Event.php @@ -0,0 +1,76 @@ +<?php +namespace Zotlabs\Module; + +use Zotlabs\Web\Controller; +use Zotlabs\Lib\ActivityStreams; +use Zotlabs\Lib\Activity; +use Zotlabs\Lib\LDSignatures; +use Zotlabs\Web\HTTPSig; + +class Event extends Controller { + + function init() { + + if(ActivityStreams::is_as_request()) { + $item_id = argv(1); + + if(! $item_id) + return; + + $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 + and item.item_delayed = 0 and item.item_blocked = 0 "; + + $sql_extra = item_permissions_sql(0); + + $r = q("select * from item where mid like '%s' $item_normal $sql_extra limit 1", + dbesc(z_root() . '/activity/' . $item_id . '%') + ); + + if(! $r) { + $r = q("select * from item where mid like '%s' $item_normal limit 1", + dbesc(z_root() . '/activity/' . $item_id . '%') + ); + + if($r) { + http_status_exit(403, 'Forbidden'); + } + http_status_exit(404, 'Not found'); + } + + xchan_query($r,true); + $items = fetch_post_tags($r,true); + + $channel = channelx_by_n($items[0]['uid']); + + if(! is_array($items[0]['obj'])) { + $obj = json_decode($items[0]['obj'],true); + } + else { + $obj = $items[0]['obj']; + } + + $x = array_merge(['@context' => [ + ACTIVITYSTREAMS_JSONLD_REV, + 'https://w3id.org/security/v1', + z_root() . ZOT_APSCHEMA_REV + ]], $obj ); + + $headers = []; + $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ; + $x['signature'] = LDSignatures::sign($x,$channel); + $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,$channel['channel_prvkey'],channel_url($channel)); + HTTPSig::set_headers($h); + + echo $ret; + killme(); + + } + + } + +}
\ No newline at end of file diff --git a/Zotlabs/Module/Feed.php b/Zotlabs/Module/Feed.php index 36869abbe..b5e7b28fa 100644 --- a/Zotlabs/Module/Feed.php +++ b/Zotlabs/Module/Feed.php @@ -17,7 +17,7 @@ class Feed extends \Zotlabs\Web\Controller { $params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0); $params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0); $params['start'] = ((x($_REQUEST,'start')) ? intval($_REQUEST['start']) : 0); - $params['records'] = ((x($_REQUEST,'records')) ? intval($_REQUEST['records']) : 40); + $params['records'] = ((x($_REQUEST,'records')) ? intval($_REQUEST['records']) : 10); $params['direction'] = ((x($_REQUEST,'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); $params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : ''); $params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 0); diff --git a/Zotlabs/Module/Fhubloc_id_url.php b/Zotlabs/Module/Fhubloc_id_url.php new file mode 100644 index 000000000..a5627a33d --- /dev/null +++ b/Zotlabs/Module/Fhubloc_id_url.php @@ -0,0 +1,79 @@ +<?php +namespace Zotlabs\Module; + +/* fix missing or hubloc_id_url entries */ + +class Fhubloc_id_url extends \Zotlabs\Web\Controller { + + function get() { + + if(! is_site_admin()) + return; + + q("START TRANSACTION"); + + // remove broken xchan entries + $r0 = dbq("DELETE FROM xchan WHERE xchan_hash = ''"); + + // remove broken hubloc entries + $r1 = dbq("DELETE FROM hubloc WHERE hubloc_hash = ''"); + + // fix legacy zot hubloc_id_url + $r2 = dbq("UPDATE hubloc + SET hubloc_id_url = CONCAT(hubloc_url, '/channel/', SUBSTRING(hubloc_addr FROM 1 FOR POSITION('@' IN hubloc_addr) -1)) + WHERE hubloc_network = 'zot' + AND hubloc_id_url = ''" + ); + + // fix singleton networks hubloc_id_url + if(ACTIVE_DBTYPE == DBTYPE_MYSQL) { + // fix entries for activitypub which miss the xchan_url due to an earlier bug + $r3 = dbq("UPDATE xchan + SET xchan_url = xchan_hash + WHERE xchan_network = 'activitypub' + AND xchan_url = ''" + ); + + $r4 = dbq("UPDATE hubloc + LEFT JOIN xchan ON hubloc.hubloc_hash = xchan.xchan_hash + SET hubloc.hubloc_id_url = xchan.xchan_url + WHERE hubloc.hubloc_network IN ('activitypub', 'diaspora', 'friendica-over-diaspora', 'gnusoc') + AND hubloc.hubloc_id_url = '' + AND xchan.xchan_url IS NOT NULL" + ); + + } + if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { + // fix entries for activitypub which miss the xchan_url due to an earlier bug + $r3 = dbq("UPDATE xchan + SET xchan_url = xchan_hash + WHERE xchan_network = 'activitypub' + AND xchan_url = ''" + ); + + $r4 = dbq("UPDATE hubloc + SET hubloc_id_url = xchan_url + FROM xchan + WHERE hubloc_hash = xchan_hash + AND hubloc_network IN ('activitypub', 'diaspora', 'friendica-over-diaspora', 'gnusoc') + AND hubloc_id_url = '' + AND xchan_url IS NOT NULL" + ); + + + } + + if($r0 && $r1 && $r2 && $r3 && $r4) { + // remove hubloc entries where hubloc_id_url could not be fixed + $r5 = dbq("DELETE FROM hubloc WHERE hubloc_id_url = ''"); + } + + if($r0 && $r1 && $r2 && $r3 && $r4 && $r5) { + q("COMMIT"); + return 'Completed'; + } + + q("ROLLBACK"); + return 'Failed'; + } +} diff --git a/Zotlabs/Module/Fhublocs.php b/Zotlabs/Module/Fhublocs.php index 42c119da3..dcd399a1f 100644 --- a/Zotlabs/Module/Fhublocs.php +++ b/Zotlabs/Module/Fhublocs.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libzot; + require_once('include/zot.php'); require_once('include/crypto.php'); @@ -10,7 +12,7 @@ require_once('include/crypto.php'); class Fhublocs extends \Zotlabs\Web\Controller { function get() { - + if(! is_site_admin()) return; @@ -21,9 +23,11 @@ class Fhublocs extends \Zotlabs\Web\Controller { if($r) { foreach($r as $rr) { + $found = false; $primary_address = ''; - $x = zot_get_hublocs($rr['channel_hash']); + $x = Libzot::get_hublocs($rr['channel_hash']); + if($x) { foreach($x as $xx) { if($xx['hubloc_url'] === z_root() && $xx['hubloc_sitekey'] === $sitekey) { @@ -42,13 +46,12 @@ class Fhublocs extends \Zotlabs\Web\Controller { if($y) $primary_address = $y[0]['xchan_addr']; - $hub_address = channel_reddress($rr['channel']); - - + $hub_address = channel_reddress($rr); + $primary = (($hub_address === $primary_address) ? 1 : 0); if(! $y) $primary = 1; - + $m = q("delete from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ", dbesc($rr['channel_hash']), dbesc(z_root()) @@ -56,7 +59,7 @@ class Fhublocs extends \Zotlabs\Web\Controller { // Create a verified hub location pointing to this site. - +/* $h = hubloc_store_lowlevel( [ 'hubloc_guid' => $rr['channel_guid'], @@ -72,7 +75,26 @@ class Fhublocs extends \Zotlabs\Web\Controller { 'hubloc_sitekey' => $sitekey ] ); - +*/ + $h = hubloc_store_lowlevel( + [ + 'hubloc_guid' => $rr['channel_guid'], + 'hubloc_guid_sig' => $rr['channel_guid_sig'], + 'hubloc_hash' => $rr['channel_hash'], + 'hubloc_id_url' => channel_url($rr), + 'hubloc_addr' => channel_reddress($rr), + 'hubloc_primary' => intval($primary), + 'hubloc_url' => z_root(), + 'hubloc_url_sig' => Libzot::sign(z_root(), $rr['channel_prvkey']), + 'hubloc_site_id' => Libzot::make_xchan_hash(z_root(), $sitekey), + 'hubloc_host' => \App::get_hostname(), + 'hubloc_callback' => z_root() . '/zot', + 'hubloc_sitekey' => $sitekey, + 'hubloc_network' => 'zot6', + 'hubloc_updated' => datetime_convert() + ] + ); + if($h) $o . 'local hubloc created for ' . $rr['channel_name'] . EOL; else diff --git a/Zotlabs/Module/File_upload.php b/Zotlabs/Module/File_upload.php index 4d1cc4cda..1735e9487 100644 --- a/Zotlabs/Module/File_upload.php +++ b/Zotlabs/Module/File_upload.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + require_once('include/attach.php'); require_once('include/channel.php'); require_once('include/photos.php'); @@ -41,7 +43,7 @@ class File_upload extends \Zotlabs\Web\Controller { $sync = attach_export_data($channel,$hash); if($sync) { - build_sync_packet($channel['channel_id'],array('file' => array($sync))); + Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); } goaway(z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']); @@ -97,7 +99,7 @@ class File_upload extends \Zotlabs\Web\Controller { if($r['success']) { $sync = attach_export_data($channel,$r['data']['hash']); if($sync) - build_sync_packet($channel['channel_id'],array('file' => array($sync))); + Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); } } diff --git a/Zotlabs/Module/Filestorage.php b/Zotlabs/Module/Filestorage.php index 2c247cd65..0c6233493 100644 --- a/Zotlabs/Module/Filestorage.php +++ b/Zotlabs/Module/Filestorage.php @@ -5,7 +5,7 @@ namespace Zotlabs\Module; * */ - +use Zotlabs\Lib\Libsync; class Filestorage extends \Zotlabs\Web\Controller { @@ -35,12 +35,12 @@ class Filestorage extends \Zotlabs\Web\Controller { $url = get_cloud_url($channel_id, $channel['channel_address'], $resource); - //get the object before permissions change so we can catch eventual former allowed members - $object = get_file_activity_object($channel_id, $resource, $url); - attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse, true); - file_activity($channel_id, $object, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], 'post', $notify); + if($notify) { + $observer = \App::get_observer(); + attach_store_item($channel, $observer, $resource); + } goaway(dirname($url)); } @@ -131,7 +131,7 @@ class Filestorage extends \Zotlabs\Web\Controller { if(! $admin_delete) { $sync = attach_export_data($channel, $f['hash'], true); if($sync) { - build_sync_packet($channel['channel_id'], array('file' => array($sync))); + Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync))); } } diff --git a/Zotlabs/Module/Follow.php b/Zotlabs/Module/Follow.php index cbf9d62c5..11febd8fc 100644 --- a/Zotlabs/Module/Follow.php +++ b/Zotlabs/Module/Follow.php @@ -1,31 +1,88 @@ <?php namespace Zotlabs\Module; +use App; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\Libsync; +use Zotlabs\Lib\ActivityStreams; +use Zotlabs\Lib\Activity; +use Zotlabs\Web\HTTPSig; +use Zotlabs\Lib\LDSignatures; +use Zotlabs\Lib\Connect; +use Zotlabs\Daemon\Master; -require_once('include/follow.php'); - - -class Follow extends \Zotlabs\Web\Controller { +class Follow extends Controller { function init() { - if(! local_channel()) { + if (ActivityStreams::is_as_request() && argc() == 2) { + + $abook_id = intval(argv(1)); + if(! $abook_id) + return; + + $r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d", + intval($abook_id) + ); + if (! $r) { + return; + } + + $chan = channelx_by_n($r[0]['abook_channel']); + + if (! $chan) { + http_status_exit(404, 'Not found'); + } + + $actor = Activity::encode_person($chan,true,true); + if (! $actor) { + http_status_exit(404, 'Not found'); + } + + $x = array_merge(['@context' => [ + ACTIVITYSTREAMS_JSONLD_REV, + 'https://w3id.org/security/v1', + z_root() . ZOT_APSCHEMA_REV + ]], + [ + 'id' => z_root() . '/follow/' . $r[0]['abook_id'], + 'type' => 'Follow', + 'actor' => $actor, + 'object' => $r[0]['xchan_url'] + ]); + + $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)); + HTTPSig::set_headers($h); + echo $ret; + killme(); + + } + + if (! local_channel()) { return; } - + $uid = local_channel(); $url = notags(trim(punify($_REQUEST['url']))); $return_url = $_SESSION['return_url']; $confirm = intval($_REQUEST['confirm']); $interactive = (($_REQUEST['interactive']) ? intval($_REQUEST['interactive']) : 1); - $channel = \App::get_channel(); + $channel = App::get_channel(); - $result = new_contact($uid,$url,$channel,$interactive,$confirm); + $result = Connect::connect($channel,$url); - if($result['success'] == false) { - if($result['message']) + if ($result['success'] == false) { + if ($result['message']) { notice($result['message']); - if($interactive) { + } + if ($interactive) { goaway($return_url); } else { @@ -36,8 +93,8 @@ class Follow extends \Zotlabs\Web\Controller { info( t('Connection added.') . EOL); $clone = array(); - foreach($result['abook'] as $k => $v) { - if(strpos($k,'abook_') === 0) { + foreach ($result['abook'] as $k => $v) { + if (strpos($k,'abook_') === 0) { $clone[$k] = $v; } } @@ -46,20 +103,21 @@ class Follow extends \Zotlabs\Web\Controller { unset($clone['abook_channel']); $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']); - if($abconfig) + if ($abconfig) { $clone['abconfig'] = $abconfig; + } + Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true); - build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)), true); - - $can_view_stream = intval(get_abconfig($channel['channel_id'],$clone['abook_xchan'],'their_perms','view_stream')); + $can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream'); // If we can view their stream, pull in some posts - if(($can_view_stream) || ($result['abook']['xchan_network'] === 'rss')) - \Zotlabs\Daemon\Master::Summon(array('Onepoll',$result['abook']['abook_id'])); + if (($can_view_stream) || ($result['abook']['xchan_network'] === 'rss')) { + Master::Summon([ 'Onepoll', $result['abook']['abook_id'] ]); + } - if($interactive) { - goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?f=&follow=1'); + if ($interactive) { + goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1'); } else { json_return_and_die([ 'success' => true ]); @@ -68,7 +126,7 @@ class Follow extends \Zotlabs\Web\Controller { } function get() { - if(! local_channel()) { + if (! local_channel()) { return login(); } } diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index f836978ee..993d428f5 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -4,6 +4,7 @@ namespace Zotlabs\Module; use App; use Zotlabs\Web\Controller; use Zotlabs\Lib\Apps; +use Zotlabs\Lib\Libsync; require_once('include/group.php'); @@ -80,7 +81,7 @@ class Group extends Controller { info( t('Privacy group updated.') . EOL ); - build_sync_packet(local_channel(),null,true); + Libsync::build_sync_packet(local_channel(),null,true); } goaway(z_root() . '/group/' . argv(1) . '/' . argv(2)); diff --git a/Zotlabs/Module/Help.php b/Zotlabs/Module/Help.php index f1b1acaef..ce05035b3 100644 --- a/Zotlabs/Module/Help.php +++ b/Zotlabs/Module/Help.php @@ -66,7 +66,10 @@ class Help extends \Zotlabs\Web\Controller { case IMAGETYPE_PNG: header("Content-Type: image/png"); break; - default: + case IMAGETYPE_WEBP: + header("Content-Type: image/webp"); + break; + default: break; } header("Content-Length: " . filesize($realpath)); diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index 848fe3e25..e2678c07f 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -152,8 +152,8 @@ 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['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); @@ -179,6 +179,7 @@ class Hq extends \Zotlabs\Web\Controller { '$conv' => '0', '$spam' => '0', '$fh' => '0', + '$dm' => '0', '$nouveau' => '0', '$wall' => '0', '$static' => $static, @@ -198,8 +199,6 @@ class Hq extends \Zotlabs\Web\Controller { ]); } - $updateable = false; - if($load && $target_item) { $r = null; @@ -212,10 +211,6 @@ class Hq extends \Zotlabs\Web\Controller { dbesc($target_item['parent_mid']) ); - if($r) { - $updateable = true; - } - if(!$r) { $sys_item = true; @@ -242,10 +237,6 @@ class Hq extends \Zotlabs\Web\Controller { dbesc($target_item['parent_mid']) ); - if($r) { - $updateable = true; - } - if(!$r) { $sys_item = true; @@ -282,13 +273,6 @@ class Hq extends \Zotlabs\Web\Controller { $o .= conversation($items, 'hq', $update, 'client'); - if($updateable) { - $x = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d AND parent = %d ", - intval(local_channel()), - intval($r[0]['item_id']) - ); - } - $o .= '<div id="content-complete"></div>'; return $o; diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php index 18cb5560e..2c6e09fa7 100644 --- a/Zotlabs/Module/Import.php +++ b/Zotlabs/Module/Import.php @@ -137,6 +137,11 @@ class Import extends \Zotlabs\Web\Controller { return; } + 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) $seize = 1; @@ -212,50 +217,21 @@ class Import extends \Zotlabs\Web\Controller { // create new hubloc for the new channel at this site if(array_key_exists('channel',$data)) { - $r = hubloc_store_lowlevel( - [ - 'hubloc_guid' => $channel['channel_guid'], - 'hubloc_guid_sig' => $channel['channel_guid_sig'], - 'hubloc_hash' => $channel['channel_hash'], - 'hubloc_addr' => channel_reddress($channel), - 'hubloc_network' => 'zot', - 'hubloc_primary' => (($seize) ? 1 : 0), - 'hubloc_url' => z_root(), - 'hubloc_url_sig' => base64url_encode(rsa_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() - ] - ); - - // 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_hash']), - dbesc(z_root()) - ); - } - - // create a new zot6 hubloc if we have got a channel_portable_id if($channel['channel_portable_id']) { $r = hubloc_store_lowlevel( [ 'hubloc_guid' => $channel['channel_guid'], - 'hubloc_guid_sig' => 'sha256.' . $channel['channel_guid_sig'], + 'hubloc_guid_sig' => $channel['channel_guid_sig'], 'hubloc_hash' => $channel['channel_portable_id'], 'hubloc_addr' => channel_reddress($channel), - 'hubloc_network' => 'zot6', + 'hubloc_network' => 'zot', 'hubloc_primary' => (($seize) ? 1 : 0), 'hubloc_url' => z_root(), - 'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])), + 'hubloc_url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])), 'hubloc_host' => \App::get_hostname(), - 'hubloc_callback' => z_root() . '/zot', + 'hubloc_callback' => z_root() . '/post', '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_updated' => datetime_convert() ] ); @@ -266,7 +242,35 @@ class Import extends \Zotlabs\Web\Controller { dbesc(z_root()) ); } + } + // create a new zot6 hubloc if we have got a channel_portable_id + + $r = hubloc_store_lowlevel( + [ + 'hubloc_guid' => $channel['channel_guid'], + 'hubloc_guid_sig' => $channel['channel_guid_sig'], + 'hubloc_hash' => $channel['channel_hash'], + 'hubloc_addr' => channel_reddress($channel), + 'hubloc_network' => 'zot6', + 'hubloc_primary' => (($seize) ? 1 : 0), + 'hubloc_url' => z_root(), + 'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])), + 'hubloc_host' => \App::get_hostname(), + 'hubloc_callback' => z_root() . '/zot', + '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')) + ] + ); + + // 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_hash']), + dbesc(z_root()) + ); } } @@ -285,32 +289,12 @@ class Import extends \Zotlabs\Web\Controller { dbesc($channel['channel_portable_id']) ); - $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' => 'zot', - 'xchan_photo_date' => datetime_convert(), - 'xchan_name_date' => datetime_convert() - ] - ); - if($channel['channel_portable_id']) { $r = xchan_store_lowlevel( [ - 'xchan_hash' => \Zotlabs\Lib\Libzot::make_xchan_hash($channel['channel_guid'],$channel['channel_pubkey']), + 'xchan_hash' => $channel['channel_portable_id'], 'xchan_guid' => $channel['channel_guid'], - 'xchan_guid_sig' => 'sha256.' . $channel['channel_guid_sig'], + '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'], @@ -320,13 +304,32 @@ class Import extends \Zotlabs\Web\Controller { '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_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() + ] + ); } @@ -346,7 +349,7 @@ class Import extends \Zotlabs\Web\Controller { } if($xchan['xchan_network'] === 'zot6') { - $zhash = \Zotlabs\Lib\Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']); + $zhash = Libzot::make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_pubkey']); if($zhash !== $xchan['xchan_hash']) { logger('forged xchan: ' . print_r($xchan,true)); continue; diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 14881844d..922a2ef06 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module; +use Zotlabs\Lib\Config; use Zotlabs\Lib\IConfig; use Zotlabs\Lib\Enotify; use Zotlabs\Web\Controller; @@ -11,7 +12,9 @@ use Zotlabs\Lib\ActivityStreams; use Zotlabs\Lib\LDSignatures; use Zotlabs\Web\HTTPSig; use Zotlabs\Lib\Libzot; +use Zotlabs\Lib\Libsync; use Zotlabs\Lib\ThreadListener; +use Zotlabs\Access\PermissionRoles; use App; require_once('include/crypto.php'); @@ -46,7 +49,7 @@ class Item extends Controller { $item_id = argv(1); - if (! $item_id) + if(! $item_id) http_status_exit(404, 'Not found'); $portable_id = EMPTY_STR; @@ -67,32 +70,24 @@ class Item extends Controller { // process an authenticated fetch - $sigdata = HTTPSig::verify(EMPTY_STR); - if($sigdata['portable_id'] && $sigdata['header_valid']) { + $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); - // first see if we have a copy of this item's parent owned by the current signer - // include xchans for all zot-like networks - these will have the same guid and public key - - $x = q("select * from xchan where xchan_hash = '%s'", - dbesc($sigdata['portable_id']) + $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1", + dbesc($r[0]['parent_mid']), + dbesc($portable_id) ); - - if ($x) { - $xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ", - dbesc($sigdata['portable_id']), - dbesc($x[0]['xchan_guid']), - dbesc($x[0]['xchan_pubkey']) - ); - - if ($xchans) { - $hashes = ids_to_querystr($xchans,'xchan_hash',true); - $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1", - dbesc($r[0]['parent_mid']) - ); - } - } + } + 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 @@ -112,7 +107,7 @@ class Item extends Controller { $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 ", + $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) ); @@ -123,43 +118,112 @@ class Item extends Controller { xchan_query($items,true); $items = fetch_post_tags($items,true); - $observer = App::get_observer(); - $parent = $items[0]; - $recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'],'activitypub','recips', []) : []); - $to = (($recips && array_key_exists('to',$recips) && is_array($recips['to'])) ? $recips['to'] : null); - $nitems = []; - foreach($items as $i) { + if(! $items) + http_status_exit(404, 'Not found'); - $mids = []; + $chan = channelx_by_n($items[0]['uid']); - if(intval($i['item_private'])) { - if(! $observer) { - continue; - } - // ignore private reshare, possibly from hubzilla - if($i['verb'] === 'Announce') { - if(! in_array($i['thr_parent'],$mids)) { - $mids[] = $i['thr_parent']; - } - continue; - } - // also ignore any children of the private reshares - if(in_array($i['thr_parent'],$mids)) { - continue; - } + if(! $chan) + http_status_exit(404, 'Not found'); - if((! $to) || (! in_array($observer['xchan_url'],$to))) { - continue; - } + if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream')) + http_status_exit(403, 'Forbidden'); - } - $nitems[] = $i; + + $i = Activity::encode_item_collection($items, 'conversation/' . $item_id, 'OrderedCollection'); + if($portable_id) { + ThreadListener::store(z_root() . '/item/' . $item_id,$portable_id); } - if(! $nitems) + if(! $i) + http_status_exit(404, 'Not found'); + + $x = array_merge(['@context' => [ + ACTIVITYSTREAMS_JSONLD_REV, + 'https://w3id.org/security/v1', + z_root() . ZOT_APSCHEMA_REV + ]], $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['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; + $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan)); + HTTPSig::set_headers($h); + echo $ret; + killme(); + + } + + if(ActivityStreams::is_as_request()) { + + $item_id = argv(1); + if(! $item_id) http_status_exit(404, 'Not found'); - $chan = channelx_by_n($nitems[0]['uid']); + $portable_id = EMPTY_STR; + + $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 "; + + $i = null; + + // do we have the item (at all)? + // add preferential bias to item owners (item_wall = 1) + + $r = q("select * from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1", + dbesc(z_root() . '/item/' . $item_id), + dbesc($item_id) + ); + + if (! $r) { + http_status_exit(404,'Not found'); + } + + // process an authenticated fetch + + $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); + + $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1 ", + dbesc($r[0]['parent_mid']), + dbesc($portable_id) + ); + } + 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 + // with a bias towards those items owned by channels on this site (item_wall = 1) + + $sql_extra = item_permissions_sql(0); + + 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 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); + + $chan = channelx_by_n($items[0]['uid']); if(! $chan) http_status_exit(404, 'Not found'); @@ -167,10 +231,7 @@ class Item extends Controller { if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream')) http_status_exit(403, 'Forbidden'); - $i = Activity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection'); - if($portable_id) { - ThreadListener::store(z_root() . '/item/' . $item_id,$portable_id); - } + $i = Activity::encode_item($items[0],true); if(! $i) http_status_exit(404, 'Not found'); @@ -182,9 +243,10 @@ class Item extends Controller { ]], $i); $headers = []; - $headers['Content-Type'] = 'application/x-zot+json' ; + $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)); @@ -194,9 +256,11 @@ class Item extends Controller { } + if(argc() > 1 && argv(1) !== 'drop') { - $x = q("select uid, item_wall, llink, mid from item where mid = '%s' ", - dbesc(z_root() . '/item/' . argv(1)) + $x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' ", + dbesc(z_root() . '/item/' . argv(1)), + dbesc(z_root() . '/activity/' . argv(1)) ); if($x) { foreach($x as $xv) { @@ -273,7 +337,9 @@ class Item extends Controller { $consensus = intval($_REQUEST['consensus']); $nocomment = intval($_REQUEST['nocomment']); - + + $is_poll = ((trim($_REQUEST['poll_answers'][0]) != '' && trim($_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. // If using the API from a device (leaf node) you must set origin to 1 (default) or leave unset. @@ -711,6 +777,27 @@ class Item extends Controller { $str_group_allow = $gacl['allow_gid']; $str_contact_deny = $gacl['deny_cid']; $str_group_deny = $gacl['deny_gid']; + + + $groupww = false; + + // 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); + + if (($is_group) && ($walltowall) && (! $walltowall_comment)) { + $groupww = true; + $str_contact_allow = $owner_xchan['xchan_hash']; + $str_group_allow = ''; + } + + $post_tags = []; if($mimetype === 'text/bbcode') { @@ -720,19 +807,18 @@ class Item extends Controller { // BBCODE alert: the following functions assume bbcode input // and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.) // we may need virtual or template classes to implement the possible alternatives - if(strpos($body,'[/summary]') !== false) { - $match = ''; - $cnt = preg_match("/\[summary\](.*?)\[\/summary\]/ism",$body,$match); - if($cnt) { - $summary .= $match[1]; - } - $body_content = preg_replace("/^(.*?)\[summary\](.*?)\[\/summary\](.*?)$/ism", '',$body); - $body = trim($body_content); - } - - $summary = cleanup_bbcode($summary); + $match = ''; + $cnt = preg_match("/\[summary\](.*?)\[\/summary\]/ism",$body,$match); + if($cnt) { + $summary .= $match[1]; + } + $body_content = preg_replace("/\[summary\](.*?)\[\/summary\]/ism", '',$body); + $body = trim($body_content); + } + + $summary = cleanup_bbcode($summary); $body = cleanup_bbcode($body); @@ -746,7 +832,6 @@ class Item extends Controller { // Set permissions based on tag replacements set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $parent_item, $private); - $post_tags = array(); foreach($results as $result) { $success = $result['success']; if($success['replaced']) { @@ -759,6 +844,7 @@ class Item extends Controller { ); } } + } if(($str_contact_allow) && (! $str_group_allow)) { @@ -830,8 +916,6 @@ class Item extends Controller { $i = 0; foreach($match[2] as $mtch) { $reshare = new \Zotlabs\Lib\Share($mtch); - $datarray['obj'] = $reshare->obj(); - $datarray['obj_type'] = $datarray['obj']['type']; $body = str_replace($match[1][$i],$reshare->bbcode(),$body); $i++; } @@ -924,6 +1008,27 @@ class Item extends Controller { } + if($is_poll) { + $poll = [ + 'question' => $body, + 'answers' => $_REQUEST['poll_answers'], + 'multiple_answers' => $_REQUEST['poll_multiple_answers'], + '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 ]); + } + else { + $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_type = 'Question'; + } + if(! $parent_mid) { $parent_mid = $mid; } @@ -969,10 +1074,15 @@ class Item extends Controller { } if ((! $plink) && ($item_thread_top)) { - $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid); - $plink = substr($plink,0,190); + // $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid); + // $plink = substr($plink,0,190); + $plink = $mid; } - + + if ($datarray['obj']) { + $datarray['obj']['id'] = $mid; + } + $datarray['aid'] = $channel['channel_account_id']; $datarray['uid'] = $profile_uid; $datarray['uuid'] = $uuid; @@ -1030,10 +1140,9 @@ class Item extends Controller { $datarray['layout_mid'] = $layout_mid; $datarray['public_policy'] = $public_policy; $datarray['comment_policy'] = map_scope($comment_policy); - $datarray['term'] = $post_tags; + $datarray['term'] = array_unique($post_tags, SORT_REGULAR); $datarray['plink'] = $plink; $datarray['route'] = $route; - // A specific ACL over-rides public_policy completely @@ -1131,7 +1240,7 @@ class Item extends Controller { if($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true)))); + Libsync::build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true)))); } } if(! $nopush) @@ -1234,7 +1343,7 @@ class Item extends Controller { if($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true)))); + Libsync::build_sync_packet($profile_uid,array('item' => array(encode_item($sync_item[0],true)))); } } @@ -1242,7 +1351,11 @@ class Item extends Controller { $datarray['llink'] = z_root() . '/display/' . gen_link_id($datarray['mid']); call_hooks('post_local_end', $datarray); - + + if ($groupww) { + $nopush = false; + } + if(! $nopush) Master::Summon([ 'Notifier', $notify_type, $post_id ]); @@ -1336,7 +1449,7 @@ class Item extends Controller { if($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true)))); + Libsync::build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true)))); } if($complex) { @@ -1389,5 +1502,104 @@ class Item extends Controller { return $ret; } - + function extract_bb_poll_data(&$body,$item) { + + $multiple = false; + + if (strpos($body,'[/question]') === false && strpos($body,'[/answer]') === false) { + return false; + } + if (strpos($body,'[nobb]') !== false) { + return false; + } + + + $obj = []; + $ptr = []; + $matches = null; + $obj['type'] = 'Question'; + + 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); + } + } + + $matches = null; + + 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; + } + + $matches = null; + + 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; + } + + $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 ($item['item_private']) { + $obj['to'] = Activity::map_acl($item); + } + else { + $obj['to'] = [ ACTIVITY_PUBLIC_INBOX ]; + } + + return $obj; + + } + + + function extract_poll_data($poll, $item) { + + $multiple = intval($poll['multiple_answers']); + $expire_value = intval($poll['expire_value']); + $expire_unit = $poll['expire_unit']; + $question = $poll['question']; + $answers = $poll['answers']; + + $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 ]]; + } + + if($multiple) { + $obj['anyOf'] = $ptr; + } + else { + $obj['oneOf'] = $ptr; + } + + $obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', 'now + ' . $expire_value . ' ' . $expire_unit, ATOM_TIME); + + if ($item['item_private']) { + $obj['to'] = Activity::map_acl($item); + } + else { + $obj['to'] = [ ACTIVITY_PUBLIC_INBOX ]; + } + + return $obj; + + } + + + } diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php index 052d51d43..8ffa7f66c 100644 --- a/Zotlabs/Module/Like.php +++ b/Zotlabs/Module/Like.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module; use Zotlabs\Lib\Activity; +use Zotlabs\Lib\Libsync; require_once('include/security.php'); require_once('include/bbcode.php'); @@ -75,7 +76,12 @@ class Like extends \Zotlabs\Web\Controller { return EMPTY_STR; } - + $is_rsvp = false; + if (in_array($activity, [ ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE ])) { + $is_rsvp = true; + } + + $extended_like = false; $object = $target = null; $post_type = EMPTY_STR; @@ -204,20 +210,8 @@ class Like extends \Zotlabs\Web\Controller { if(! $plink) $plink = '[zrl=' . z_root() . '/profile/' . $ch[0]['channel_address'] . ']' . $post_type . '[/zrl]'; - $links = array(); - $links[] = array('rel' => 'alternate', 'type' => 'text/html', - 'href' => z_root() . '/profile/' . $ch[0]['channel_address']); - $links[] = array('rel' => 'photo', 'type' => $ch[0]['xchan_photo_mimetype'], - 'href' => $ch[0]['xchan_photo_l']); - - $object = json_encode(array( - 'type' => ACTIVITY_OBJ_PROFILE, - 'title' => $ch[0]['channel_name'], - 'id' => $ch[0]['xchan_url'] . '/' . $ch[0]['xchan_hash'], - 'link' => $links - )); - - + $object = json_encode(Activity::fetch_profile([ 'id' => channel_url($ch[0]) ])); + // second like of the same thing is "undo" for the first like $z = q("select * from likes where channel_id = %d and liker = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' limit 1", @@ -230,7 +224,7 @@ class Like extends \Zotlabs\Web\Controller { if($z) { $z[0]['deleted'] = 1; - build_sync_packet($ch[0]['channel_id'],array('likes' => $z)); + Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $z)); q("delete from likes where id = %d", intval($z[0]['id']) @@ -381,7 +375,7 @@ class Like extends \Zotlabs\Web\Controller { $arr = array(); $arr['uuid'] = $uuid; - $arr['mid'] = z_root() . '/item/' . $uuid; + $arr['mid'] = z_root() . (($is_rsvp) ? '/activity/' : '/item/') . $uuid; if($extended_like) { $arr['item_thread_top'] = 1; @@ -402,27 +396,8 @@ class Like extends \Zotlabs\Web\Controller { $body = $item['body']; - $object = json_encode(array( - 'type' => $objtype, - 'id' => $item['mid'], - 'asld' => Activity::fetch_item( [ 'id' => $item['mid'] ] ), - 'parent' => (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']), - 'link' => $links, - 'title' => $item['title'], - 'content' => $item['body'], - 'created' => $item['created'], - 'edited' => $item['edited'], - 'author' => array( - 'name' => $item_author['xchan_name'], - 'address' => $item_author['xchan_addr'], - 'guid' => $item_author['xchan_guid'], - 'guid_sig' => $item_author['xchan_guid_sig'], - 'link' => array( - array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']), - array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])), - ), - )); - + $object = json_encode(Activity::fetch_item( [ 'id' => $item['mid'] ])); + if(! intval($item['item_thread_top'])) $post_type = 'comment'; @@ -466,15 +441,15 @@ class Like extends \Zotlabs\Web\Controller { if($extended_like) { - $ulink = '[zrl=' . $ch[0]['xchan_url'] . ']' . $ch[0]['xchan_name'] . '[/zrl]'; - $alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]'; + $ulink = '[zrl=' . $ch[0]['xchan_url'] . '][bdi]' . $ch[0]['xchan_name'] . '[/bdi][/zrl]'; + $alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]'; $private = (($public) ? 0 : 1); } else { $arr['parent'] = $item['id']; $arr['thr_parent'] = $item['mid']; - $ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]'; - $alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]'; + $ulink = '[zrl=' . $item_author['xchan_url'] . '][bdi]' . $item_author['xchan_name'] . '[/bdi][/zrl]'; + $alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]'; $plink = '[zrl=' . z_root() . '/display/' . gen_link_id($item['mid']) . ']' . $post_type . '[/zrl]'; $allow_cid = $item['allow_cid']; $allow_gid = $item['allow_gid']; @@ -561,7 +536,7 @@ class Like extends \Zotlabs\Web\Controller { dbesc($obj_id) ); if($r) - build_sync_packet($ch[0]['channel_id'],array('likes' => $r)); + Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $r)); } diff --git a/Zotlabs/Module/Locs.php b/Zotlabs/Module/Locs.php index 47ece8041..4c935a6a2 100644 --- a/Zotlabs/Module/Locs.php +++ b/Zotlabs/Module/Locs.php @@ -1,22 +1,24 @@ <?php namespace Zotlabs\Module; /** @file */ +use App; +use Zotlabs\Web\Controller; +use Zotlabs\Daemon\Master; - -class Locs extends \Zotlabs\Web\Controller { +class Locs extends Controller { function post() { if(! local_channel()) return; - $channel = \App::get_channel(); + $channel = App::get_channel(); if($_REQUEST['primary']) { $hubloc_id = intval($_REQUEST['primary']); if($hubloc_id) { - $r = q("select hubloc_id from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1", + $r = q("select * from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1", intval($hubloc_id), dbesc($channel['channel_hash']) ); @@ -26,15 +28,16 @@ class Locs extends \Zotlabs\Web\Controller { return; } - $r = 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 = 0 WHERE hubloc_primary = 1 AND (hubloc_hash = '%s' OR hubloc_hash = '%s')", + dbesc($channel['channel_hash']), + dbesc($channel['channel_portable_id']) ); - $r = q("update hubloc set hubloc_primary = 1 where hubloc_id = %d and hubloc_hash = '%s'", + q("UPDATE hubloc SET hubloc_primary = 1 WHERE hubloc_id = %d AND hubloc_hash = '%s'", intval($hubloc_id), dbesc($channel['channel_hash']) ); - - \Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id'])); + + Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] ); return; } } @@ -68,11 +71,12 @@ class Locs extends \Zotlabs\Web\Controller { } } - $r = q("update hubloc set hubloc_deleted = 1 where hubloc_id = %d and hubloc_hash = '%s'", - intval($hubloc_id), - dbesc($channel['channel_hash']) + q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND (hubloc_hash = '%s' OR hubloc_hash = '%s')", + dbesc($r[0]['hubloc_id_url']), + dbesc($channel['channel_hash']), + dbesc($channel['channel_portable_id']) ); - \Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id'])); + Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] ); return; } } @@ -88,10 +92,10 @@ class Locs extends \Zotlabs\Web\Controller { return; } - $channel = \App::get_channel(); + $channel = App::get_channel(); if($_REQUEST['sync']) { - \Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id'])); + Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] ); info( t('Syncing locations') . EOL); goaway(z_root() . '/locs'); } diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php index 6ac656a04..b4372e26d 100644 --- a/Zotlabs/Module/Magic.php +++ b/Zotlabs/Module/Magic.php @@ -1,214 +1,133 @@ <?php namespace Zotlabs\Module; +use App; +use Zotlabs\Web\Controller; use Zotlabs\Web\HTTPSig; +use Zotlabs\Lib\Libzot; +use Zotlabs\Lib\SConfig; -@require_once('include/zot.php'); - - -class Magic extends \Zotlabs\Web\Controller { +class Magic extends Controller { function init() { + + $ret = [ + 'success' => false, + 'url' => '', + 'message' => '' + ]; - $ret = array('success' => false, 'url' => '', 'message' => ''); logger('mod_magic: invoked', LOGGER_DEBUG); - - logger('mod_magic: args: ' . print_r($_REQUEST,true),LOGGER_DATA); - - $addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : ''); - $bdest = ((x($_REQUEST,'bdest')) ? $_REQUEST['bdest'] : ''); - $dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : ''); - $test = ((x($_REQUEST,'test')) ? intval($_REQUEST['test']) : 0); - $rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0); - $owa = ((x($_REQUEST,'owa')) ? intval($_REQUEST['owa']) : 0); - $delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : ''); - - if($bdest) + + logger('args: ' . print_r($_REQUEST,true),LOGGER_DATA); + + $addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : ''); + $bdest = ((x($_REQUEST,'bdest')) ? $_REQUEST['bdest'] : ''); + $dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : ''); + $rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0); + $owa = ((x($_REQUEST,'owa')) ? intval($_REQUEST['owa']) : 0); + $delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : ''); + + // bdest is preferred as it is hex-encoded and can survive url rewrite and argument parsing + + if ($bdest) { $dest = hex2bin($bdest); + } $parsed = parse_url($dest); - if(! $parsed) { - if($test) { - $ret['message'] .= 'could not parse ' . $dest . EOL; - return($ret); - } + + if (! $parsed) { goaway($dest); } - + $basepath = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : ''); - - $x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1", - dbesc($basepath) - ); - - if(! $x) { - - /* - * We have no records for, or prior communications with this hub. - * If an address was supplied, let's finger them to create a hub record. - * Otherwise we'll use the special address '[system]' which will return - * either a system channel or the first available normal channel. We don't - * really care about what channel is returned - we need the hub information - * from that response so that we can create signed auth packets destined - * for that hub. - * - */ - - $j = \Zotlabs\Zot\Finger::run((($addr) ? $addr : '[system]@' . $parsed['host']),null); - if($j['success']) { - import_xchan($j); - - // Now try again - - $x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1", - dbesc($basepath) - ); - } - } - - if(! $x) { - if($rev) - goaway($dest); - else { - logger('mod_magic: no channels found for requested hub.' . print_r($_REQUEST,true)); - if($test) { - $ret['message'] .= 'This site has no previous connections with ' . $basepath . EOL; - return $ret; - } - notice( t('Hub not found.') . EOL); - return; - } - } - + $owapath = SConfig::get($basepath,'system','openwebauth', $basepath . '/owa'); + // This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating. // By default, we'll proceed without asking. - - $arr = array( - 'channel_id' => local_channel(), - 'xchan' => $x[0], + + $arr = [ + 'channel_id' => local_channel(), 'destination' => $dest, - 'proceed' => true - ); - + 'proceed' => true + ]; + call_hooks('magic_auth',$arr); $dest = $arr['destination']; - if(! $arr['proceed']) { - if($test) { - $ret['message'] .= 'cancelled by plugin.' . EOL; - return $ret; - } + if (! $arr['proceed']) { goaway($dest); } - - if((get_observer_hash()) && ($x[0]['hubloc_url'] === z_root())) { + + if((get_observer_hash()) && (stripos($dest,z_root()) === 0)) { + // We are already authenticated on this site and a registered observer. - // Just redirect. - if($test) { - $ret['success'] = true; - $ret['message'] .= 'Local site - you are already authenticated.' . EOL; - return $ret; - } - - $delegation_success = false; - if($delegate) { + // First check if this is a delegate request on the local system and process accordingly. + // Otherwise redirect. + + if ($delegate) { + $r = q("select * from channel left join hubloc on channel_hash = hubloc_hash where hubloc_addr = '%s' limit 1", dbesc($delegate) ); - - if($r && intval($r[0]['channel_id'])) { - $allowed = perm_is_allowed($r[0]['channel_id'],get_observer_hash(),'delegate'); - if($allowed) { + + if ($r) { + $c = array_shift($r); + if (perm_is_allowed($c['channel_id'],get_observer_hash(),'delegate')) { $tmp = $_SESSION; - $_SESSION['delegate_push'] = $tmp; - $_SESSION['delegate_channel'] = $r[0]['channel_id']; - $_SESSION['delegate'] = get_observer_hash(); - $_SESSION['account_id'] = intval($r[0]['channel_account_id']); - change_channel($r[0]['channel_id']); - - $delegation_success = true; + $_SESSION['delegate_push'] = $tmp; + $_SESSION['delegate_channel'] = $c['channel_id']; + $_SESSION['delegate'] = get_observer_hash(); + $_SESSION['account_id'] = intval($c['channel_account_id']); + + change_channel($c['channel_id']); } } } - - - - // FIXME: check and honour local delegation - - + goaway($dest); } - - if(local_channel()) { - $channel = \App::get_channel(); - + + if (local_channel()) { + $channel = App::get_channel(); + // OpenWebAuth - if($owa) { + if ($owa) { $dest = strip_zids($dest); $dest = strip_query_param($dest,'f'); + // We now post to the OWA endpoint. This improves security by providing a signed digest + $data = json_encode([ 'OpenWebAuth' => random_string() ]); $headers = []; $headers['Accept'] = 'application/x-zot+json' ; + $headers['Content-Type'] = 'application/x-zot+json' ; $headers['X-Open-Web-Auth'] = random_string(); - $headers['Host'] = $parsed['host']; $headers['Digest'] = HTTPSig::generate_digest_header($data); + $headers['Host'] = $parsed['host']; + $headers['(request-target)'] = 'post ' . '/owa'; - $headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], 'acct:' . channel_reddress($channel),true,'sha512'); - $x = z_post_url($basepath . '/owa',$data,$redirects,[ 'headers' => $headers ]); - - if($x['success']) { + $headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512'); + $x = z_post_url($owapath,$data,$redirects,[ 'headers' => $headers ]); + logger('owa fetch returned: ' . print_r($x,true),LOGGER_DATA); + if ($x['success']) { $j = json_decode($x['body'],true); - if($j['success']) { + if ($j['success'] && $j['encrypted_token']) { + // decrypt the token using our private key $token = ''; - if($j['encrypted_token']) { - openssl_private_decrypt(base64url_decode($j['encrypted_token']),$token,$channel['channel_prvkey']); - } - else { - $token = $j['token']; - } - - $strp = strpbrk($dest,'?&'); - $args = (($strp) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : ''); + openssl_private_decrypt(base64url_decode($j['encrypted_token']),$token,$channel['channel_prvkey']); + $x = strpbrk($dest,'?&'); + // redirect using the encrypted token which will be exchanged for an authenticated session + $args = (($x) ? '&owt=' . $token : '?f=&owt=' . $token) . (($delegate) ? '&delegate=1' : ''); goaway($dest . $args); } } - goaway($dest); - } - - - $token = random_string(); - - \Zotlabs\Lib\Verify::create('auth',$channel['channel_id'],$token,$x[0]['hubloc_url']); - - $target_url = $x[0]['hubloc_callback'] . '/?f=&auth=' . urlencode(channel_reddress($channel)) - . '&sec=' . $token . '&dest=' . urlencode($dest) . '&version=' . ZOT_REVISION; - - if($delegate) - $target_url .= '&delegate=' . urlencode($delegate); - - logger('mod_magic: redirecting to: ' . $target_url, LOGGER_DEBUG); - - if($test) { - $ret['success'] = true; - $ret['url'] = $target_url; - $ret['message'] = 'token ' . $token . ' created for channel ' . $channel['channel_id'] . ' for url ' . $x[0]['hubloc_url'] . EOL; - return $ret; } - - goaway($target_url); - } - - if($test) { - $ret['message'] = 'Not authenticated or invalid arguments to mod_magic' . EOL; - return $ret; - } - + goaway($dest); - } - + } diff --git a/Zotlabs/Module/Mail.php b/Zotlabs/Module/Mail.php deleted file mode 100644 index 7c344966b..000000000 --- a/Zotlabs/Module/Mail.php +++ /dev/null @@ -1,449 +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 Mail extends \Zotlabs\Web\Controller { - - function post() { - - if(! local_channel()) - return; - - $replyto = ((x($_REQUEST,'replyto')) ? notags(trim($_REQUEST['replyto'])) : ''); - $subject = ((x($_REQUEST,'subject')) ? notags(trim($_REQUEST['subject'])) : ''); - $body = ((x($_REQUEST,'body')) ? escape_tags(trim($_REQUEST['body'])) : ''); - $recipient = ((x($_REQUEST,'messageto')) ? notags(trim(urldecode($_REQUEST['messageto']))) : ''); - $rstr = ((x($_REQUEST,'messagerecip')) ? notags(trim($_REQUEST['messagerecip'])) : ''); - $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0); - $expires = ((x($_REQUEST,'expires')) ? datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['expires']) : NULL_DATE); - $raw = ((x($_REQUEST,'raw')) ? intval($_REQUEST['raw']) : 0); - $mimetype = ((x($_REQUEST,'mimetype')) ? notags(trim($_REQUEST['mimetype'])) : 'text/bbcode'); - - $sig = ((x($_REQUEST,'signature')) ? trim($_REQUEST['signature']) : ''); - if(strpos($sig,'b64.') === 0) - $sig = base64_decode(str_replace('b64.', '', $sig)); - - if($preview) { - - if($raw) { - $body = mail_prepare_binary(['id' => 'M0']); - echo json_encode(['preview' => $body]); - } - else { - $body = cleanup_bbcode($body); - $results = linkify_tags($body, local_channel()); - - if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) { - $attachments = array(); - foreach($match[2] as $mtch) { - $hash = substr($mtch,0,strpos($mtch,',')); - $rev = intval(substr($mtch,strpos($mtch,','))); - $r = attach_by_hash_nodata($hash,get_observer_hash(),$rev); - if($r['success']) { - $attachments[] = array( - 'href' => z_root() . '/attach/' . $r['data']['hash'], - 'length' => $r['data']['filesize'], - 'type' => $r['data']['filetype'], - 'title' => urlencode($r['data']['filename']), - 'revision' => $r['data']['revision'] - ); - } - $body = trim(str_replace($match[1],'',$body)); - } - } - echo json_encode(['preview' => zidify_links(smilies(bbcode($body)))]); - } - killme(); - } - - // If we have a raw string for a recipient which hasn't been auto-filled, - // it means they probably aren't in our address book, hence we don't know - // if we have permission to send them private messages. - // finger them and find out before we try and send it. - - if(! $recipient) { - $channel = \App::get_channel(); - - $j = \Zotlabs\Zot\Finger::run(punify($rstr),$channel); - - if(! $j['success']) { - notice( t('Unable to lookup recipient.') . EOL); - return; - } - - logger('message_post: lookup: ' . $rstr . ' ' . print_r($j,true)); - - if(! $j['guid']) { - notice( t('Unable to communicate with requested channel.')); - return; - } - - $x = import_xchan($j); - - if(! $x['success']) { - notice( t('Cannot verify requested channel.')); - return; - } - - $recipient = $x['hash']; - - $their_perms = 0; - - if($j['permissions']['data']) { - $permissions = crypto_unencapsulate($j['permissions'],$channel['channel_prvkey']); - if($permissions) - $permissions = json_decode($permissions, true); - logger('decrypted permissions: ' . print_r($permissions,true), LOGGER_DATA); - } - else - $permissions = $j['permissions']; - - if(! ($permissions['post_mail'])) { - notice( t('Selected channel has private message restrictions. Send failed.')); - // reported issue: let's still save the message and continue. We'll just tell them - // that nothing useful is likely to happen. They might have spent hours on it. - // return; - - } - } - - require_once('include/text.php'); - linkify_tags($body, local_channel()); - - - if(! $recipient) { - notice('No recipient found.'); - \App::$argc = 2; - \App::$argv[1] = 'new'; - return; - } - - // We have a local_channel, let send_message use the session channel and save a lookup - - $ret = send_message(0, $recipient, $body, $subject, $replyto, $expires, $mimetype, $raw, $sig); - - if($ret['success']) { - xchan_mail_query($ret['mail']); - build_sync_packet(0,array('conv' => array($ret['conv']),'mail' => array(encode_mail($ret['mail'],true)))); - } - else { - notice($ret['message']); - } - - goaway(z_root() . '/mail/combined'); - - } - - function get() { - - $o = ''; - nav_set_selected('Mail'); - - 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'; - - $tpl = get_markup_template('mail_head.tpl'); - $header = replace_macros($tpl, array( - '$header' => t('Messages'), - )); - - if(argc() == 3 && intval(argv(1)) && argv(2) === 'download') { - - $r = q("select * from mail where id = %d and channel_id = %d", - intval(argv(1)), - intval(local_channel()) - ); - - if($r) { - - header('Content-type: ' . $r[0]['mail_mimetype']); - header('Content-disposition: attachment; filename="' . t('message') . '-' . $r[0]['id'] . '"' ); - $body = (($r[0]['mail_obscured']) ? base64url_decode(str_rot47($r[0]['body'])) : $r[0]['body']); - echo $body; - killme(); - } - - } - - - if((argc() == 4) && (argv(2) === 'drop')) { - if(! intval(argv(3))) - return; - $cmd = argv(2); - $mailbox = argv(1); - $r = private_messages_drop(local_channel(), argv(3)); - if($r) { - //info( t('Message deleted.') . EOL ); - } - goaway(z_root() . '/mail/' . $mailbox); - } - - if((argc() == 4) && (argv(2) === 'recall')) { - if(! intval(argv(3))) - return; - $cmd = argv(2); - $mailbox = argv(1); - $r = q("update mail set mail_recalled = 1 where id = %d and channel_id = %d", - intval(argv(3)), - intval(local_channel()) - ); - $x = q("select * from mail where id = %d and channel_id = %d", - intval(argv(3)), - intval(local_channel()) - ); - if($x) { - build_sync_packet(local_channel(),array('mail' => encode_mail($x[0],true))); - } - - \Zotlabs\Daemon\Master::Summon(array('Notifier','mail',intval(argv(3)))); - - if($r) { - info( t('Message recalled.') . EOL ); - } - goaway(z_root() . '/mail/' . $mailbox . '/' . argv(3)); - - } - - if((argc() == 4) && (argv(2) === 'dropconv')) { - if(! intval(argv(3))) - return; - $cmd = argv(2); - $mailbox = argv(1); - $r = private_messages_drop(local_channel(), argv(3), true); - if($r) - info( t('Conversation removed.') . EOL ); - goaway(z_root() . '/mail/' . $mailbox); - } - - if((argc() > 1) && (argv(1) === 'new')) { - - $plaintext = true; - - $tpl = get_markup_template('msg-header.tpl'); - - $header = replace_macros($tpl, array( - '$baseurl' => z_root(), - '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), - '$nickname' => $channel['channel_address'], - '$linkurl' => t('Please enter a link URL:'), - '$expireswhen' => t('Expires YYYY-MM-DD HH:MM') - )); - - \App::$page['htmlhead'] .= $header; - - $prename = ''; - $preid = ''; - - if(x($_REQUEST,'hash')) { - - $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(local_channel()), - dbesc($_REQUEST['hash']) - ); - - if(!$r) { - $r = q("select * from xchan where xchan_hash = '%s' and xchan_network = 'zot' limit 1", - dbesc($_REQUEST['hash']) - ); - } - - if($r) { - $prename = (($r[0]['abook_id']) ? $r[0]['xchan_name'] : $r[0]['xchan_addr']); - $preurl = $r[0]['xchan_url']; - $preid = (($r[0]['abook_id']) ? ($r[0]['xchan_hash']) : ''); - } - else { - notice( t('Requested channel is not in this network') . EOL ); - } - - } - - $tpl = get_markup_template('prv_message.tpl'); - $o .= replace_macros($tpl,array( - '$new' => true, - '$header' => t('Send Private Message'), - '$to' => t('To:'), - '$prefill' => $prename, - '$preid' => $preid, - '$subject' => t('Subject:'), - '$subjtxt' => ((x($_REQUEST,'subject')) ? strip_tags($_REQUEST['subject']) : ''), - '$text' => ((x($_REQUEST,'body')) ? htmlspecialchars($_REQUEST['body'], ENT_COMPAT, 'UTF-8') : ''), - '$yourmessage' => t('Your message:'), - '$parent' => '', - '$attach' => t('Attach file'), - '$insert' => t('Insert web link'), - '$submit' => t('Send'), - '$defexpire' => '', - '$feature_expire' => ((feature_enabled(local_channel(),'content_expire')) ? true : false), - '$expires' => t('Set expiration date'), - '$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false), - '$encrypt' => t('Encrypt text'), - '$cipher' => $cipher, - )); - - return $o; - } - - $direct_mid = 0; - - switch(argv(1)) { - case 'combined': - $mailbox = 'combined'; - break; - case 'inbox': - $mailbox = 'inbox'; - break; - case 'outbox': - $mailbox = 'outbox'; - break; - default: - $mailbox = 'combined'; - - // notifications direct to mail/nn - - if(intval(argv(1))) - $direct_mid = intval(argv(1)); - break; - } - - - $last_message = private_messages_list(local_channel(), $mailbox, 0, 1); - - $mid = ((argc() > 2) && (intval(argv(2)))) ? argv(2) : $last_message[0]['id']; - - if($direct_mid) - $mid = $direct_mid; - - - $plaintext = true; - - // if( local_channel() && feature_enabled(local_channel(),'richtext') ) - // $plaintext = false; - - - - if($mailbox == 'combined') { - $messages = private_messages_fetch_conversation(local_channel(), $mid, true); - } - else { - $messages = private_messages_fetch_message(local_channel(), $mid, true); - } - - if(! $messages) { - //info( t('Message not found.') . EOL); - return; - } - - if($messages[0]['to_xchan'] === $channel['channel_hash']) - \App::$poi = $messages[0]['from']; - else - \App::$poi = $messages[0]['to']; - - $tpl = get_markup_template('msg-header.tpl'); - - \App::$page['htmlhead'] .= replace_macros($tpl, array( - '$nickname' => $channel['channel_address'], - '$baseurl' => z_root(), - '$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'), - '$linkurl' => t('Please enter a link URL:'), - '$expireswhen' => t('Expires YYYY-MM-DD HH:MM') - )); - - $mails = array(); - - $seen = 0; - $unknown = false; - - foreach($messages as $message) { - - $s = theme_attachments($message); - - if($message['mail_raw']) - $message['body'] = mail_prepare_binary([ 'id' => $message['id'] ]); - else - $message['body'] = zidify_links(smilies(bbcode($message['body']))); - - $mails[] = array( - 'mailbox' => $mailbox, - 'id' => $message['id'], - 'mid' => $message['mid'], - 'from_name' => $message['from']['xchan_name'], - 'from_url' => chanlink_hash($message['from_xchan']), - 'from_photo' => $message['from']['xchan_photo_s'], - 'to_name' => $message['to']['xchan_name'], - 'to_url' => chanlink_hash($message['to_xchan']), - 'to_photo' => $message['to']['xchan_photo_s'], - 'subject' => $message['title'], - 'body' => $message['body'], - 'attachments' => $s, - 'delete' => t('Delete message'), - 'dreport' => t('Delivery report'), - 'recall' => t('Recall message'), - 'can_recall' => ($channel['channel_hash'] == $message['from_xchan']), - 'is_recalled' => (intval($message['mail_recalled']) ? t('Message has been recalled.') : ''), - 'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c'), - 'sig' => base64_encode($message['sig']) - ); - - $seen = $message['seen']; - - } - - $recp = (($message['from_xchan'] === $channel['channel_hash']) ? 'to' : 'from'); - - $tpl = get_markup_template('mail_display.tpl'); - $o = replace_macros($tpl, array( - '$mailbox' => $mailbox, - '$prvmsg_header' => $message['title'], - '$thread_id' => $mid, - '$thread_subject' => $message['title'], - '$thread_seen' => $seen, - '$delete' => t('Delete Conversation'), - '$canreply' => (($unknown) ? false : '1'), - '$unknown_text' => t("No secure communications available. You <strong>may</strong> be able to respond from the sender's profile page."), - '$mails' => $mails, - - // reply - '$header' => t('Send Reply'), - '$to' => t('To:'), - '$reply' => true, - '$subject' => t('Subject:'), - '$subjtxt' => $message['title'], - '$yourmessage' => sprintf(t('Your message for %s (%s):'), $message[$recp]['xchan_name'], $message[$recp]['xchan_addr']), - '$text' => '', - '$parent' => $message['parent_mid'], - '$recphash' => $message[$recp]['xchan_hash'], - '$attach' => t('Attach file'), - '$insert' => t('Insert web link'), - '$submit' => t('Submit'), - '$defexpire' => '', - '$feature_expire' => ((feature_enabled(local_channel(),'content_expire')) ? true : false), - '$expires' => t('Set expiration date'), - '$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false), - '$encrypt' => t('Encrypt text'), - '$cipher' => $cipher, - )); - - return $o; - - } - -} diff --git a/Zotlabs/Module/Moderate.php b/Zotlabs/Module/Moderate.php index a7c98e05e..b66b052a6 100644 --- a/Zotlabs/Module/Moderate.php +++ b/Zotlabs/Module/Moderate.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + require_once('include/conversation.php'); @@ -14,7 +16,7 @@ class Moderate extends \Zotlabs\Web\Controller { return; } - \App::set_pager_itemspage(60); + \App::set_pager_itemspage(30); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); //show all items @@ -77,7 +79,7 @@ class Moderate extends \Zotlabs\Web\Controller { if($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - build_sync_packet(local_channel(),array('item' => array(encode_item($sync_item[0],true)))); + Libsync::build_sync_packet(local_channel(),array('item' => array(encode_item($sync_item[0],true)))); } if($action === 'approve') { \Zotlabs\Daemon\Master::Summon(array('Notifier', 'comment-new', $post_id)); diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 1c16e34ef..bbacbb21e 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -69,6 +69,7 @@ class Network extends \Zotlabs\Web\Controller { $category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : ''); $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : ''); $verb = ((x($_REQUEST,'verb')) ? $_REQUEST['verb'] : ''); + $dm = ((x($_REQUEST,'dm')) ? $_REQUEST['dm'] : 0); $order = get_pconfig(local_channel(), 'mod_network', 'order', 0); @@ -132,8 +133,6 @@ class Network extends \Zotlabs\Web\Controller { $pf = ((x($_GET,'pf')) ? $_GET['pf'] : ''); $unseen = ((x($_GET,'unseen')) ? $_GET['unseen'] : ''); - $deftag = ''; - if (Apps::system_app_installed(local_channel(),'Affinity Tool')) { $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); if ($affinity_locked) { @@ -159,10 +158,7 @@ class Network extends \Zotlabs\Web\Controller { goaway(z_root() . '/network'); // NOTREACHED } - if($pf) - $deftag = '!{' . (($cid_r[0]['xchan_addr']) ? $cid_r[0]['xchan_addr'] : $cid_r[0]['xchan_url']) . '}'; - else - $def_acl = [ 'allow_cid' => '<' . $cid_r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; + $def_acl = [ 'allow_cid' => '<' . $cid_r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; } if(! $update) { @@ -176,6 +172,17 @@ class Network extends \Zotlabs\Web\Controller { nav_set_selected('Network'); + $bang = '!'; + + if($cid_r) { + $forums = get_forum_channels($channel['channel_id']); + if($forums) { + $forum_xchans = ids_to_array($forums, 'xchan_hash'); + if(in_array($cid_r[0]['abook_xchan'], $forum_xchans)) + $bang = $cid_r[0]['abook_xchan']; + } + } + $channel_acl = array( 'allow_cid' => $channel['channel_allow_cid'], 'allow_gid' => $channel['channel_allow_gid'], @@ -183,7 +190,7 @@ class Network extends \Zotlabs\Web\Controller { 'deny_gid' => $channel['channel_deny_gid'] ); - $private_editing = ((($group || $cid) && (! intval($_GET['pf']))) ? true : false); + $private_editing = (($group || $cid) ? true : false); $x = array( 'is_owner' => true, @@ -193,7 +200,7 @@ class Network extends \Zotlabs\Web\Controller { 'lockstate' => (($private_editing || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), 'acl' => populate_acl((($private_editing) ? $def_acl : $channel_acl), true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'permissions' => (($private_editing) ? $def_acl : $channel_acl), - 'bang' => (($private_editing) ? '!' : ''), + 'bang' => (($private_editing) ? $bang : ''), 'visitor' => true, 'profile_uid' => local_channel(), 'editor_autocomplete' => true, @@ -202,9 +209,6 @@ class Network extends \Zotlabs\Web\Controller { 'jotnets' => true, 'reset' => t('Reset form') ); - if($deftag) - $x['pretext'] = $deftag; - $status_editor = status_editor($a,$x,false,'Network'); $o .= $status_editor; @@ -339,7 +343,7 @@ class Network extends \Zotlabs\Web\Controller { // The special div is needed for liveUpdate to kick in for this page. // 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'); if(! $maxheight) $maxheight = 400; @@ -363,6 +367,7 @@ class Network extends \Zotlabs\Web\Controller { '$conv' => (($conv) ? $conv : '0'), '$spam' => (($spam) ? $spam : '0'), '$fh' => '0', + '$dm' => (($dm) ? $dm : '0'), '$nouveau' => (($nouveau) ? $nouveau : '0'), '$wall' => '0', '$static' => $static, @@ -409,15 +414,33 @@ class Network extends \Zotlabs\Web\Controller { } } - if($verb) { - $sql_extra .= sprintf(" AND item.verb like '%s' ", - dbesc(protect_sprintf('%' . $verb . '%')) - ); + if ($verb) { + + // the presence of a leading dot in the verb determines + // whether to match the type of activity or the child object. + // The name 'verb' is a holdover from the earlier XML + // ActivityStreams specification. + + if (substr($verb,0,1) === '.') { + $verb = substr($verb,1); + $sql_extra .= sprintf(" AND item.obj_type like '%s' ", + dbesc(protect_sprintf('%' . $verb . '%')) + ); + } + else { + $sql_extra .= sprintf(" AND item.verb like '%s' ", + dbesc(protect_sprintf('%' . $verb . '%')) + ); + } } if(strlen($file)) { $sql_extra .= term_query('item',$file,TERM_FILE); } + + if ($dm) { + $sql_extra .= " AND item_private = 2 "; + } if($conv) { $item_thread_top = ''; @@ -432,7 +455,7 @@ class Network extends \Zotlabs\Web\Controller { } else { $itemspage = get_pconfig(local_channel(),'system','itemspage'); - App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10)); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); } @@ -470,7 +493,6 @@ class Network extends \Zotlabs\Web\Controller { $page_mode = 'client'; $parents_str = ''; - $update_unseen = ''; $simple_update = (($update) ? " and item_unseen = 1 " : ''); @@ -509,9 +531,6 @@ class Network extends \Zotlabs\Web\Controller { ); $parents_str = ids_to_querystr($items,'item_id'); - if($parents_str) { - $update_unseen = " AND id IN ( " . dbesc($parents_str) . " )"; - } require_once('include/items.php'); @@ -575,35 +594,6 @@ class Network extends \Zotlabs\Web\Controller { $items = array(); } - if($page_mode === 'list') { - - /** - * in "list mode", only mark the parent item and any like activities as "seen". - * We won't distinguish between comment likes and post likes. The important thing - * is that the number of unseen comments will be accurate. The SQL to separate the - * comment likes could also get somewhat hairy. - */ - - if($parents_str) { - $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; - $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; - } - } - else { - if($parents_str) { - $update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )"; - } - } - } - - if($update_unseen) { - $x = [ 'channel_id' => local_channel(), 'update' => 'unset' ]; - call_hooks('update_unseen',$x); - if($x['update'] === 'unset' || intval($x['update'])) { - $r = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d $update_unseen ", - intval(local_channel()) - ); - } } $mode = (($nouveau) ? 'network-new' : 'network'); diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php index 7572f7420..b448cff83 100644 --- a/Zotlabs/Module/Notes.php +++ b/Zotlabs/Module/Notes.php @@ -4,6 +4,7 @@ namespace Zotlabs\Module; use App; use Zotlabs\Web\Controller; use Zotlabs\Lib\Apps; +use Zotlabs\Lib\Libsync; /** * @brief Notes Module controller. @@ -38,7 +39,7 @@ class Notes extends Controller { if((argc() > 1) && (argv(1) === 'sync')) { require_once('include/zot.php'); - build_sync_packet(); + Libsync::build_sync_packet(); } logger('notes saved.', LOGGER_DEBUG); diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php index 3977ac8dd..75304161b 100644 --- a/Zotlabs/Module/Oep.php +++ b/Zotlabs/Module/Oep.php @@ -125,7 +125,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='".(($p[0]['author']['network'] === 'zot') ? 'true' : 'false') . + "' 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']) @@ -213,7 +213,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='".(($p[0]['author']['network'] === 'zot') ? 'true' : 'false') . + "' 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']) @@ -299,7 +299,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='".(($p[0]['author']['network'] === 'zot') ? 'true' : 'false') . + "' 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']) @@ -374,7 +374,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='".(($p[0]['author']['network'] === 'zot') ? 'true' : 'false') . + "' 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']) diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php index 89f83bf8f..561e35754 100644 --- a/Zotlabs/Module/Owa.php +++ b/Zotlabs/Module/Owa.php @@ -3,10 +3,12 @@ namespace Zotlabs\Module; use Zotlabs\Web\HTTPSig; +use Zotlabs\Lib\Verify; +use Zotlabs\Web\Controller; /** * OpenWebAuth verifier and token generator - * See https://macgirvin.com/wiki/mike/OpenWebAuth/Home + * See spec/OpenWebAuth/Home.md * Requests to this endpoint should be signed using HTTP Signatures * using the 'Authorization: Signature' authentication method * If the signature verifies a token is returned. @@ -14,74 +16,51 @@ use Zotlabs\Web\HTTPSig; * This token may be exchanged for an authenticated cookie. */ -class Owa extends \Zotlabs\Web\Controller { +class Owa extends Controller { function init() { $ret = [ 'success' => false ]; - foreach([ 'REDIRECT_REMOTE_USER', 'HTTP_AUTHORIZATION' ] as $head) { - if(array_key_exists($head,$_SERVER) && substr(trim($_SERVER[$head]),0,9) === 'Signature') { - if($head !== 'HTTP_AUTHORIZATION') { - $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER[$head]; - continue; - } - - $sigblock = HTTPSig::parse_sigheader($_SERVER[$head]); - if($sigblock) { - $keyId = $sigblock['keyId']; - - if($keyId) { - - // Hubzilla connections can have both zot and zot6 hublocs - // The connections will usually be zot so match those first - - $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash - where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) and hubloc_network = 'zot' ", - dbesc(str_replace('acct:','',$keyId)), - dbesc($keyId) - ); + if (array_key_exists('REDIRECT_REMOTE_USER',$_SERVER) && (! array_key_exists('HTTP_AUTHORIZATION',$_SERVER))) { + $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['REDIRECT_REMOTE_USER']; + } - // If nothing was found, try searching on any network - - if (! $r) { + if (array_key_exists('HTTP_AUTHORIZATION',$_SERVER) && substr(trim($_SERVER['HTTP_AUTHORIZATION']),0,9) === 'Signature') { + $sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']); + if ($sigblock) { + $keyId = $sigblock['keyId']; + if ($keyId) { + $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash + where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ", + dbesc(str_replace('acct:','',$keyId)), + 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_addr = '%s' or hubloc_id_url = '%s' )", + where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ", dbesc(str_replace('acct:','',$keyId)), dbesc($keyId) ); } - - // If nothing was found on any network, use network discovery and create a new record - - 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_addr = '%s' or hubloc_id_url = '%s' ) ", - dbesc(str_replace('acct:','',$keyId)), - dbesc($keyId) - ); - } - } - - if ($r) { - foreach($r as $hubloc) { - $verified = HTTPSig::verify(file_get_contents('php://input'),$hubloc['xchan_pubkey']); - if($verified && $verified['header_signed'] && $verified['header_valid']) { - logger('OWA header: ' . print_r($verified,true),LOGGER_DATA); - logger('OWA success: ' . $hubloc['hubloc_addr'],LOGGER_DATA); - $ret['success'] = true; - $token = random_string(32); - \Zotlabs\Lib\Verify::create('owt',0,$token,$hubloc['hubloc_network'] . ',' . $hubloc['hubloc_addr']); - $result = ''; - openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']); - $ret['encrypted_token'] = base64url_encode($result); - break; - } - else { - logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_addr']); - } + } + if ($r) { + foreach ($r as $hubloc) { + $verified = HTTPSig::verify(file_get_contents('php://input')); + if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) { + logger('OWA header: ' . print_r($verified,true),LOGGER_DATA); + logger('OWA success: ' . $hubloc['hubloc_addr'],LOGGER_DATA); + $ret['success'] = true; + $token = random_string(32); + Verify::create('owt',0,$token,$hubloc['hubloc_addr']); + $result = ''; + openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']); + $ret['encrypted_token'] = base64url_encode($result); + break; + } else { + logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_addr']); } } } diff --git a/Zotlabs/Module/Pconfig.php b/Zotlabs/Module/Pconfig.php index 06b94b34f..b2b5d4386 100644 --- a/Zotlabs/Module/Pconfig.php +++ b/Zotlabs/Module/Pconfig.php @@ -1,7 +1,7 @@ <?php namespace Zotlabs\Module; - +use Zotlabs\Lib\Libsync; @@ -38,7 +38,7 @@ class Pconfig extends \Zotlabs\Web\Controller { } set_pconfig(local_channel(),$cat,$k,$v); - build_sync_packet(); + Libsync::build_sync_packet(); if($aj) killme(); diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php index 5cedb29a8..36201544f 100644 --- a/Zotlabs/Module/Pdledit.php +++ b/Zotlabs/Module/Pdledit.php @@ -4,6 +4,7 @@ namespace Zotlabs\Module; use App; use Zotlabs\Web\Controller; use Zotlabs\Lib\Apps; +use Zotlabs\Lib\Libsync; class Pdledit extends Controller { @@ -22,7 +23,7 @@ class Pdledit extends Controller { goaway(z_root() . '/pdledit'); } set_pconfig(local_channel(),'system','mod_' . $_REQUEST['module'] . '.pdl',escape_tags($_REQUEST['content'])); - build_sync_packet(); + Libsync::build_sync_packet(); info( t('Layout updated.') . EOL); goaway(z_root() . '/pdledit/' . $_REQUEST['module']); } diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php index 75ac2ac87..6a599282c 100644 --- a/Zotlabs/Module/Permcats.php +++ b/Zotlabs/Module/Permcats.php @@ -5,6 +5,7 @@ namespace Zotlabs\Module; use App; use Zotlabs\Web\Controller; use Zotlabs\Lib\Apps; +use Zotlabs\Lib\Libsync; class Permcats extends Controller { @@ -42,7 +43,7 @@ class Permcats extends Controller { \Zotlabs\Lib\Permcat::update(local_channel(),$name,$pcarr); - build_sync_packet(); + Libsync::build_sync_packet(); info( t('Permission category saved.') . EOL); @@ -71,7 +72,7 @@ class Permcats extends Controller { if(argc() > 2 && argv(2) === 'drop') { \Zotlabs\Lib\Permcat::delete(local_channel(),$name); - build_sync_packet(); + Libsync::build_sync_packet(); json_return_and_die([ 'success' => true ]); } diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index 48e2bf4a5..c88696578 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -67,18 +67,20 @@ class Photo extends \Zotlabs\Web\Controller { $data = ''; - $r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1", - intval($resolution), - intval($uid), - intval(PHOTO_PROFILE) - ); - if($r) { - $modified = strtotime($r[0]['edited'] . "Z"); - $mimetype = $r[0]['mimetype']; - if(intval($r[0]['os_storage'])) - $data = file_get_contents(dbunescbin($r[0]['content'])); - else - $data = dbunescbin($r[0]['content']); + if ($uid > 0) { + $r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1", + intval($resolution), + intval($uid), + intval(PHOTO_PROFILE) + ); + if($r) { + $modified = strtotime($r[0]['edited'] . "Z"); + $mimetype = $r[0]['mimetype']; + if(intval($r[0]['os_storage'])) + $data = file_get_contents(dbunescbin($r[0]['content'])); + else + $data = dbunescbin($r[0]['content']); + } } if(! $data) { @@ -213,7 +215,7 @@ class Photo extends \Zotlabs\Web\Controller { if(! $data) killme(); - + $etag = '"' . md5($data . $modified) . '"'; if($modified == 0) @@ -269,7 +271,7 @@ class Photo extends \Zotlabs\Web\Controller { // in the event that infrastructure caching is present. $smaxage = intval($maxage/12); - header("Cache-Control: s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol); + header("Cache-Control: no-cache, s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol); } diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 43c9f86ee..fa9216c97 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + require_once('include/photo/photo_driver.php'); require_once('include/photos.php'); require_once('include/items.php'); @@ -162,7 +164,7 @@ class Photos extends \Zotlabs\Web\Controller { $sync = attach_export_data(\App::$data['channel'],$folder_hash, true); if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); + Libsync::build_sync_packet($page_owner_uid,array('file' => array($sync))); } } @@ -189,7 +191,7 @@ class Photos extends \Zotlabs\Web\Controller { $sync = attach_export_data(\App::$data['channel'],$r[0]['resource_id'], true); if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); + Libsync::build_sync_packet($page_owner_uid,array('file' => array($sync))); } elseif(is_site_admin()) { // If the admin deletes a photo, don't sync @@ -208,9 +210,9 @@ class Photos extends \Zotlabs\Web\Controller { if(($m) && ($m[0]['folder'] != $_POST['move_to_album'])) { attach_move($page_owner_uid,argv(2),$_POST['move_to_album']); - $sync = attach_export_data(\App::$data['channel'],argv(2),true); + $sync = attach_export_data(\App::$data['channel'], argv(2), false); if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); + Libsync::build_sync_packet($page_owner_uid,array('file' => array($sync))); if(! ($_POST['desc'] && $_POST['newtag'])) goaway(z_root() . '/' . $_SESSION['photo_return']); @@ -420,7 +422,7 @@ class Photos extends \Zotlabs\Web\Controller { $sync = attach_export_data(\App::$data['channel'],$resource_id); if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); + Libsync::build_sync_packet($page_owner_uid,array('file' => array($sync))); goaway(z_root() . '/' . $_SESSION['photo_return']); return; // NOTREACHED @@ -706,7 +708,7 @@ class Photos extends \Zotlabs\Web\Controller { ]); if($x = photos_album_exists($owner_uid, get_observer_hash(), $datum)) { - \App::set_pager_itemspage(60); + \App::set_pager_itemspage(30); $album = $x['display_path']; } else { @@ -1287,7 +1289,7 @@ class Photos extends \Zotlabs\Web\Controller { \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n"; - \App::set_pager_itemspage(60); + \App::set_pager_itemspage(30); $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.album, p.imgscale, p.created, p.display_path FROM photo p diff --git a/Zotlabs/Module/Pin.php b/Zotlabs/Module/Pin.php new file mode 100644 index 000000000..63b28754b --- /dev/null +++ b/Zotlabs/Module/Pin.php @@ -0,0 +1,69 @@ +<?php +namespace Zotlabs\Module; + +/* + * Pinned post processing + */ + +use App; + +class Pin extends \Zotlabs\Web\Controller { + + + function init() { + + if(argc() !== 2) + http_status_exit(400, 'Bad request'); + } + + + function post() { + + $item_id = intval($_POST['id']); + + if ($item_id <= 0) + http_status_exit(404, 'Not found'); + + $observer = \App::get_observer(); + if(! $observer) + http_status_exit(403, 'Forbidden'); + + $r = q("SELECT * FROM item WHERE id = %d AND id = parent AND item_private = 0 LIMIT 1", + $item_id + ); + if(! $r) { + notice(t('Unable to locate original post.')); + http_status_exit(404, 'Not found'); + } + + $midb64 = 'b64.' . base64url_encode($r[0]['mid']); + $pinned = (in_array($midb64, get_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], [])) ? true : false); + + switch(argv(1)) { + + case 'pin': + if(! local_channel() || (local_channel() != $r[0]['uid'] && local_channel() != is_site_admin())) + http_status_exit(403, 'Forbidden'); + // Currently allow only one pinned item for each type + set_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], ($pinned ? [] : [ $midb64 ])); + if($pinned) + del_pconfig($r[0]['uid'], 'pinned_hide', $midb64); + break; + + case 'hide': + if($pinned) { + $hidden = get_pconfig($r[0]['uid'], 'pinned_hide', $midb64, []); + if(! in_array($observer['xchan_hash'], $hidden)) { + $hidden[] = $observer['xchan_hash']; + set_pconfig($r[0]['uid'], 'pinned_hide', $midb64, $hidden); + } + } + break; + + default: + http_status_exit(404, 'Not found'); + } + + build_sync_packet($r[0]['uid'], [ 'config' ]); + } +} diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php index a812ca210..d6c80b653 100644 --- a/Zotlabs/Module/Profile_photo.php +++ b/Zotlabs/Module/Profile_photo.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + /* * @file Profile_photo.php * @brief Module-file with functions for handling of profile-photos @@ -73,7 +75,7 @@ class Profile_photo extends \Zotlabs\Web\Controller { $sync = attach_export_data($channel,$r[0]['resource_id']); if($sync) - build_sync_packet($channel['channel_id'],array('file' => array($sync))); + Libsync:: build_sync_packet($channel['channel_id'],array('file' => array($sync))); } $_SESSION['reload_avatar'] = true; @@ -243,7 +245,7 @@ class Profile_photo extends \Zotlabs\Web\Controller { $sync = attach_export_data($channel,$base_image['resource_id']); if($sync) - build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles)); + Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles)); // Similarly, tell the nav bar to bypass the cache and update the avatar image. @@ -411,7 +413,7 @@ class Profile_photo extends \Zotlabs\Web\Controller { $sync = attach_export_data($channel,$resource_id); if($sync) - build_sync_packet($channel['channel_id'],array('file' => array($sync))); + Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); $_SESSION['reload_avatar'] = true; diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php index 33e7d8a9d..9ac0e725e 100644 --- a/Zotlabs/Module/Profiles.php +++ b/Zotlabs/Module/Profiles.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + require_once('include/channel.php'); require_once('include/selectors.php'); @@ -599,16 +601,16 @@ class Profiles extends \Zotlabs\Web\Controller { ); if($r) { require_once('include/zot.php'); - build_sync_packet(local_channel(),array('profile' => $r)); + 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_hash = '%s'", + $r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'", dbesc($name), dbesc(datetime_convert()), - dbesc($channel['xchan_hash']) + dbesc(z_root() . '/channel/' . $channel['channel_address']) ); $r = q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'", dbesc($name), diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 84ac42f72..55c96b23d 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -62,6 +62,11 @@ class Pubstream extends \Zotlabs\Web\Controller { $static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0); $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') : '') + )); + + $o = (($hashtags) ? $title : ''); if(local_channel() && (! $update)) { @@ -94,7 +99,7 @@ class Pubstream extends \Zotlabs\Web\Controller { 'reset' => t('Reset form') ); - $o = '<div id="jot-popup">'; + $o .= '<div id="jot-popup">'; $o .= status_editor($a,$x,false,'Pubstream'); $o .= '</div>'; } @@ -139,6 +144,7 @@ class Pubstream extends \Zotlabs\Web\Controller { '$conv' => '0', '$spam' => '0', '$fh' => '1', + '$dm' => '0', '$nouveau' => '0', '$wall' => '0', '$list' => '0', @@ -163,7 +169,7 @@ class Pubstream extends \Zotlabs\Web\Controller { $pager_sql = ''; } else { - \App::set_pager_itemspage(20); + \App::set_pager_itemspage(10); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); } @@ -258,7 +264,6 @@ class Pubstream extends \Zotlabs\Web\Controller { // Then fetch all the children of the parents that are on this page $parents_str = ''; - $update_unseen = ''; if($r) { @@ -285,7 +290,7 @@ class Pubstream extends \Zotlabs\Web\Controller { } // fake it - $mode = ('pubstream'); + $mode = (($hashtags) ? 'search' : 'pubstream'); $o .= conversation($items,$mode,$update,$page_mode); diff --git a/Zotlabs/Module/Regdir.php b/Zotlabs/Module/Regdir.php index f4d16c562..e49f89231 100644 --- a/Zotlabs/Module/Regdir.php +++ b/Zotlabs/Module/Regdir.php @@ -1,6 +1,9 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Zotfinger; +use Zotlabs\Web\Controller; + /** * With args, register a directory server for this realm. * With no args, return a JSON array of directory servers for this realm. @@ -14,7 +17,7 @@ namespace Zotlabs\Module; * @param App &$a */ -class Regdir extends \Zotlabs\Web\Controller { +class Regdir extends Controller { function init() { @@ -25,7 +28,7 @@ class Regdir extends \Zotlabs\Web\Controller { $valid = 0; // we probably don't need the realm as we will find out in the probe. - // What we may want to die is throw an error if you're trying to register in a different realm + // What we may want to do is throw an error if you're trying to register in a different realm // so this configuration issue can be discovered. $realm = $_REQUEST['realm']; @@ -59,34 +62,28 @@ class Regdir extends \Zotlabs\Web\Controller { json_return_and_die($result); } - $j = \Zotlabs\Zot\Finger::run('[system]@' . $m['host']); - if($j['success'] && $j['guid']) { - $x = import_xchan($j); - if($x['success']) { - $result['success'] = true; - } + $j = Zotfinger::exec($url); + if($j) { + $result['success'] = true; } - - if(! $result['success']) + else { $valid = 0; - + } + q("update site set site_valid = %d where site_url = '%s'", intval($valid), strtolower($url) ); - + json_return_and_die($result); - } else { - - // We can put this in the sql without the condition after 31 august 2015 assuming - // most directory servers will have updated by then - // This just makes sure it happens if I forget + + } + else { - $sql_extra = ((datetime_convert() > datetime_convert('UTC','UTC','2015-08-31')) ? ' and site_valid = 1 ' : '' ); if ($dirmode == DIRECTORY_MODE_STANDALONE) { $r = array(array('site_url' => z_root())); } else { - $r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s' and site_type = %d $sql_extra ", + $r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s' and site_type = %d and site_valid = 1 ", dbesc(get_directory_realm()), intval(SITE_TYPE_ZOT) ); diff --git a/Zotlabs/Module/Register.php b/Zotlabs/Module/Register.php index bc813f8e1..278cf15ca 100644 --- a/Zotlabs/Module/Register.php +++ b/Zotlabs/Module/Register.php @@ -118,7 +118,7 @@ class Register extends Controller { $invite_code = ((x($_POST,'invite_code')) ? notags(trim($_POST['invite_code'])) : ''); if($using_invites && $invite_code) { - q("delete * from register where hash = '%s'", dbesc($invite_code)); + q("delete from register where hash = '%s'", dbesc($invite_code)); // @FIXME - this also needs to be considered when using 'invites_remaining' in mod/invite.php set_aconfig($result['account']['account_id'],'system','invites_remaining',$num_invites); } diff --git a/Zotlabs/Module/Removeaccount.php b/Zotlabs/Module/Removeaccount.php index 9d2bbd0de..cd18b79c0 100644 --- a/Zotlabs/Module/Removeaccount.php +++ b/Zotlabs/Module/Removeaccount.php @@ -37,7 +37,7 @@ class Removeaccount extends \Zotlabs\Web\Controller { } } - $global_remove = intval($_POST['global']); + $global_remove = 0; //intval($_POST['global']); account_remove($account_id, 1 - $global_remove); } @@ -57,7 +57,7 @@ class Removeaccount extends \Zotlabs\Web\Controller { '$title' => t('Remove This Account'), '$desc' => array(t('WARNING: '), t('This account and all its channels will be completely removed from the network. '), t('This action is permanent and can not be undone!')), '$passwd' => t('Please enter your password for verification:'), - '$global' => array('global', t('Remove this account, all its channels and all its channel clones from the network'), false, t('By default only the instances of the channels located on this hub will be removed from the network')), + // '$global' => array('global', t('Remove this account, all its channels and all its channel clones from the network'), false, t('By default only the instances of the channels located on this hub will be removed from the network')), '$submit' => t('Remove Account') )); diff --git a/Zotlabs/Module/Removeme.php b/Zotlabs/Module/Removeme.php index 451e280c3..876d61ca6 100644 --- a/Zotlabs/Module/Removeme.php +++ b/Zotlabs/Module/Removeme.php @@ -37,7 +37,7 @@ class Removeme extends \Zotlabs\Web\Controller { } } - $global_remove = intval($_POST['global']); + $global_remove = 0; //intval($_POST['global']); channel_remove(local_channel(),1 - $global_remove,true); @@ -60,7 +60,7 @@ class Removeme extends \Zotlabs\Web\Controller { '$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!') ], '$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') ] ], + // '$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') )); diff --git a/Zotlabs/Module/Rmagic.php b/Zotlabs/Module/Rmagic.php index 8c1e5cdab..ab9ad059e 100644 --- a/Zotlabs/Module/Rmagic.php +++ b/Zotlabs/Module/Rmagic.php @@ -1,6 +1,7 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libzot; class Rmagic extends \Zotlabs\Web\Controller { @@ -11,23 +12,24 @@ class Rmagic extends \Zotlabs\Web\Controller { $me = get_my_address(); if($me) { - $r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1", + $r = q("select hubloc_url from hubloc where hubloc_addr = '%s'", dbesc($me) ); if(! $r) { $w = discover_by_webbie($me); if($w) { - $r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1", + $r = q("select hubloc_url from hubloc where hubloc_addr = '%s'", dbesc($me) ); } } - if($r) { - if($r[0]['hubloc_url'] === z_root()) + if($r) { + $r = Libzot::zot_record_preferred($r); + if($r['hubloc_url'] === z_root()) goaway(z_root() . '/login'); $dest = bin2hex(z_root() . '/' . str_replace(['rmagic','zid='],['','zid_='],\App::$query_string)); - goaway($r[0]['hubloc_url'] . '/magic' . '?f=&owa=1&bdest=' . $dest); + goaway($r['hubloc_url'] . '/magic' . '?f=&owa=1&bdest=' . $dest); } } } @@ -55,13 +57,13 @@ class Rmagic extends \Zotlabs\Web\Controller { $r = null; if($address) { - $r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1", + $r = q("select hubloc_url from hubloc where hubloc_addr = '%s'", dbesc($address) ); if(! $r) { $w = discover_by_webbie($address); if($w) { - $r = q("select hubloc_url from hubloc where hubloc_addr = '%s' limit 1", + $r = q("select hubloc_url from hubloc where hubloc_addr = '%s'", dbesc($address) ); } @@ -69,7 +71,8 @@ class Rmagic extends \Zotlabs\Web\Controller { } if($r) { - $url = $r[0]['hubloc_url']; + $r = Libzot::zot_record_preferred($r); + $url = $r['hubloc_url']; } else { $url = 'https://' . substr($address,strpos($address,'@')+1); diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php index 214ece9a3..d586ae12f 100644 --- a/Zotlabs/Module/Search.php +++ b/Zotlabs/Module/Search.php @@ -128,6 +128,7 @@ class Search extends \Zotlabs\Web\Controller { '$conv' => '0', '$spam' => '0', '$fh' => '0', + '$dm' => '0', '$nouveau' => '0', '$wall' => '0', '$static' => $static, @@ -158,7 +159,7 @@ class Search extends \Zotlabs\Web\Controller { if(($update) && ($load)) { $itemspage = get_pconfig(local_channel(),'system','itemspage'); - \App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + \App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10)); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); // in case somebody turned off public access to sys channel content with permissions diff --git a/Zotlabs/Module/Settings/Calendar.php b/Zotlabs/Module/Settings/Calendar.php index 0298b412e..ab85eb450 100644 --- a/Zotlabs/Module/Settings/Calendar.php +++ b/Zotlabs/Module/Settings/Calendar.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Calendar { @@ -15,7 +16,7 @@ class Calendar { process_module_features_post(local_channel(), $features, $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index b0115d352..2eed1efc9 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -3,6 +3,7 @@ namespace Zotlabs\Module\Settings; use Zotlabs\Lib\Apps; +use Zotlabs\Lib\Libsync; require_once('include/selectors.php'); @@ -273,10 +274,11 @@ class Channel { } if($name_change) { - $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'", + // 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($channel['channel_hash']) + dbesc(z_root() . '/channel/' . $channel['channel_address']) ); $r = q("update profile set fullname = '%s' where uid = %d and is_default = 1", dbesc($username), @@ -286,7 +288,7 @@ class Channel { \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel())); - build_sync_packet(); + Libsync::build_sync_packet(); if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) { diff --git a/Zotlabs/Module/Settings/Channel_home.php b/Zotlabs/Module/Settings/Channel_home.php index b6ecf4ff1..e8faa7fb2 100644 --- a/Zotlabs/Module/Settings/Channel_home.php +++ b/Zotlabs/Module/Settings/Channel_home.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; + require_once('include/menu.php'); class Channel_home { @@ -24,7 +26,7 @@ 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); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Connections.php b/Zotlabs/Module/Settings/Connections.php index cac357791..4369deb27 100644 --- a/Zotlabs/Module/Settings/Connections.php +++ b/Zotlabs/Module/Settings/Connections.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Connections { @@ -15,7 +16,7 @@ class Connections { process_module_features_post(local_channel(), $features, $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Conversation.php b/Zotlabs/Module/Settings/Conversation.php index 43e59a3c2..aa0ff6a7e 100644 --- a/Zotlabs/Module/Settings/Conversation.php +++ b/Zotlabs/Module/Settings/Conversation.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Conversation { @@ -15,7 +16,7 @@ class Conversation { process_module_features_post(local_channel(), $features, $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['aj']) { if($_POST['auto_update'] == 1) diff --git a/Zotlabs/Module/Settings/Directory.php b/Zotlabs/Module/Settings/Directory.php index 13fe6eb79..d1dd0677e 100644 --- a/Zotlabs/Module/Settings/Directory.php +++ b/Zotlabs/Module/Settings/Directory.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Directory { @@ -15,7 +16,7 @@ class Directory { process_module_features_post(local_channel(), $features, $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php index 45d80e011..01ae8652a 100644 --- a/Zotlabs/Module/Settings/Display.php +++ b/Zotlabs/Module/Settings/Display.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Display { @@ -35,9 +36,9 @@ class Display { if($browser_update < 10000) $browser_update = 10000; - $itemspage = ((x($_POST,'itemspage')) ? intval($_POST['itemspage']) : 20); - if($itemspage > 100) - $itemspage = 100; + $itemspage = ((x($_POST,'itemspage')) ? intval($_POST['itemspage']) : 10); + if($itemspage > 30) + $itemspage = 30; set_pconfig(local_channel(),'system','preload_images',$preload_images); @@ -78,7 +79,7 @@ class Display { ); call_hooks('display_settings_post', $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); goaway(z_root() . '/settings/display' ); return; // NOTREACHED } @@ -158,7 +159,7 @@ class Display { $browser_update = (($browser_update == 0) ? 80 : $browser_update / 1000); // default if not set: 40 seconds $itemspage = intval(get_pconfig(local_channel(), 'system','itemspage')); - $itemspage = (($itemspage > 0 && $itemspage < 101) ? $itemspage : 20); // default if not set: 20 items + $itemspage = (($itemspage > 0 && $itemspage <= 30) ? $itemspage : 10); // default if not set: 10 items $nosmile = get_pconfig(local_channel(),'system','no_smilies'); $nosmile = (($nosmile===false)? '0': $nosmile); // default if not set: 0 @@ -196,7 +197,7 @@ class Display { '$preload_images' => array('preload_images', t("Preload images before rendering the page"), $preload_images, t("The subjective page load time will be longer but the page will be ready when displayed"), $yes_no), '$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, '', $yes_no), '$ajaxint' => array('browser_update', t("Update browser every xx seconds"), $browser_update, t('Minimum of 10 seconds, no maximum')), - '$itemspage' => array('itemspage', t("Maximum number of conversations to load at any time:"), $itemspage, t('Maximum of 100 items')), + '$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 ], '$manual_update' => array('manual_update', t('Manual conversation updates'), channel_manual_conv_update(local_channel()), t('Default is on, turning this off may increase screen jumping'), $yes_no), diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php index 5e7a9473a..cf6dd2807 100644 --- a/Zotlabs/Module/Settings/Editor.php +++ b/Zotlabs/Module/Settings/Editor.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Editor { @@ -15,7 +16,7 @@ class Editor { process_module_features_post(local_channel(), $features, $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Events.php b/Zotlabs/Module/Settings/Events.php index eb6dda99b..ab393c932 100644 --- a/Zotlabs/Module/Settings/Events.php +++ b/Zotlabs/Module/Settings/Events.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Events { @@ -15,7 +16,7 @@ class Events { process_module_features_post(local_channel(), $features, $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Featured.php b/Zotlabs/Module/Settings/Featured.php index d5d740aff..d615e176c 100644 --- a/Zotlabs/Module/Settings/Featured.php +++ b/Zotlabs/Module/Settings/Featured.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Featured { @@ -10,7 +11,7 @@ class Featured { call_hooks('feature_settings_post', $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); return; } diff --git a/Zotlabs/Module/Settings/Features.php b/Zotlabs/Module/Settings/Features.php index 6a3ab104b..553ff0836 100644 --- a/Zotlabs/Module/Settings/Features.php +++ b/Zotlabs/Module/Settings/Features.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; + class Features { @@ -19,7 +21,7 @@ class Features { set_pconfig(local_channel(),'feature', $k, ''); } } - build_sync_packet(); + Libsync::build_sync_packet(); return; } diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php index 9bae12022..cbc494cf8 100644 --- a/Zotlabs/Module/Settings/Manage.php +++ b/Zotlabs/Module/Settings/Manage.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; + class Manage { @@ -15,7 +17,7 @@ class Manage { process_module_features_post(local_channel(), $features, $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index ae02b06e9..9f5bdb2e5 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Network { @@ -21,7 +22,7 @@ class Network { set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Photos.php b/Zotlabs/Module/Settings/Photos.php index 9edbaa929..8195d660b 100644 --- a/Zotlabs/Module/Settings/Photos.php +++ b/Zotlabs/Module/Settings/Photos.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; class Photos { @@ -15,7 +16,7 @@ class Photos { process_module_features_post(local_channel(), $features, $_POST); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php index fb6abf664..67b03e04f 100644 --- a/Zotlabs/Module/Settings/Profiles.php +++ b/Zotlabs/Module/Settings/Profiles.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Libsync; + require_once('include/selectors.php'); class Profiles { @@ -19,7 +21,7 @@ class Profiles { $profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : ''); set_pconfig(local_channel(),'system','profile_assign',$profile_assign); - build_sync_packet(); + Libsync::build_sync_packet(); if($_POST['rpath']) goaway($_POST['rpath']); diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index a18a81937..c0db9978e 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -4,6 +4,7 @@ namespace Zotlabs\Module; use App; use Zotlabs\Daemon\Master; use Zotlabs\Lib\Activity; +use Zotlabs\Lib\Libsync; require_once('include/security.php'); @@ -124,7 +125,7 @@ class Share extends \Zotlabs\Web\Controller { if($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]); + Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]); } Master::Summon([ 'Notifier','like',$post_id ]); diff --git a/Zotlabs/Module/Sharedwithme.php b/Zotlabs/Module/Sharedwithme.php index c986f6695..4211a3af8 100644 --- a/Zotlabs/Module/Sharedwithme.php +++ b/Zotlabs/Module/Sharedwithme.php @@ -1,5 +1,8 @@ <?php namespace Zotlabs\Module; + +use Zotlabs\Web\Controller; + require_once('include/conversation.php'); require_once('include/text.php'); @@ -9,7 +12,7 @@ require_once('include/text.php'); * */ -class Sharedwithme extends \Zotlabs\Web\Controller { +class Sharedwithme extends Controller { function get() { if(! local_channel()) { @@ -20,81 +23,80 @@ class Sharedwithme extends \Zotlabs\Web\Controller { $channel = \App::get_channel(); $is_owner = (local_channel() && (local_channel() == $channel['channel_id'])); - - //check for updated items and remove them - require_once('include/sharedwithme.php'); - apply_updates(); + + $item_normal = item_normal(); //drop single file - localuser if((argc() > 2) && (argv(2) === 'drop')) { - + $id = intval(argv(1)); - - q("DELETE FROM item WHERE id = %d AND uid = %d", - intval($id), - intval(local_channel()) - ); - + + drop_item($id); + goaway(z_root() . '/sharedwithme'); + } //drop all files - localuser if((argc() > 1) && (argv(1) === 'dropall')) { - - q("DELETE FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d", + + $r = q("SELECT id FROM item WHERE verb = '%s' AND obj_type IN ('Document', 'Video', 'Audio', 'Image') AND uid = %d AND owner_xchan != '%s' $item_normal", dbesc(ACTIVITY_POST), - dbesc(ACTIVITY_OBJ_FILE), - intval(local_channel()) + intval(local_channel()), + dbesc($channel['channel_hash']) ); - + + $ids = ids_to_array($r); + + if($ids) + drop_items($ids); + goaway(z_root() . '/sharedwithme'); + } - + //list files - $r = q("SELECT id, uid, obj, item_unseen FROM item WHERE verb = '%s' AND obj_type = '%s' AND uid = %d AND owner_xchan != '%s'", + $r = q("SELECT id, uid, obj, item_unseen FROM item WHERE verb = '%s' AND obj_type IN ('Document', 'Video', 'Audio', 'Image') AND uid = %d AND owner_xchan != '%s' $item_normal", dbesc(ACTIVITY_POST), - dbesc(ACTIVITY_OBJ_FILE), intval(local_channel()), dbesc($channel['channel_hash']) ); - - $items =array(); - $ids = ''; - + + $items = []; + $ids = []; + if($r) { foreach($r as $rr) { $object = json_decode($rr['obj'],true); - - $item = array(); + $meta = self::get_meta($object); + + $item = []; $item['id'] = $rr['id']; - $item['objfiletype'] = $object['filetype']; - $item['objfiletypeclass'] = getIconFromType($object['filetype']); - $item['objurl'] = rawurldecode(get_rel_link($object['link'],'alternate')) . '?f=&zid=' . $channel['xchan_addr']; - $item['objfilename'] = $object['filename']; - $item['objfilesize'] = userReadableSize($object['filesize']); - $item['objedited'] = $object['edited']; + $item['objfiletype'] = $meta['type']; + $item['objfiletypeclass'] = getIconFromType($meta['type']); + $item['objurl'] = $meta['path'] . '?f=&zid=' . $channel['xchan_addr']; + $item['objfilename'] = $object['name']; + $item['objfilesize'] = userReadableSize($meta['size']); + $item['objedited'] = $meta['edited']; $item['unseen'] = $rr['item_unseen']; $items[] = $item; - if($item['unseen'] > 0) { - $ids .= " '" . $rr['id'] . "',"; + if($item['unseen']) { + $ids[] = $rr['id']; } } } - + + $ids = implode(',', $ids); + if($ids) { - - //remove trailing , - $ids = rtrim($ids, ","); - q("UPDATE item SET item_unseen = 0 WHERE id IN ( $ids ) AND uid = %d", intval(local_channel()) ); - } $o = ''; @@ -114,5 +116,22 @@ class Sharedwithme extends \Zotlabs\Web\Controller { } + function get_meta($object) { + + $ret = []; + + if(! is_array($object['attachment'])) + return; + + foreach($object['attachment'] as $a) { + if($a['name'] === 'zot.attach.meta') { + $ret = $a['value']; + break; + } + } + + return $ret; + + } } diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php new file mode 100644 index 000000000..b68fe6705 --- /dev/null +++ b/Zotlabs/Module/Sse.php @@ -0,0 +1,121 @@ +<?php + +namespace Zotlabs\Module; + +use App; +use Zotlabs\Lib\Apps; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\Enotify; +use Zotlabs\Lib\XConfig; + +class Sse extends Controller { + + public static $uid; + public static $ob_hash; + public static $sse_id; + public static $vnotify; + + function init() { + + if((observer_prohibited(true))) { + killme(); + } + + if(! intval(get_config('system','open_pubstream',1))) { + if(! get_observer_hash()) { + killme(); + } + } + + // this is important! + session_write_close(); + + self::$uid = local_channel(); + self::$ob_hash = get_observer_hash(); + self::$sse_id = false; + + if(! self::$ob_hash) { + if(session_id()) { + self::$sse_id = true; + self::$ob_hash = 'sse_id.' . session_id(); + } + else { + return; + } + } + + self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify'); + + $sys = get_sys_channel(); + $sleep_seconds = 3; + + header("Content-Type: text/event-stream"); + header("Cache-Control: no-cache"); + header("Connection: keep-alive"); + header("X-Accel-Buffering: no"); + + while(true) { + + /** + * Update chat presence indication (if applicable) + */ + + if(! self::$sse_id) { + $r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1", + dbesc(self::$ob_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(self::$ob_hash), + dbesc(datetime_convert()), + dbesc('online'), + dbesc($_SERVER['REMOTE_ADDR']) + ); + } + } + + XConfig::Load(self::$ob_hash); + + $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []); + $lock = XConfig::Get(self::$ob_hash, 'sse', 'lock'); + + if($result && !$lock) { + echo "event: notifications\n"; + echo 'data: ' . json_encode($result); + echo "\n\n"; + + XConfig::Set(self::$ob_hash, 'sse', 'notifications', []); + unset($result); + } + + // always send heartbeat to detect disconnected clients + echo "event: heartbeat\n"; + echo 'data: {}'; + echo "\n\n"; + + ob_end_flush(); + flush(); + + if(connection_status() != CONNECTION_NORMAL || connection_aborted()) { + //TODO: this does not seem to be triggered + XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE); + break; + } + + sleep($sleep_seconds); + + } + + } + +} diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php new file mode 100644 index 000000000..287c24829 --- /dev/null +++ b/Zotlabs/Module/Sse_bs.php @@ -0,0 +1,691 @@ +<?php + +namespace Zotlabs\Module; + +use App; +use Zotlabs\Lib\Apps; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\Enotify; + +class Sse_bs extends Controller { + + public static $uid; + public static $ob_hash; + public static $sse_id; + public static $vnotify; + public static $evdays; + public static $limit; + public static $offset; + public static $xchans; + + function init() { + + self::$uid = local_channel(); + self::$ob_hash = get_observer_hash(); + self::$sse_id = false; + + if(! self::$ob_hash) { + if(session_id()) { + self::$sse_id = true; + self::$ob_hash = 'sse_id.' . session_id(); + } + else { + return; + } + } + + self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify', -1); + self::$evdays = intval(get_pconfig(self::$uid, 'system', 'evdays')); + self::$limit = 50; + self::$offset = 0; + self::$xchans = ''; + + if($_REQUEST['sse_rmids']) + self::mark_read($_REQUEST['sse_rmids']); + + if(!empty($_REQUEST['nquery']) && $_REQUEST['nquery'] !== '%') { + $nquery = $_REQUEST['nquery']; + + $x = q("SELECT xchan_hash FROM xchan WHERE xchan_name LIKE '%s' OR xchan_addr LIKE '%s'", + dbesc($nquery . '%'), + dbesc($nquery . '%') + ); + + self::$xchans = ids_to_querystr($x, 'xchan_hash', true); + } + + if(intval(argv(2)) > 0) + self::$offset = argv(2); + else + $_SESSION['sse_loadtime'] = datetime_convert(); + + $network = false; + $dm = false; + $home = false; + $pubs = false; + $f = ''; + + switch (argv(1)) { + case 'network': + $network = true; + $f = 'bs_network'; + break; + case 'dm': + $dm = true; + $f = 'bs_dm'; + break; + case 'home': + $home = true; + $f = 'bs_home'; + break; + case 'pubs': + $pubs = true; + $f = 'bs_pubs'; + break; + default: + } + + if(self::$offset && $f) { + $result = self::$f(true); + json_return_and_die($result); + } + + $result = array_merge( + self::bs_network($network), + self::bs_dm($dm), + self::bs_home($home), + self::bs_notify(), + self::bs_intros(), + self::bs_forums(), + self::bs_pubs($pubs), + self::bs_files(), + self::bs_mail(), + self::bs_all_events(), + self::bs_register() + ); + + set_xconfig(self::$ob_hash, 'sse', 'timestamp', datetime_convert()); + set_xconfig(self::$ob_hash, 'sse', 'notifications', []); // reset the cache + set_xconfig(self::$ob_hash, 'sse', 'language', App::$language); + + json_return_and_die($result); + } + + function mark_read($arr) { + + if(! self::$uid) + return; + + $mids = []; + $str = ''; + + foreach($arr as $a) { + $mids[] = '\'' . dbesc(@base64url_decode(substr($a,4))) . '\''; + } + + $str = implode($mids, ','); + + $x = [ 'channel_id' => self::$uid, 'update' => 'unset' ]; + call_hooks('update_unseen',$x); + + if($x['update'] === 'unset' || intval($x['update'])) { + q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND mid in (%s) AND item_unseen = 1", + intval(self::$uid), + $str // this is dbesc() in the above foreach loop + ); + } + + } + + function bs_network($notifications) { + + $result['network']['notifications'] = []; + $result['network']['count'] = 0; + + if(! self::$uid) + return $result; + + if(! (self::$vnotify & VNOTIFY_NETWORK)) + return $result; + + $limit = intval(self::$limit); + $offset = self::$offset; + + $sql_extra = ''; + if(! (self::$vnotify & VNOTIFY_LIKE)) + $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; + + $sql_extra2 = ''; + if(self::$xchans) + $sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") "; + + $item_normal = item_normal(); + + if ($notifications) { + $items = q("SELECT * FROM item + WHERE uid = %d + AND created <= '%s' + AND item_unseen = 1 AND item_wall = 0 AND item_private IN (0, 1) + AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image') + AND author_xchan != '%s' + $item_normal + $sql_extra + $sql_extra2 + ORDER BY created DESC LIMIT $limit OFFSET $offset", + intval(self::$uid), + dbescdate($_SESSION['sse_loadtime']), + dbesc(self::$ob_hash) + ); + + if($items) { + $result['network']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1); + xchan_query($items); + foreach($items as $item) { + $result['network']['notifications'][] = Enotify::format($item); + } + } + else { + $result['network']['offset'] = -1; + } + + } + + $r = q("SELECT count(id) as total FROM item + WHERE uid = %d and item_unseen = 1 AND item_wall = 0 AND item_private IN (0, 1) + AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image') + AND author_xchan != '%s' + $item_normal + $sql_extra", + intval(self::$uid), + dbesc(self::$ob_hash) + ); + + if($r) + $result['network']['count'] = intval($r[0]['total']); + + return $result; + } + + function bs_dm($notifications) { + + $result['dm']['notifications'] = []; + $result['dm']['count'] = 0; + + if(! self::$uid) + return $result; + + if(! (self::$vnotify & VNOTIFY_MAIL)) + return $result; + + $limit = intval(self::$limit); + $offset = self::$offset; + + $sql_extra = ''; + if(! (self::$vnotify & VNOTIFY_LIKE)) + $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; + + $sql_extra2 = ''; + if(self::$xchans) + $sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") "; + + $item_normal = item_normal(); + + if ($notifications) { + $items = q("SELECT * FROM item + WHERE uid = %d + AND created <= '%s' + AND item_unseen = 1 AND item_wall = 0 AND item_private = 2 + AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image') + AND author_xchan != '%s' + $item_normal + $sql_extra + $sql_extra2 + ORDER BY created DESC LIMIT $limit OFFSET $offset", + intval(self::$uid), + dbescdate($_SESSION['sse_loadtime']), + dbesc(self::$ob_hash) + ); + + if($items) { + $result['dm']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1); + xchan_query($items); + foreach($items as $item) { + $result['dm']['notifications'][] = Enotify::format($item); + } + } + else { + $result['dm']['offset'] = -1; + } + + } + + $r = q("SELECT count(id) as total FROM item + WHERE uid = %d and item_unseen = 1 AND item_wall = 0 AND item_private = 2 + $item_normal + $sql_extra + AND author_xchan != '%s'", + intval(self::$uid), + dbesc(self::$ob_hash) + ); + + if($r) + $result['dm']['count'] = intval($r[0]['total']); + + return $result; + } + + function bs_home($notifications) { + + $result['home']['notifications'] = []; + $result['home']['count'] = 0; + + if(! self::$uid) + return $result; + + if(! (self::$vnotify & VNOTIFY_CHANNEL)) + return $result; + + $limit = intval(self::$limit); + $offset = self::$offset; + + $sql_extra = ''; + if(! (self::$vnotify & VNOTIFY_LIKE)) + $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; + + $sql_extra2 = ''; + if(self::$xchans) + $sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") "; + + + $item_normal = item_normal(); + + if ($notifications) { + $items = q("SELECT * FROM item + WHERE uid = %d + AND created <= '%s' + AND item_unseen = 1 AND item_wall = 1 + AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image') + AND author_xchan != '%s' + $item_normal + $sql_extra + $sql_extra2 + ORDER BY created DESC LIMIT $limit OFFSET $offset", + intval(self::$uid), + dbescdate($_SESSION['sse_loadtime']), + dbesc(self::$ob_hash) + ); + + if($items) { + $result['home']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1); + xchan_query($items); + foreach($items as $item) { + $result['home']['notifications'][] = Enotify::format($item); + } + } + else { + $result['home']['offset'] = -1; + } + + } + + $r = q("SELECT count(id) as total FROM item + WHERE uid = %d and item_unseen = 1 AND item_wall = 1 + $item_normal + $sql_extra + AND author_xchan != '%s'", + intval(self::$uid), + dbesc(self::$ob_hash) + ); + + if($r) + $result['home']['count'] = intval($r[0]['total']); + + return $result; + } + + function bs_pubs($notifications) { + + $result['pubs']['notifications'] = []; + $result['pubs']['count'] = 0; + + if(! (self::$vnotify & VNOTIFY_PUBS)) + return $result; + + if((observer_prohibited(true))) { + return $result; + } + + if(! intval(get_config('system','open_pubstream',1))) { + if(! get_observer_hash()) { + return $result; + } + } + + if(! isset($_SESSION['static_loadtime'])) + $_SESSION['static_loadtime'] = datetime_convert(); + + $limit = intval(self::$limit); + $offset = self::$offset; + + $sys = get_sys_channel(); + $sql_extra = ''; + if(! (self::$vnotify & VNOTIFY_LIKE)) + $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; + + $sql_extra2 = ''; + if(self::$xchans) + $sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") "; + + $item_normal = item_normal(); + + if ($notifications) { + $items = q("SELECT * FROM item + WHERE uid = %d + AND created <= '%s' + AND item_unseen = 1 + AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image') + AND author_xchan != '%s' + AND created > '%s' + $item_normal + $sql_extra + $sql_extra2 + ORDER BY created DESC LIMIT $limit OFFSET $offset", + intval($sys['channel_id']), + dbescdate($_SESSION['sse_loadtime']), + dbesc(self::$ob_hash), + dbescdate($_SESSION['static_loadtime']) + ); + + if($items) { + $result['pubs']['offset'] = ((count($items) == $limit) ? intval($offset + $limit) : -1); + xchan_query($items); + foreach($items as $item) { + $result['pubs']['notifications'][] = Enotify::format($item); + } + } + else { + $result['pubs']['offset'] = -1; + } + + + } + + $r = q("SELECT count(id) as total FROM item + WHERE uid = %d AND item_unseen = 1 + AND created > '%s' + $item_normal + $sql_extra + AND author_xchan != '%s'", + intval($sys['channel_id']), + dbescdate($_SESSION['static_loadtime']), + dbesc(self::$ob_hash) + ); + + if($r) + $result['pubs']['count'] = intval($r[0]['total']); + + return $result; + } + + + function bs_notify() { + + $result['notify']['notifications'] = []; + $result['notify']['count'] = 0; + $result['notify']['offset'] = -1; + + if(! self::$uid) + return $result; + + if(! (self::$vnotify & VNOTIFY_SYSTEM)) + return $result; + + $r = q("SELECT * FROM notify WHERE uid = %d AND seen = 0 ORDER BY created DESC", + intval(self::$uid) + ); + + if($r) { + foreach($r as $rr) { + $result['notify']['notifications'][] = Enotify::format_notify($rr); + } + $result['notify']['count'] = count($r); + } + + return $result; + + } + + function bs_intros() { + + $result['intros']['notifications'] = []; + $result['intros']['count'] = 0; + $result['intros']['offset'] = -1; + + if(! self::$uid) + return $result; + + if(! (self::$vnotify & VNOTIFY_INTRO)) + return $result; + + $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(self::$uid) + ); + + if($r) { + foreach($r as $rr) { + $result['intros']['notifications'][] = Enotify::format_intros($rr); + } + $result['intros']['count'] = count($r); + } + + return $result; + + } + + function bs_forums() { + + $result['forums']['notifications'] = []; + $result['forums']['count'] = 0; + $result['forums']['offset'] = -1; + + if(! self::$uid) + return $result; + + if(! (self::$vnotify & VNOTIFY_FORUMS)) + return $result; + + $forums = get_forum_channels(self::$uid); + + if($forums) { + $item_normal = item_normal(); + + $sql_extra = ''; + if(! (self::$vnotify & VNOTIFY_LIKE)) + $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; + + $fcount = count($forums); + $i = 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(self::$uid), + 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 mid from item + where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $sql_extra $item_normal", + intval(self::$uid), + dbesc($forums[$x]['xchan_hash']), + dbesc($forums[$x]['xchan_hash']) + ); + + if($r) { + $mids = flatten_array_recursive($r); + $b64mids = []; + + foreach($mids as $mid) + $b64mids[] = 'b64.' . base64url_encode($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']; + $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'] = count($b64mids); + $forums[$x]['private_forum'] = (($forums[$x]['private_forum']) ? 'lock' : ''); + $forums[$x]['message'] = (($forums[$x]['private_forum']) ? t('Private forum') : t('Public forum')); + $forums[$x]['mids'] = json_encode($b64mids); + + 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']); + + $i = $i + count($mids); + + } + else { + unset($forums[$x]); + } + } + + $result['forums']['count'] = $i; + $result['forums']['notifications'] = array_values($forums); + + } + + return $result; + + } + + function bs_files() { + + $result['files']['notifications'] = []; + $result['files']['count'] = 0; + $result['files']['offset'] = -1; + + if(! self::$uid) + return $result; + + if(! (self::$vnotify & VNOTIFY_FILES)) + return $result; + + $item_normal = item_normal(); + + $r = q("SELECT * FROM item + WHERE verb = '%s' + AND obj_type IN ('Document', 'Video', 'Audio', 'Image') + AND uid = %d + AND author_xchan != '%s' + AND item_unseen = 1 + $item_normal + ORDER BY created DESC", + dbesc(ACTIVITY_POST), + intval(self::$uid), + dbesc(self::$ob_hash) + ); + if($r) { + xchan_query($r); + foreach($r as $rr) { + $result['files']['notifications'][] = Enotify::format($rr); + } + $result['files']['count'] = count($r); + } + + return $result; + + } + + 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'] = []; + $result['all_events']['count'] = 0; + $result['all_events']['offset'] = -1; + + if(! self::$uid) + return $result; + + if(! (self::$vnotify & VNOTIFY_EVENT)) + return $result; + + $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", + intval(self::$uid), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + ' . intval(self::$evdays) . ' days')), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) + ); + + if($r) { + foreach($r as $rr) { + $result['all_events']['notifications'][] = Enotify::format_all_events($rr); + } + $result['all_events']['count'] = count($r); + } + + return $result; + } + + function bs_register() { + + $result['register']['notifications'] = []; + $result['register']['count'] = 0; + $result['register']['offset'] = -1; + + if(! self::$uid && ! is_site_admin()) + return $result; + + if(! (self::$vnotify & VNOTIFY_REGISTER)) + return $result; + + $r = q("SELECT account_email, account_created from account where (account_flags & %d) > 0", + intval(ACCOUNT_PENDING) + ); + if($r) { + foreach($r as $rr) { + $result['register']['notifications'][] = Enotify::format_register($rr); + } + $result['register']['count'] = count($r); + } + + return $result; + + } + +} diff --git a/Zotlabs/Module/Starred.php b/Zotlabs/Module/Starred.php index 8349ae25c..2d7063669 100644 --- a/Zotlabs/Module/Starred.php +++ b/Zotlabs/Module/Starred.php @@ -1,6 +1,7 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; class Starred extends \Zotlabs\Web\Controller { @@ -37,7 +38,7 @@ class Starred extends \Zotlabs\Web\Controller { if($r) { xchan_query($r); $sync_item = fetch_post_tags($r); - build_sync_packet(local_channel(),[ + Libsync::build_sync_packet(local_channel(),[ 'item' => [ encode_item($sync_item[0],true) ] diff --git a/Zotlabs/Module/Tagger.php b/Zotlabs/Module/Tagger.php index e6e80dce3..4fbfb7070 100644 --- a/Zotlabs/Module/Tagger.php +++ b/Zotlabs/Module/Tagger.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + require_once('include/security.php'); require_once('include/bbcode.php'); require_once('include/items.php'); @@ -149,7 +151,7 @@ class Tagger extends \Zotlabs\Web\Controller { $ret = post_activity_item($arr); if($ret['success']) { - build_sync_packet(local_channel(), + Libsync::build_sync_packet(local_channel(), [ 'item' => [ encode_item($ret['activity'],true) ] ] diff --git a/Zotlabs/Module/Thing.php b/Zotlabs/Module/Thing.php index c3d8ff802..b065b0022 100644 --- a/Zotlabs/Module/Thing.php +++ b/Zotlabs/Module/Thing.php @@ -5,6 +5,8 @@ namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + require_once('include/items.php'); require_once('include/security.php'); require_once('include/selectors.php'); @@ -124,7 +126,7 @@ class Thing extends \Zotlabs\Web\Controller { dbesc($term_hash) ); if($r) { - build_sync_packet(0, array('obj' => $r)); + Libsync::build_sync_packet(0, array('obj' => $r)); } return; @@ -180,7 +182,7 @@ class Thing extends \Zotlabs\Web\Controller { dbesc($hash) ); if($r) { - build_sync_packet(0, array('obj' => $r)); + Libsync::build_sync_packet(0, array('obj' => $r)); } if($activity) { @@ -353,7 +355,7 @@ class Thing extends \Zotlabs\Web\Controller { $r[0]['obj_deleted'] = 1; - build_sync_packet(0,array('obj' => $r)); + Libsync::build_sync_packet(0,array('obj' => $r)); return $o; } diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php index 30df0b9e4..a0c293ddf 100644 --- a/Zotlabs/Module/Viewconnections.php +++ b/Zotlabs/Module/Viewconnections.php @@ -74,7 +74,29 @@ class Viewconnections extends \Zotlabs\Web\Controller { if(! intval(get_abconfig(\App::$profile['uid'],$rr['xchan_hash'],'their_perms','post_comments'))) { $oneway = true; } - + + $perminfo=[]; + $perminfo['connpermcount']=0; + $perminfo['connperms']=t('Accepts').': '; + if(intval(get_abconfig(\App::$profile['uid'],$rr['xchan_hash'],'their_perms','post_comments'))) { + $perminfo['connpermcount']++; + $perminfo['connperms'] .= t('Comments'); + } + if(intval(get_abconfig(\App::$profile['uid'],$rr['xchan_hash'],'their_perms','send_stream'))) { + $perminfo['connpermcount']++; + $perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ; + $perminfo['connperms'] .= t('Stream items'); + } + if(intval(get_abconfig(\App::$profile['uid'],$rr['xchan_hash'],'their_perms','post_wall'))) { + $perminfo['connpermcount']++; + $perminfo['connperms'] = ($perminfo['connperms']) ? $perminfo['connperms'] . ', ' : $perminfo['connperms'] ; + $perminfo['connperms'] .= t('Wall posts'); + } + + if ($perminfo['connpermcount'] == 0) { + $perminfo['connperms'] .= t('Nothing'); + } + $url = chanlink_hash($rr['xchan_hash']); if($url) { $contacts[] = array( @@ -88,12 +110,12 @@ class Viewconnections extends \Zotlabs\Web\Controller { 'sparkle' => '', 'itemurl' => $rr['url'], 'network' => '', + 'perminfo' => (($is_owner) ? $perminfo : (($perminfo['connpermcount'] === 0) ? $perminfo : [])), 'oneway' => $oneway ); } } - - + if($_REQUEST['aj']) { if($contacts) { $o = replace_macros(get_markup_template('viewcontactsajax.tpl'),array( diff --git a/Zotlabs/Module/Vote.php b/Zotlabs/Module/Vote.php new file mode 100644 index 000000000..d67a6f176 --- /dev/null +++ b/Zotlabs/Module/Vote.php @@ -0,0 +1,143 @@ +<?php +namespace Zotlabs\Module; + +use App; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\Activity; +use Zotlabs\Daemon\Master; +use Zotlabs\Lib\Libsync; + +class Vote extends Controller { + + function init() { + + $ret = [ 'success' => false, 'message' => EMPTY_STR ]; + + $channel = App::get_channel(); + + if (! $channel) { + $ret['message'] = t('Permission denied.'); + json_return_and_die($ret); + } + + + $fetch = null; + $id = argv(1); + $response = $_REQUEST['answer']; + + if ($id) { + $fetch = q("select * from item where id = %d limit 1", + intval($id) + ); + } + + + if ($fetch && $fetch[0]['obj_type'] === 'Question') { + $obj = json_decode($fetch[0]['obj'],true); + + } + else { + $ret['message'] = t('Poll not found.'); + json_return_and_die($ret); + } + + $valid = false; + + if ($obj['oneOf']) { + foreach($obj['oneOf'] as $selection) { + // logger('selection: ' . $selection); + // logger('response: ' . $response); + if($selection['name'] && $selection['name'] === $response) { + $valid = true; + } + } + } + + $choices = []; + if ($obj['anyOf']) { + foreach ($obj['anyOf'] as $selection) { + $choices[] = $selection['name']; + } + foreach ($response as $res) { + if (! in_array($res,$choices)) { + $valid = false; + break; + } + $valid = true; + } + } + + if (! $valid) { + $ret['message'] = t('Invalid response.'); + json_return_and_die($ret); + } + + if (! is_array($response)) { + $response = [ $response ]; + } + + foreach ($response as $res) { + + $item = []; + + + $item['aid'] = $channel['channel_account_id']; + $item['uid'] = $channel['channel_id']; + $item['item_origin'] = 1; + $item['parent'] = $fetch[0]['id']; + $item['parent_mid'] = $fetch[0]['mid']; + $item['thr_parent'] = $fetch[0]['mid']; + $item['uuid'] = new_uuid(); + $item['mid'] = z_root() . '/item/' . $item['uuid']; + $item['verb'] = 'Create'; + $item['title'] = $res; + $item['author_xchan'] = $channel['channel_hash']; + $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 + + $item['verb'] = ACTIVITY_POST; + $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) + ); + if ($r) { + xchan_query($r); + $sync_item = fetch_post_tags($r); + 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/Wall_attach.php b/Zotlabs/Module/Wall_attach.php index e1088d18f..2c0eeec77 100644 --- a/Zotlabs/Module/Wall_attach.php +++ b/Zotlabs/Module/Wall_attach.php @@ -1,6 +1,8 @@ <?php namespace Zotlabs\Module; +use Zotlabs\Lib\Libsync; + require_once('include/attach.php'); require_once('include/photos.php'); @@ -134,7 +136,7 @@ class Wall_attach extends \Zotlabs\Web\Controller { $sync = attach_export_data($channel,$r['data']['hash']); if($sync) { - build_sync_packet($channel['channel_id'],array('file' => array($sync))); + Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync))); } if($using_api) diff --git a/Zotlabs/Module/Well_known.php b/Zotlabs/Module/Well_known.php index 140ab260d..0d7b222b8 100644 --- a/Zotlabs/Module/Well_known.php +++ b/Zotlabs/Module/Well_known.php @@ -65,11 +65,6 @@ class Well_known extends \Zotlabs\Web\Controller { killme(); case 'caldav': - if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') { - http_status('301', 'moved permanently'); - goaway(z_root() . '/cdav'); - }; - case 'carddav': if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') { http_status('301', 'moved permanently'); diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php index a19bdbedc..d24a31a15 100644 --- a/Zotlabs/Module/Wfinger.php +++ b/Zotlabs/Module/Wfinger.php @@ -3,6 +3,7 @@ namespace Zotlabs\Module; require_once('include/zot.php'); +use Zotlabs\Lib\Libzot; class Wfinger extends \Zotlabs\Web\Controller { @@ -128,7 +129,7 @@ class Wfinger extends \Zotlabs\Web\Controller { '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' => 'zot,zot6' + 'http://purl.org/zot/federation' => 'zot6,zot' ]; foreach($aliases as $alias) @@ -142,7 +143,7 @@ class Wfinger extends \Zotlabs\Web\Controller { [ 'rel' => 'http://webfinger.net/rel/avatar', 'type' => $r[0]['xchan_photo_mimetype'], - 'href' => $r[0]['xchan_photo_l'] + 'href' => $r[0]['xchan_photo_l'] ], [ @@ -162,13 +163,13 @@ class Wfinger extends \Zotlabs\Web\Controller { else { $result['links'] = [ - + [ 'rel' => 'http://webfinger.net/rel/avatar', 'type' => $r[0]['xchan_photo_mimetype'], 'href' => $r[0]['xchan_photo_l'] ], - + [ 'rel' => 'http://microformats.org/profile/hcard', 'type' => 'text/html', @@ -180,12 +181,11 @@ class Wfinger extends \Zotlabs\Web\Controller { 'href' => z_root() ], - [ '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', @@ -196,16 +196,11 @@ class Wfinger extends \Zotlabs\Web\Controller { 'rel' => 'http://webfinger.net/rel/blog', 'href' => z_root() . '/channel/' . $r[0]['channel_address'], ], - + [ 'rel' => 'http://ostatus.org/schema/1.0/subscribe', 'template' => z_root() . '/follow?f=&url={uri}', ], - - [ - 'rel' => 'http://purl.org/zot/protocol', - 'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'], - ], [ 'rel' => 'http://purl.org/zot/protocol/6.0', @@ -214,12 +209,16 @@ class Wfinger extends \Zotlabs\Web\Controller { ], [ + 'rel' => 'http://purl.org/zot/protocol', + 'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'], + ], + + [ 'rel' => 'http://purl.org/openwebauth/v1', 'type' => 'application/x-zot+json', 'href' => z_root() . '/owa', ], - [ 'rel' => 'magic-public-key', 'href' => 'data:application/magic-public-key,' . salmon_key($r[0]['channel_pubkey']), @@ -229,7 +228,7 @@ class Wfinger extends \Zotlabs\Web\Controller { if($zot) { // get a zotinfo packet and return it with webfinger - $result['zot'] = zotinfo( [ 'address' => $r[0]['xchan_addr'] ]); + $result['zot'] = Libzot::zotinfo( [ 'address' => $r[0]['xchan_addr'] ]); } } @@ -241,7 +240,6 @@ class Wfinger extends \Zotlabs\Web\Controller { $arr = [ 'channel' => $r[0], 'pchan' => $pchan, 'request' => $_REQUEST, 'result' => $result ]; call_hooks('webfinger',$arr); - json_return_and_die($arr['result'],'application/jrd+json'); } diff --git a/Zotlabs/Module/Z6trans.php b/Zotlabs/Module/Z6trans.php new file mode 100644 index 000000000..72667316f --- /dev/null +++ b/Zotlabs/Module/Z6trans.php @@ -0,0 +1,161 @@ +<?php +/** + * @file Zotlabs/Module/Z6trans.php + * + * @brief replace all occurances of an zot xchan with the zot6 xchan in DB. + * + */ + +namespace Zotlabs\Module; + +use Zotlabs\Web\Controller; + +class Z6trans extends Controller { + + function get() { + if(!is_site_admin()) + return '<h1>Not Allowed</h1>'; + + $o = '<h2>' . t('Update to Hubzilla 5.0 step 2') . '</h2><br>'; + + $o .= '<h3>' . t('To complete the update please run') . '</h3>'; + + $o .= '<code>' . t('php util/z6convert.php') . '</code>'; + + $o .= '<h3>' . t('from the terminal.') . '</h3>'; + + return $o; + +/* this code is outdated use util/z6convert.php instead + + $path = 'store/z6trans.sql'; + + $r = q("SELECT channel.channel_name, channel.channel_portable_id, xchan.xchan_network FROM channel + LEFT JOIN xchan ON channel_portable_id = xchan_hash + WHERE xchan.xchan_network = 'zot' + AND channel.channel_removed = 0" + ); + + $q = ''; + + foreach($r as $rr) { + + $zot_xchan = $rr['channel_portable_id']; + + $r = q("SELECT xchan_guid FROM xchan WHERE xchan_hash = '%s' AND xchan_network = 'zot'", + dbesc($zot_xchan) + ); + + if(!$r) { + $q .= '-- ' . $zot_xchan . 'failed: zot xchan not found' . "\r\n"; + continue; + } + + $guid = $r[0]['xchan_guid']; + + $r = q("SELECT xchan_hash, xchan_guid_sig FROM xchan WHERE xchan_guid = '%s' AND xchan_network = 'zot6'", + dbesc($guid) + ); + + if(!$r) { + $q .= '-- ' . $zot_xchan . 'failed: zot6 xchan not found' . "\r\n"; + continue; + } + + $zot6_xchan = $r[0]['xchan_hash']; + + $core = self::get_core_cols(); + + $q .= '-- Transforming ' . $rr['channel_name'] . "\r\n"; + + foreach($core as $table => $cols) { + + foreach($cols as $col) { + + $q .= sprintf("UPDATE %s SET %s = replace(%s, '%s', '%s');\r\n", + dbesc($table), + dbesc($col), + dbesc($col), + dbesc($zot_xchan), + dbesc($zot6_xchan) + ); + + } + + } + + $zot = dbesc($zot_xchan); + $zot6 = dbesc($zot6_xchan); + + // Item table + foreach(['owner_xchan', 'author_xchan'] as $x) { + $q .= sprintf("UPDATE item SET $x = '%s' WHERE $x = '%s';\r\n", + $zot6, + $zot + ); + } + $q .= "UPDATE item SET source_xchan = replace(source_xchan, '$zot', '$zot6'), route = replace(route, '$zot', '$zot6'), allow_cid = replace(allow_cid, '$zot', '$zot6'), deny_cid = replace(deny_cid, '$zot', '$zot6');\r\n"; + + // photo table + $q .= "UPDATE photo SET xchan = replace(xchan, '$zot', '$zot6'), allow_cid = replace(allow_cid, '$zot', '$zot6'), deny_cid = replace(deny_cid, '$zot', '$zot6');\r\n"; + + // dreport table + $q .= "UPDATE dreport SET dreport_recip = '$zot6' WHERE dreport_recip = '$zot';\r\n"; + $q .= "UPDATE dreport SET dreport_xchan = '$zot6' WHERE dreport_xchan = '$zot';\r\n"; + } + + if($q) + file_put_contents($path, $q); + + $o = '<h2>' . t('Update to Hubzilla 5.0 step 2') . '</h2><br>'; + + $o .= '<h3>' . t('To complete the update please run') . '</h3>'; + if(ACTIVE_DBTYPE == DBTYPE_MYSQL) + $o .= '<code>source ' . $_SERVER["DOCUMENT_ROOT"] . '/' . $path . '</code><h3>from the mysql console.</h3>'; + else + $o .= '<code>\i ' . $_SERVER["DOCUMENT_ROOT"] . '/' . $path . '</code><h3>from the postgresql console.</h3>'; + + $o .= '<br><h3>' . t('INFO: this command can take a very long time depending on your DB size.') . '</h3>'; + + return $o; +*/ + + } + + function get_core_cols() { + + $core = [ + 'abconfig' => ['xchan'], + 'abook' => ['abook_xchan'], + 'app' => ['app_author'], + 'attach' => ['creator', 'allow_cid', 'deny_cid'], + 'channel' => ['channel_allow_cid', 'channel_deny_cid'], + 'chat' => ['chat_xchan'], + 'chatpresence' => ['cp_xchan'], + 'chatroom' => ['allow_cid', 'deny_cid'], + 'config' => ['v'], +// 'dreport' => ['dreport_recip', 'dreport_xchan'], + 'event' => ['event_xchan', 'allow_cid', 'deny_cid'], + 'iconfig' => ['v'], +// 'item' => ['owner_xchan', 'author_xchan', 'source_xchan', 'route', 'allow_cid', 'deny_cid'], + 'mail' => ['from_xchan', 'to_xchan'], + 'menu_item' => ['allow_cid', 'deny_cid'], + 'obj' => ['allow_cid', 'deny_cid'], + 'pconfig' => ['v'], + 'pgrp_member' => ['xchan'], +// 'photo' => ['xchan', 'allow_cid', 'deny_cid'], + 'source' => ['src_channel_xchan', 'src_xchan'], + 'updates' => ['ud_hash'], + 'xchat' => ['xchat_xchan'], + 'xconfig' => ['xchan', 'v'], + 'xign' => ['xchan'], + 'xlink' => ['xlink_xchan', 'xlink_link'], +// 'xprof' => ['xprof_hash'], + 'xtag' => ['xtag_hash'], + ]; + + return $core; + + } + +} diff --git a/Zotlabs/Module/Zfinger.php b/Zotlabs/Module/Zfinger.php index 3a20144a5..533f0a5db 100644 --- a/Zotlabs/Module/Zfinger.php +++ b/Zotlabs/Module/Zfinger.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module; use Zotlabs\Web\HTTPSig; +use Zotlabs\Lib\Libzot; class Zfinger extends \Zotlabs\Web\Controller { @@ -9,7 +10,7 @@ class Zfinger extends \Zotlabs\Web\Controller { require_once('include/zot.php'); require_once('include/crypto.php'); - + $x = zotinfo($_REQUEST); if($x && $x['guid'] && $x['guid_sig']) { |