Commit 2f1958d1 authored by Mario's avatar Mario
Browse files

files_ng: initial commit

parent 3f40d6f7
Pipeline #367091 passed with stage
in 5 minutes and 24 seconds
......@@ -8,7 +8,11 @@ namespace Zotlabs\Module;
*/
use Sabre\DAV as SDAV;
use \Zotlabs\Storage;
use \Zotlabs\Web\Controller;
use \Zotlabs\Storage\BasicAuth;
use \Zotlabs\Storage\Directory;
use \Zotlabs\Storage\Browser;
// composer autoloader for SabreDAV
require_once('vendor/autoload.php');
......@@ -20,7 +24,7 @@ require_once('include/attach.php');
* @brief Cloud Module.
*
*/
class Cloud extends \Zotlabs\Web\Controller {
class Cloud extends Controller {
/**
* @brief Fires up the SabreDAV server.
......@@ -42,7 +46,7 @@ class Cloud extends \Zotlabs\Web\Controller {
$auth = new \Zotlabs\Storage\BasicAuth();
$auth = new BasicAuth();
$ob_hash = get_observer_hash();
......@@ -72,7 +76,7 @@ class Cloud extends \Zotlabs\Web\Controller {
if($x !== \App::$query_string)
goaway(z_root() . '/' . $x);
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
$rootDirectory = new Directory('/', $auth);
// A SabreDAV server-object
$server = new SDAV\Server($rootDirectory);
......@@ -85,7 +89,7 @@ class Cloud extends \Zotlabs\Web\Controller {
$is_readable = false;
// provide a directory view for the cloud in Hubzilla
$browser = new \Zotlabs\Storage\Browser($auth);
$browser = new Browser($auth);
$auth->setBrowserPlugin($browser);
$server->addPlugin($browser);
......
......@@ -138,7 +138,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
if($json_return)
json_return_and_die([ 'success' => true ]);
goaway(dirname($url));
//goaway(dirname($url));
}
......
......@@ -108,13 +108,18 @@ class Browser extends DAV\Browser\Plugin {
$parentpath['path'] = $fullPath;
}
$folder_list = attach_folder_select_list($this->auth->owner_id);
$f = array();
foreach ($files as $file) {
$ft = array();
$type = null;
// This is the current directory, we can skip it
if (rtrim($file['href'], '/') == $path) continue;
if (rtrim($file['href'], '/') == $path)
continue;
list(, $name) = \Sabre\Uri\split($file['href']);
......@@ -166,7 +171,7 @@ class Browser extends DAV\Browser\Plugin {
$size = isset($file[200]['{DAV:}getcontentlength']) ? (int)$file[200]['{DAV:}getcontentlength'] : '';
$lastmodified = ((isset($file[200]['{DAV:}getlastmodified'])) ? $file[200]['{DAV:}getlastmodified']->getTime()->format('Y-m-d H:i:s') : '');
$fullPath = \Sabre\HTTP\encodePath('/' . trim($this->server->getBaseUri() . ($path ? $path . '/' : '') . $name, '/'));
$relPath = \Sabre\HTTP\encodePath('/' . trim($this->server->getBaseUri() . ($path ? $path . '/' : '') . $name, '/'));
$displayName = isset($file[200]['{DAV:}displayname']) ? $file[200]['{DAV:}displayname'] : $name;
......@@ -180,7 +185,7 @@ class Browser extends DAV\Browser\Plugin {
$node = $this->server->tree->getNodeForPath(($path ? $path . '/' : '') . $name);
foreach (array_reverse($this->iconMap) as $class=>$iconName) {
if ($node instanceof $class) {
$icon = '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl($iconName . $this->iconExtension) . '" alt="" width="24"></a>';
$icon = '<a href="' . $relPath . '"><img src="' . $this->getAssetUrl($iconName . $this->iconExtension) . '" alt="" width="24"></a>';
break;
}
}
......@@ -188,7 +193,7 @@ class Browser extends DAV\Browser\Plugin {
$parentHash = '';
$owner = $this->auth->owner_id;
$splitPath = explode('/', $fullPath);
$splitPath = explode('/', $relPath);
if (count($splitPath) > 3) {
for ($i = 3; $i < count($splitPath); $i++) {
$attachName = urldecode($splitPath[$i]);
......@@ -209,7 +214,7 @@ class Browser extends DAV\Browser\Plugin {
$photo_icon = '';
$preview_style = intval(get_config('system','thumbnail_security',0));
$r = q("select content, creator from attach where hash = '%s' and uid = %d limit 1",
$r = q("select * from attach where hash = '%s' and uid = %d limit 1",
dbesc($attachHash),
intval($owner)
);
......@@ -223,16 +228,16 @@ class Browser extends DAV\Browser\Plugin {
}
if(strpos($type,'image/') === 0 && $attachHash) {
$r = q("select resource_id, imgscale from photo where resource_id = '%s' and imgscale in ( %d, %d ) order by imgscale asc limit 1",
$p = q("select resource_id, imgscale from photo where resource_id = '%s' and imgscale in ( %d, %d ) order by imgscale asc limit 1",
dbesc($attachHash),
intval(PHOTO_RES_320),
intval(PHOTO_RES_PROFILE_80)
);
if($r) {
$photo_icon = 'photo/' . $r[0]['resource_id'] . '-' . $r[0]['imgscale'];
if($p) {
$photo_icon = 'photo/' . $p[0]['resource_id'] . '-' . $p[0]['imgscale'];
}
if($type === 'image/svg+xml' && $preview_style > 0) {
$photo_icon = $fullPath;
$photo_icon = $relPath;
}
}
......@@ -242,24 +247,38 @@ class Browser extends DAV\Browser\Plugin {
$attachIcon = ""; // "<a href=\"attach/".$attachHash."\" title=\"".$displayName."\"><i class=\"fa fa-arrow-circle-o-down\"></i></a>";
$lockstate = (($r[0]['allow_cid'] || $r[0]['allow_gid'] || $r[0]['deny_cid'] || $r[0]['deny_gid']) ? 'lock' : 'unlock');
// put the array for this file together
$ft['attachId'] = $this->findAttachIdByHash($attachHash);
$ft['fileStorageUrl'] = substr($fullPath, 0, strpos($fullPath, "cloud/")) . "filestorage/" . $this->auth->owner_nick;
$ft['fileStorageUrl'] = substr($relPath, 0, strpos($relPath, "cloud/")) . "filestorage/" . $this->auth->owner_nick;
$ft['icon'] = $icon;
$ft['photo_icon'] = $photo_icon;
$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['relPath'] = $relPath;
$ft['fullPath'] = z_root() . $relPath;
$ft['displayName'] = $displayName;
$ft['type'] = $type;
$ft['size'] = $size;
$ft['collection'] = (($type === 'Collection') ? true : false);
$ft['sizeFormatted'] = userReadableSize($size);
$ft['lastmodified'] = (($lastmodified) ? datetime_convert('UTC', date_default_timezone_get(), $lastmodified) : '');
$ft['iconFromType'] = getIconFromType($type);
$ft['allow_cid'] = acl2json($r[0]['allow_cid']);
$ft['allow_gid'] = acl2json($r[0]['allow_gid']);
$ft['deny_cid'] = acl2json($r[0]['deny_cid']);
$ft['deny_gid'] = acl2json($r[0]['deny_gid']);
$ft['lockstate'] = $lockstate;
$ft['resource'] = $r[0]['hash'];
$ft['folder'] = $r[0]['folder'];
$ft['revision'] = $r[0]['revision'];
$ft['newfilename'] = ['newfilename', t('Change filename to'), $displayName];
$ft['newfolder'] = ['newfolder', t('Move to directory'), $r[0]['folder'], '', $folder_list];
$f[] = $ft;
}
......@@ -273,7 +292,8 @@ class Browser extends DAV\Browser\Plugin {
$deftiles = (($is_owner) ? 0 : 1);
$tiles = ((array_key_exists('cloud_tiles',$_SESSION)) ? intval($_SESSION['cloud_tiles']) : $deftiles);
$_SESSION['cloud_tiles'] = $tiles;
$html .= replace_macros(get_markup_template('cloud.tpl'), array(
'$header' => t('Files') . ": " . $this->escapeHTML($path) . "/",
'$total' => t('Total'),
......@@ -295,10 +315,16 @@ class Browser extends DAV\Browser\Plugin {
'$parent' => t('parent'),
'$edit' => t('Edit'),
'$delete' => t('Delete'),
'$nick' => $this->auth->getCurrentUser()
));
'$nick' => $this->auth->getCurrentUser(),
'$recurse' => array('recurse', t('Change permission fo all files and sub folders'), 0, '', array(t('No'), t('Yes'))),
'$notify' => array('notify_edit', t('Show in your contacts shared folder'), 0, '', array(t('No'), t('Yes'))),
'$cpdesc' => t('Copy/paste this code to attach file to a post'),
'$cpldesc' => t('Copy/paste this URL to link file from a web page'),
));
$a = false;
nav_set_selected('Files');
......
......@@ -732,24 +732,33 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
* @return array Directory[]
*/
function ChannelList(&$auth) {
$ret = [];
$sql_extra = '';
$restricted = false;
if (intval(get_config('system','cloud_disable_siteroot'))) {
return $ret;
if (! local_channel())
return $ret;
$restricted = true;
$sql_extra = sprintf(" and channel_id = %d ", intval(local_channel()));
}
$r = q("SELECT channel_id, channel_address, profile.publish FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0",
$r = q("SELECT channel_id, channel_address, profile.publish FROM channel join profile on profile.uid = channel.channel_id WHERE profile.is_default = 1 and channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0 $sql_extra",
intval(PAGE_HIDDEN)
);
if ($r) {
foreach ($r as $rr) {
if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage') && $rr['publish']) {
$publish = (($restricted) ? 1 : $rr['publish']);
if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage') && $publish) {
logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA);
$ret[] = new Directory($rr['channel_address'], $auth);
}
}
}
return $ret;
}
......
......@@ -2509,7 +2509,7 @@ function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpat
* @param string $new_folder_hash
* @return void|boolean
*/
function attach_move($channel_id, $resource_id, $new_folder_hash) {
function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '') {
$c = channelx_by_n($channel_id);
if(! ($c && $resource_id))
......@@ -2529,7 +2529,6 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
$oldstorepath = dbunescbin($r[0]['content']);
// find the resource we are moving to
if($new_folder_hash) {
......@@ -2540,6 +2539,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
if(! $n)
return false;
$newdirname = $n[0]['filename'];
$newalbumname = $n[0]['display_path'];
$newstorepath = dbunescbin($n[0]['content']) . '/' . $resource_id;
}
......@@ -2547,6 +2547,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
// root directory
$newdirname = EMPTY_STR;
$newalbumname = EMPTY_STR;
$newstorepath = 'store/' . $c['channel_address'] . '/' . $resource_id;
}
......@@ -2555,7 +2556,8 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
// duplicate detection. If 'overwrite' is specified, return false because we can't yet do that.
$filename = $r[0]['filename'];
$oldfilename = $r[0]['filename'];
$filename = (($newname) ? basename($newname) : $oldfilename);
// don't do duplicate check unless our parent folder has changed.
......
#files-mkdir-tools,
#files-upload-tools,
.cloud-tools,
.link-code,
[id^="perms-panel-"] {
display: none;
}
......@@ -8,6 +10,10 @@
padding: 3px 10px 0px 10px !important;
}
[id^="attach-edit-panel-"] {
padding: 3px 10px 0px 10px !important;
}
#attach-code,
#link-code {
display: none;
......@@ -17,6 +23,10 @@
width: 100%;
}
#cloud-index td a {
display: block;
}
#cloud-index td:nth-child(1){
padding: 7px 3px 7px 10px;
}
......
......@@ -1253,24 +1253,25 @@ function dopin(id) {
}
function dropItem(url, object) {
var confirm = confirmDelete();
if(confirm) {
var id = url.split('/')[2];
$('body').css('cursor', 'wait');
$(object + ', #pinned-wrapper-' + id).css('opacity', 0.33);
var confirm = confirmDelete();
if(confirm) {
var id = url.split('/')[2];
$('body').css('cursor', 'wait');
$(object + ', #pinned-wrapper-' + id).fadeTo('fast', 0.33, function () {
$.get(url).done(function() {
$(object + ', #pinned-wrapper-' + id).remove();
$('body').css('cursor', 'auto');
});
});
if($('#wall-item-pinned-' + id).length)
$.post('pin/pin', { 'id' : id });
return true;
}
else {
return false;
$.get(url, function() {
$(object + ', #pinned-wrapper-' + id).remove();
$('body').css('cursor', 'auto');
});
if($('#wall-item-pinned-' + id).length)
$.post('pin/pin', { 'id' : id });
return true;
}
else {
return false;
}
}
function dosubthread(ident) {
......
......@@ -18,7 +18,7 @@
{{foreach $entries as $item}}
<div class="cloud-container">
<div class="cloud-icon tiles"><a href="{{$item.fullPath}}">
<div class="cloud-icon tiles"><a href="{{$item.relPath}}">
{{if $item.photo_icon}}
<img src="{{$item.photo_icon}}" title="{{$item.type}}" >
{{else}}
......@@ -26,7 +26,7 @@
{{/if}}
</a>
</div>
<div class="cloud-title"><a href="{{$item.fullPath}}">
<div class="cloud-title"><a href="{{$item.relPath}}">
{{$item.displayName}}
</a>
</div>
......@@ -60,11 +60,11 @@
{{foreach $entries as $item}}
<tr id="cloud-index-{{$item.attachId}}">
<td><i class="fa {{$item.iconFromType}}" title="{{$item.type}}"></i></td>
<td><a href="{{$item.fullPath}}">{{$item.displayName}}</a></td>
<td><a href="{{$item.relPath}}">{{$item.displayName}}</a></td>
{{if $item.is_owner}}
<td class="cloud-index-tool">{{$item.attachIcon}}</td>
<td class="cloud-index-tool"><div id="file-edit-{{$item.attachId}}" class="spinner-wrapper"><div class="spinner s"></div></div></td>
<td class="cloud-index-tool"><i class="fakelink fa fa-pencil" onclick="filestorage(event, '{{$nick}}', {{$item.attachId}});"></i></td>
<td class="cloud-index-tool cursor-pointer" onclick="openCloseTR('cloud-tools-{{$item.attachId}}');"><i class="fa fa-pencil"></i></td>
<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}}
......@@ -74,10 +74,41 @@
<td class="d-none d-md-table-cell">{{$item.sizeFormatted}}</td>
<td class="d-none d-md-table-cell">{{$item.lastmodified}}</td>
</tr>
<tr id="cloud-tools-{{$item.attachId}}">
<td id="perms-panel-{{$item.attachId}}" colspan="9"></td>
<tr id="cloud-tools-{{$item.attachId}}" class="cloud-tools">
<td id="attach-edit-panel-{{$item.attachId}}" colspan="9">
<form id="attach_edit_form_{{$item.attachId}}" action="attach_edit/{{$nick}}/{{$item.attachId}}" method="post" class="acl-form" data-form_id="attach_edit_form_{{$item.attachId}}" data-allow_cid='{{$item.allow_cid}}' data-allow_gid='{{$item.allow_gid}}' data-deny_cid='{{$item.deny_cid}}' data-deny_gid='{{$item.deny_gid}}'>
<input type="hidden" name="resource" value="{{$item.resource}}" />
<input type="hidden" name="filename" value="{{$item.displayName}}" />
<input type="hidden" name="folder" value="{{$item.folder}}" />
{{include file="field_input.tpl" field=$item.newfilename}}
{{include file="field_select.tpl" field=$item.newfolder}}
{{if !$item.collection}}{{include file="field_checkbox.tpl" field=$notify}}{{/if}}
{{if $item.collection}}{{include file="field_checkbox.tpl" field=$recurse}}{{/if}}
<div id="attach-edit-tools-share" class="btn-group form-group">
{{if !$item.collection}}
<a href="/rpost?attachment=[attachment]{{$item.resource}},{{$item.revision}}[/attachment]" id="attach-btn" class="btn btn-outline-secondary btn-sm" title="{{$attach_btn_title}}">
<i class="fa fa-share-square-o jot-icons"></i>
</a>
{{/if}}
<button id="link-btn-{{$item.attachId}}" class="btn btn-outline-secondary btn-sm" type="button" onclick="openClose('link-code-{{$item.attachId}}');" title="{{$link_btn_title}}">
<i class="fa fa-link jot-icons"></i>
</button>
</div>
<div id="attach-edit-perms" class="btn-group pull-right">
<button id="dbtn-acl-{{$item.attachId}}" class="btn btn-outline-secondary btn-sm" data-toggle="modal" data-target="#aclModal" title="{{$permset}}" type="button">
<i id="jot-perms-icon-{{$item.attachId}}" class="fa fa-{{$item.lockstate}} jot-icons jot-perms-icon"></i>
</button>
<button id="dbtn-submit-{{$item.attachId}}" class="btn btn-primary btn-sm" type="submit" name="submit">
{{$edit}}
</button>
</div>
<div id="link-code-{{$item.attachId}}" class="form-group link-code">
<label for="">{{$cpldesc}}</label>
<input type="text" class="form-control" id="linkpasteinput" name="cutpasteextlink" value="{{$item.fullPath}}" onclick="this.select();"/>
</div>
</form>
</td>
</tr>
{{/foreach}}
</table>
{{/if}}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment