aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2019-02-20 08:52:13 +0100
committerMario <mario@mariovavti.com>2019-02-20 08:52:13 +0100
commit65e8ed6871ba40b1582853cf3e20822232226b24 (patch)
treeeaf2eff7a7d5a9902f93554bfd29e2e1dbbfac37
parentcead10b9af6ff9d8b1bc702ca21d27af7c2112f0 (diff)
parenta77d7b844240030a764455b78b1b13fc886322f5 (diff)
downloadvolse-hubzilla-65e8ed6871ba40b1582853cf3e20822232226b24.tar.gz
volse-hubzilla-65e8ed6871ba40b1582853cf3e20822232226b24.tar.bz2
volse-hubzilla-65e8ed6871ba40b1582853cf3e20822232226b24.zip
Merge branch 'dev' into 'dev'
basic support for nomadic content, fix for permitted guests deleting their own files in cloud space of other channel,urlencode category widget links See merge request hubzilla/core!1523
-rw-r--r--Zotlabs/Lib/Activity.php45
-rw-r--r--Zotlabs/Lib/ActivityStreams.php20
-rw-r--r--Zotlabs/Lib/ZotURL.php91
-rw-r--r--Zotlabs/Module/Filestorage.php40
-rw-r--r--Zotlabs/Module/Id.php119
-rw-r--r--Zotlabs/Storage/Browser.php14
-rwxr-xr-xview/tpl/categories_widget.tpl2
-rw-r--r--view/tpl/cloud_directory.tpl2
8 files changed, 295 insertions, 38 deletions
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index bcbe53df7..9aaf6d866 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -2,10 +2,7 @@
namespace Zotlabs\Lib;
-use Zotlabs\Lib\Libzot;
-use Zotlabs\Lib\Libsync;
-use Zotlabs\Lib\ActivityStreams;
-use Zotlabs\Lib\Group;
+use Zotlabs\Zot6\HTTPSig;
class Activity {
@@ -43,6 +40,46 @@ class Activity {
}
+ static function fetch($url,$channel = null) {
+ $redirects = 0;
+ if(! check_siteallowed($url)) {
+ logger('blacklisted: ' . $url);
+ return null;
+ }
+ if(! $channel) {
+ $channel = get_sys_channel();
+ }
+
+ logger('fetch: ' . $url, LOGGER_DEBUG);
+
+ if(strpos($url,'x-zot:') === 0) {
+ $x = ZotURL::fetch($url,$channel);
+ }
+ else {
+ $m = parse_url($url);
+ $headers = [
+ 'Accept' => 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
+ 'Host' => $m['host'],
+ '(request-target)' => 'get ' . get_request_string($url),
+ 'Date' => datetime_convert('UTC','UTC','now','D, d M Y H:i:s') . ' UTC'
+ ];
+ $h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
+ $x = z_fetch_url($url, true, $redirects, [ 'headers' => $h ] );
+ }
+
+ if($x['success']) {
+ $y = json_decode($x['body'],true);
+ logger('returned: ' . json_encode($y,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));
+ return json_decode($x['body'], true);
+ }
+ else {
+ logger('fetch failed: ' . $url);
+ }
+ return null;
+ }
+
+
+
static function fetch_person($x) {
return self::fetch_profile($x);
diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php
index 49978031e..a357b6d69 100644
--- a/Zotlabs/Lib/ActivityStreams.php
+++ b/Zotlabs/Lib/ActivityStreams.php
@@ -263,24 +263,8 @@ class ActivityStreams {
return self::fetch($url);
}
- static function fetch($url) {
- $redirects = 0;
- if(! check_siteallowed($url)) {
- logger('blacklisted: ' . $url);
- return null;
- }
- logger('fetch: ' . $url, LOGGER_DEBUG);
- $x = z_fetch_url($url, true, $redirects,
- [ 'headers' => [ 'Accept: application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ]]);
- if($x['success']) {
- $y = json_decode($x['body'],true);
- logger('returned: ' . json_encode($y,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));
- return json_decode($x['body'], true);
- }
- else {
- logger('fetch failed: ' . $url);
- }
- return null;
+ static function fetch($url,$channel = null) {
+ return Activity::fetch($url,$channel);
}
static function is_an_actor($s) {
diff --git a/Zotlabs/Lib/ZotURL.php b/Zotlabs/Lib/ZotURL.php
new file mode 100644
index 000000000..d1c705fcb
--- /dev/null
+++ b/Zotlabs/Lib/ZotURL.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Zotlabs\Lib;
+
+use Zotlabs\Zot6\HTTPSig;
+
+
+class ZotURL {
+
+ static public function fetch($url,$channel) {
+
+ $ret = [ 'success' => false ];
+
+ if(strpos($url,'x-zot:') !== 0) {
+ return $ret;
+ }
+
+
+ if(! $url) {
+ return $ret;
+ }
+
+ $portable_url = substr($url,6);
+ $u = explode('/',$portable_url);
+ $portable_id = $u[0];
+
+ $hosts = self::lookup($portable_id);
+
+ if(! $hosts) {
+ return $ret;
+ }
+
+ foreach($hosts as $h) {
+ $newurl = $h . '/id/' . $portable_url;
+
+ $m = parse_url($newurl);
+
+ $data = json_encode([ 'zot_token' => random_string() ]);
+
+ if($channel && $m) {
+
+ $headers = [
+ 'Accept' => 'application/x-zot+json',
+ 'Content-Type' => 'application/x-zot+json',
+ 'X-Zot-Token' => random_string(),
+ 'Digest' => HTTPSig::generate_digest_header($data),
+ 'Host' => $m['host'],
+ '(request-target)' => 'post ' . get_request_string($newurl)
+ ];
+ $h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
+ }
+ else {
+ $h = [ 'Accept: application/x-zot+json' ];
+ }
+
+ $result = [];
+
+ $redirects = 0;
+ $x = z_post_url($newurl,$data,$redirects, [ 'headers' => $h ] );
+ if($x['success']) {
+ return $x;
+ }
+ }
+
+ return $ret;
+
+ }
+
+ static public function is_zoturl($s) {
+
+ if(strpos($url,'x-zot:') === 0) {
+ return true;
+ }
+ return false;
+ }
+
+
+ static public function lookup($portable_id) {
+
+ $r = q("select * from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and site_dead = 0 order by hubloc_primary desc",
+ dbesc($portable_id)
+ );
+
+ if(! $r) {
+ // extend to network lookup
+ return false;
+ }
+ return ids_to_array($r,'hubloc_url');
+ }
+
+} \ No newline at end of file
diff --git a/Zotlabs/Module/Filestorage.php b/Zotlabs/Module/Filestorage.php
index 23bd63f95..2c247cd65 100644
--- a/Zotlabs/Module/Filestorage.php
+++ b/Zotlabs/Module/Filestorage.php
@@ -5,6 +5,8 @@ namespace Zotlabs\Module;
*
*/
+
+
class Filestorage extends \Zotlabs\Web\Controller {
function post() {
@@ -71,14 +73,6 @@ class Filestorage extends \Zotlabs\Web\Controller {
return;
}
- // Since we have ACL'd files in the wild, but don't have ACL here yet, we
- // need to return for anyone other than the owner, despite the perms check for now.
-
- $is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false);
- if(! ($is_owner || is_site_admin())){
- info( t('Permission Denied.') . EOL );
- return;
- }
if(argc() > 3 && argv(3) === 'delete') {
@@ -101,18 +95,31 @@ class Filestorage extends \Zotlabs\Web\Controller {
}
$file = intval(argv(2));
- $r = q("SELECT hash FROM attach WHERE id = %d AND uid = %d LIMIT 1",
+ $r = q("SELECT hash, creator FROM attach WHERE id = %d AND uid = %d LIMIT 1",
dbesc($file),
intval($owner)
);
if(! $r) {
+ notice( t('File not found.') . EOL);
+
if($json_return)
json_return_and_die([ 'success' => false ]);
- notice( t('File not found.') . EOL);
goaway(z_root() . '/cloud/' . $which);
}
+ if(local_channel() !== $owner) {
+ if($r[0]['creator'] && $r[0]['creator'] !== $ob_hash) {
+ notice( t('Permission denied.') . EOL);
+
+ if($json_return)
+ json_return_and_die([ 'success' => false ]);
+
+ goaway(z_root() . '/cloud/' . $which);
+ }
+ }
+
+
$f = $r[0];
$channel = channelx_by_n($owner);
@@ -134,6 +141,19 @@ class Filestorage extends \Zotlabs\Web\Controller {
goaway(dirname($url));
}
+
+
+
+ // Since we have ACL'd files in the wild, but don't have ACL here yet, we
+ // need to return for anyone other than the owner, despite the perms check for now.
+
+ $is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false);
+ if(! ($is_owner || is_site_admin())){
+ info( t('Permission Denied.') . EOL );
+ return;
+ }
+
+
if(argc() > 3 && argv(3) === 'edit') {
require_once('include/acl_selectors.php');
if(! $perms['write_storage']) {
diff --git a/Zotlabs/Module/Id.php b/Zotlabs/Module/Id.php
new file mode 100644
index 000000000..15abfa2a3
--- /dev/null
+++ b/Zotlabs/Module/Id.php
@@ -0,0 +1,119 @@
+<?php
+
+namespace Zotlabs\Module;
+
+/**
+ *
+ * Controller for responding to x-zot: protocol requests
+ * x-zot:_jkfRG85nJ-714zn-LW_VbTFW8jSjGAhAydOcJzHxqHkvEHWG2E0RbA_pbch-h4R63RG1YJZifaNzgccoLa3MQ/453c1678-1a79-4af7-ab65-6b012f6cab77
+ *
+ */
+
+use Zotlabs\Lib\Activity;
+use Zotlabs\Lib\ActivityStreams;
+use Zotlabs\Lib\LDSignatures;
+use Zotlabs\Zot6\HTTPSig;
+use Zotlabs\Web\Controller;
+use Zotlabs\Lib\Libzot;
+use Zotlabs\Lib\ThreadListener;
+use Zotlabs\Lib\IConfig;
+use Zotlabs\Lib\Enotify;
+use App;
+
+require_once('include/attach.php');
+require_once('include/bbcode.php');
+require_once('include/security.php');
+
+
+class Id extends Controller {
+
+ function init() {
+
+ if(Libzot::is_zot_request()) {
+
+ $conversation = false;
+
+ $request_portable_id = argv(1);
+ if(argc() > 2) {
+ $item_id = argv(2);
+ }
+
+ $portable_id = EMPTY_STR;
+
+ $sigdata = HTTPSig::verify(EMPTY_STR);
+ if($sigdata['portable_id'] && $sigdata['header_valid']) {
+ $portable_id = $sigdata['portable_id'];
+ }
+
+
+ $chan = channelx_by_hash($request_portable_id);
+
+ if($chan) {
+ $channel_id = $chan['channel_id'];
+ if(! $item_id) {
+ $handler = new Channel();
+ App::$argc = 2;
+ App::$argv[0] = 'channel';
+ App::$argv[1] = $chan['channel_address'];
+ $handler->init();
+ }
+ }
+ else {
+ http_status_exit(404, 'Not found');
+ }
+
+
+ $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 uuid = '%s' $item_normal $sql_extra and uid = %d limit 1",
+ dbesc($item_id),
+ intval($channel_id)
+ );
+ if(! $r) {
+
+ $r = q("select * from item where uuid = '%s' $item_normal and uid = %d limit 1",
+ dbesc($item_id),
+ intval($channel_id)
+ );
+ if($r) {
+ http_status_exit(403, 'Forbidden');
+ }
+ http_status_exit(404, 'Not found');
+ }
+
+ if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
+ http_status_exit(403, 'Forbidden');
+
+ xchan_query($r,true);
+ $items = fetch_post_tags($r,true);
+
+ $i = Activity::encode_item($items[0]);
+
+ 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' ;
+ $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();
+
+ }
+
+ }
+
+}
+
+
diff --git a/Zotlabs/Storage/Browser.php b/Zotlabs/Storage/Browser.php
index c2d70b854..fde66efcd 100644
--- a/Zotlabs/Storage/Browser.php
+++ b/Zotlabs/Storage/Browser.php
@@ -205,17 +205,21 @@ class Browser extends DAV\Browser\Plugin {
// upload access. system.thumbnail_security should be set to 1 if you want to include these
// types
+ $is_creator = false;
$photo_icon = '';
$preview_style = intval(get_config('system','thumbnail_security',0));
- $r = q("select content from attach where hash = '%s' and uid = %d limit 1",
+ $r = q("select content, creator from attach where hash = '%s' and uid = %d limit 1",
dbesc($attachHash),
intval($owner)
);
- if($r && file_exists(dbunescbin($r[0]['content']) . '.thumb')) {
- $photo_icon = 'data:image/jpeg;base64,' . base64_encode(file_get_contents(dbunescbin($r[0]['content']) . '.thumb'));
-// logger('found thumb: ' . $photo_icon);
+ if($r) {
+ $is_creator = (($r[0]['creator'] === get_observer_hash()) ? true : false);
+ if(file_exists(dbunescbin($r[0]['content']) . '.thumb')) {
+ $photo_icon = 'data:image/jpeg;base64,' . base64_encode(file_get_contents(dbunescbin($r[0]['content']) . '.thumb'));
+// logger('found thumb: ' . $photo_icon);
+ }
}
if(strpos($type,'image/') === 0 && $attachHash) {
@@ -247,6 +251,7 @@ class Browser extends DAV\Browser\Plugin {
$ft['attachIcon'] = (($size) ? $attachIcon : '');
// @todo Should this be an item value, not a global one?
$ft['is_owner'] = $is_owner;
+ $ft['is_creator'] = $is_creator;
$ft['fullPath'] = $fullPath;
$ft['displayName'] = $displayName;
$ft['type'] = $type;
@@ -256,6 +261,7 @@ class Browser extends DAV\Browser\Plugin {
$ft['iconFromType'] = getIconFromType($type);
$f[] = $ft;
+
}
diff --git a/view/tpl/categories_widget.tpl b/view/tpl/categories_widget.tpl
index 72478aa3d..1341c652c 100755
--- a/view/tpl/categories_widget.tpl
+++ b/view/tpl/categories_widget.tpl
@@ -5,7 +5,7 @@
<ul class="nav nav-pills flex-column">
<li class="nav-item"><a href="{{$base}}" class="nav-link{{if $sel_all}} active{{/if}}">{{$all}}</a></li>
{{foreach $terms as $term}}
- <li class="nav-item"><a href="{{$base}}?f=&cat={{$term.name}}" class="nav-link{{if $term.selected}} active{{/if}}">{{$term.name}}</a></li>
+ <li class="nav-item"><a href="{{$base}}?f=&cat={{$term.name|urlencode}}" class="nav-link{{if $term.selected}} active{{/if}}">{{$term.name}}</a></li>
{{/foreach}}
</ul>
diff --git a/view/tpl/cloud_directory.tpl b/view/tpl/cloud_directory.tpl
index 51178a9ba..90347d274 100644
--- a/view/tpl/cloud_directory.tpl
+++ b/view/tpl/cloud_directory.tpl
@@ -68,7 +68,7 @@
<td class="cloud-index-tool"><a href="#" title="{{$delete}}" onclick="dropItem('{{$item.fileStorageUrl}}/{{$item.attachId}}/delete/json', '#cloud-index-{{$item.attachId}},#cloud-tools-{{$item.attachId}}'); return false;"><i class="fa fa-trash-o drop-icons"></i></a></td>
{{else}}
- <td></td><td></td><td></td>{{if $is_admin}}<td class="cloud-index-tool"><a href="#" title="{{$admin_delete}}" onclick="dropItem('{{$item.fileStorageUrl}}/{{$item.attachId}}/delete/json', '#cloud-index-{{$item.attachId}},#cloud-tools-{{$item.attachId}}'); return false;"><i class="fa fa-trash-o drop-icons"></i></a>{{else}}<td>{{/if}}</td>
+ <td></td><td></td><td></td>{{if $is_admin || $item.is_creator}}<td class="cloud-index-tool"><a href="#" title="{{if $is_admin}}{{$admin_delete}}{{else}}{{$delete}}{{/if}}" onclick="dropItem('{{$item.fileStorageUrl}}/{{$item.attachId}}/delete/json', '#cloud-index-{{$item.attachId}},#cloud-tools-{{$item.attachId}}'); return false;"><i class="fa fa-trash-o drop-icons"></i></a>{{else}}<td>{{/if}}</td>
{{/if}}
<td>{{*{{$item.type}}*}}</td>
<td class="d-none d-md-table-cell">{{$item.sizeFormatted}}</td>