diff --git a/www/webdav.css b/www/webdav.css
index e0b43a8..89450a5 100644
--- a/www/webdav.css
+++ b/www/webdav.css
@@ -41,6 +41,10 @@ th, td {
border: 2px solid var(--g2-color);
}
+th {
+ word-break: break-all;
+}
+
td.thumb {
width: 5%;
}
diff --git a/www/webdav.js b/www/webdav.js
index d431db6..1b3d6c9 100644
--- a/www/webdav.js
+++ b/www/webdav.js
@@ -9,8 +9,8 @@ const WebDAVNavigator = (url, options) => {
const _ = key => typeof lang_strings != 'undefined' && key in lang_strings ? lang_strings[key] : key;
- const common_buttons = `
- `;
+ const rename_button = ``;
+ const delete_button = ``;
const edit_button = ``;
@@ -33,10 +33,6 @@ const WebDAVNavigator = (url, options) => {
const body_tpl = `
%title%
-
-
-
-
`;
- const dir_row_tpl = `%icon% | %name% | |
`;
- const file_row_tpl = `%icon% | %name% | %size% | %modified% | |
`;
+ const create_buttons = `
+
+
+ `;
+
+ const dir_row_tpl = `%icon% | %name% | %modified% | |
`;
+ const file_row_tpl = `%icon% | %name% | %size% | %modified% | |
`;
const propfind_tpl = `
-
+
-
+
`;
@@ -355,30 +356,53 @@ const WebDAVNavigator = (url, options) => {
var items = [[], []];
var title = null;
+ var root_permissions = null;
xml.querySelectorAll('response').forEach((node) => {
var item_uri = normalizeURL(node.querySelector('href').textContent);
+ var props = null;
+
+ node.querySelectorAll('propstat').forEach((propstat) => {
+ if (propstat.querySelector('status').textContent.match(/200/)) {
+ props = propstat;
+ }
+ });
+
+ // This item didn't return any properties, everything is 404?
+ if (!props) {
+ console.error('Cannot find properties for: ' + item_uri);
+ return;
+ }
+
var name = item_uri.replace(/\/$/, '').split('/').pop();
name = decodeURIComponent(name);
+ var permissions = (prop = node.querySelector('permissions')) ? prop.textContent : null;
+
if (item_uri == uri) {
title = name;
+ root_permissions = permissions;
return;
}
var is_dir = node.querySelector('resourcetype collection') ? true : false;
+ var index = sort_order == 'name' && is_dir ? 0 : 1;
- items[is_dir ? 0 : 1].push({
+ items[index].push({
'uri': item_uri,
'name': name,
'size': !is_dir && (prop = node.querySelector('getcontentlength')) ? parseInt(prop.textContent, 10) : null,
'mime': !is_dir && (prop = node.querySelector('getcontenttype')) ? prop.textContent : null,
'modified': (prop = node.querySelector('getlastmodified')) ? new Date(prop.textContent) : null,
'is_dir': is_dir,
+ 'permissions': permissions,
});
});
- items[0].sort((a, b) => a.name.localeCompare(b.name));
+ if (sort_order == 'name') {
+ items[0].sort((a, b) => a.name.localeCompare(b.name));
+ }
+
items[1].sort((a, b) => {
if (sort_order == 'date') {
return b.modified - a.modified;
@@ -391,8 +415,14 @@ const WebDAVNavigator = (url, options) => {
}
});
- // Sort with directories first
- items = items[0].concat(items[1]);
+ if (sort_order == 'name') {
+ // Sort with directories first
+ items = items[0].concat(items[1]);
+ }
+ else {
+ items = items[1];
+ }
+
var table = '';
var parent = uri.replace(/\/+$/, '').split('/').slice(0, -1).join('/') + '/';
@@ -405,9 +435,15 @@ const WebDAVNavigator = (url, options) => {
}
items.forEach(item => {
+ // Don't include files we cannot read
+ if (item.permissions !== null && item.permissions.indexOf('G') == -1) {
+ console.error('OC permissions deny read access to this file: ' + item.name, 'Permissions: ', item.permissions);
+ return;
+ }
+
var row = item.is_dir ? dir_row_tpl : file_row_tpl;
item.size = item.size !== null ? formatBytes(item.size).replace(/ /g, ' ') : null;
- item.icon = item.is_dir ? '📁' : item.uri.replace(/^.*\.(\w+)$/, '$1').toUpperCase();
+ item.icon = item.is_dir ? '📁' : (item.uri.indexOf('.') > 0 ? item.uri.replace(/^.*\.(\w+)$/, '$1').toUpperCase() : '');
item.modified = item.modified !== null ? formatDate(item.modified) : null;
item.name = html(item.name);
table += template(row, item);
@@ -416,13 +452,76 @@ const WebDAVNavigator = (url, options) => {
document.title = title;
document.querySelector('main').innerHTML = template(body_tpl, {'title': html(document.title), 'base_url': base_url, 'table': table});
+ var select = $('.sortorder');
+ select.value = sort_order;
+ select.onchange = () => {
+ sort_order = select.value;
+ window.localStorage.setItem('sort_order', sort_order);
+ reloadListing();
+ };
+
+ if (!root_permissions || root_permissions.indexOf('CK') != -1) {
+ $('.upload').insertAdjacentHTML('afterbegin', create_buttons);
+
+ $('.mkdir').onclick = () => {
+ openDialog(mkdir_dialog);
+ document.forms[0].onsubmit = () => {
+ var name = $('input[name=mkdir]').value;
+
+ if (!name) return false;
+
+ name = encodeURIComponent(name);
+
+ req('MKCOL', current_url + name).then(() => openListing(current_url + name + '/'));
+ return false;
+ };
+ };
+
+ $('.mkfile').onclick = () => {
+ openDialog(mkfile_dialog);
+ var t = $('input[name=mkfile]');
+ t.value = '.md';
+ t.focus();
+ t.selectionStart = t.selectionEnd = 0;
+ document.forms[0].onsubmit = () => {
+ var name = t.value;
+
+ if (!name) return false;
+
+ name = encodeURIComponent(name);
+
+ return reqAndReload('PUT', current_url + name, '');
+ };
+ };
+
+ var fi = $('input[type=file]');
+
+ $('.uploadfile').onclick = () => fi.click();
+
+ fi.onchange = () => {
+ if (!fi.files.length) return;
+
+ var body = new Blob(fi.files);
+ var name = fi.files[0].name;
+
+ name = encodeURIComponent(name);
+
+ return reqAndReload('PUT', current_url + name, body);
+ };
+ }
+
Array.from($('table').rows).forEach((tr) => {
var $$ = (a) => tr.querySelector(a);
var file_url = $$('a').href;
var file_name = $$('a').innerText;
var dir = $$('[colspan]');
var mime = !dir ? tr.getAttribute('data-mime') : 'dir';
- var buttons = $$('td.buttons div')
+ var buttons = $$('td.buttons div');
+ var permissions = tr.getAttribute('data-permissions');
+
+ if (permissions == 'null') {
+ permissions = null;
+ }
if (dir) {
$$('a').onclick = () => {
@@ -435,6 +534,7 @@ const WebDAVNavigator = (url, options) => {
if (dir && $$('a').getAttribute('href').length < uri.length) {
dir.setAttribute('colspan', 4);
tr.querySelector('td:last-child').remove();
+ tr.querySelector('td:last-child').remove();
return;
}
@@ -447,7 +547,43 @@ const WebDAVNavigator = (url, options) => {
}
// Add rename/delete buttons
- buttons.insertAdjacentHTML('afterbegin', common_buttons);
+ if (!permissions || permissions.indexOf('NV') != -1) {
+ buttons.insertAdjacentHTML('afterbegin', rename_button);
+
+ $$('.rename').onclick = () => {
+ openDialog(rename_dialog);
+ let t = $('input[name=rename]');
+ t.value = file_name;
+ t.focus();
+ t.selectionStart = 0;
+ t.selectionEnd = file_name.lastIndexOf('.');
+ document.forms[0].onsubmit = () => {
+ var name = t.value;
+
+ if (!name) return false;
+
+ name = encodeURIComponent(name);
+ name = name.replace(/%2F/, '/');
+
+ var dest = current_url + name;
+ dest = normalizeURL(dest);
+
+ return reqAndReload('MOVE', file_url, '', {'Destination': dest});
+ };
+ };
+
+ }
+
+ if (!permissions || permissions.indexOf('D') != -1) {
+ buttons.insertAdjacentHTML('afterbegin', delete_button);
+
+ $$('.delete').onclick = (e) => {
+ openDialog(delete_dialog);
+ document.forms[0].onsubmit = () => {
+ return reqAndReload('DELETE', file_url);
+ };
+ };
+ }
var view_url, edit_url;
@@ -485,135 +621,53 @@ const WebDAVNavigator = (url, options) => {
$$('a').download = file_name;
}
- if (mime.match(/^text\/|application\/x-empty/)) {
- buttons.insertAdjacentHTML('beforeend', edit_button);
+ if (!permissions || permissions.indexOf('W') != -1) {
+ if ( mime.match(/^text\/|application\/x-empty/)) {
+ buttons.insertAdjacentHTML('beforeend', edit_button);
- $$('.edit').onclick = (e) => {
- req('GET', file_url).then((r) => r.text().then((t) => {
- let md = file_url.match(/\.md$/);
- openDialog(md ? markdown_dialog : edit_dialog);
- var txt = $('textarea[name=edit]');
- txt.value = t;
+ $$('.edit').onclick = (e) => {
+ req('GET', file_url).then((r) => r.text().then((t) => {
+ let md = file_url.match(/\.md$/);
+ openDialog(md ? markdown_dialog : edit_dialog);
+ var txt = $('textarea[name=edit]');
+ txt.value = t;
- // Markdown editor
- if (md) {
- let pre = $('#md');
+ // Markdown editor
+ if (md) {
+ let pre = $('#md');
- txt.oninput = () => {
- pre.innerHTML = microdown.parse(html(txt.value));
+ txt.oninput = () => {
+ pre.innerHTML = microdown.parse(html(txt.value));
+ };
+
+ txt.oninput();
+
+ // Sync scroll, not perfect but better than nothing
+ txt.onscroll = (e) => {
+ var p = e.target.scrollTop / (e.target.scrollHeight - e.target.offsetHeight);
+ var target = e.target == pre ? txt : pre;
+ target.scrollTop = p * (target.scrollHeight - target.offsetHeight);
+ e.preventDefault();
+ return false;
+ };
+ }
+
+ document.forms[0].onsubmit = () => {
+ var content = txt.value;
+
+ return reqAndReload('PUT', file_url, content);
};
+ }));
+ };
+ }
+ else if (edit_url = wopi_getEditURL(file_url, mime)) {
+ buttons.insertAdjacentHTML('beforeend', edit_button);
- txt.oninput();
-
- // Sync scroll, not perfect but better than nothing
- txt.onscroll = (e) => {
- var p = e.target.scrollTop / (e.target.scrollHeight - e.target.offsetHeight);
- var target = e.target == pre ? txt : pre;
- target.scrollTop = p * (target.scrollHeight - target.offsetHeight);
- e.preventDefault();
- return false;
- };
- }
-
- document.forms[0].onsubmit = () => {
- var content = txt.value;
-
- return reqAndReload('PUT', file_url, content);
- };
- }));
- };
+ $$('.icon').classList.add('document');
+ $$('.edit').onclick = () => { wopi_open(file_url, edit_url); return false; };
+ }
}
- else if (edit_url = wopi_getEditURL(file_url, mime)) {
- buttons.insertAdjacentHTML('beforeend', edit_button);
-
- $$('.icon').classList.add('document');
- $$('.edit').onclick = () => { wopi_open(file_url, edit_url); return false; };
- }
-
- $$('.delete').onclick = (e) => {
- openDialog(delete_dialog);
- document.forms[0].onsubmit = () => {
- return reqAndReload('DELETE', file_url);
- };
- };
-
- $$('.rename').onclick = () => {
- openDialog(rename_dialog);
- let t = $('input[name=rename]');
- t.value = file_name;
- t.focus();
- t.selectionStart = 0;
- t.selectionEnd = file_name.lastIndexOf('.');
- document.forms[0].onsubmit = () => {
- var name = t.value;
-
- if (!name) return false;
-
- name = encodeURIComponent(name);
- name = name.replace(/%2F/, '/');
-
- var dest = current_url + name;
- dest = normalizeURL(dest);
-
- return reqAndReload('MOVE', file_url, '', {'Destination': dest});
- };
- };
-
});
-
- $('.mkdir').onclick = () => {
- openDialog(mkdir_dialog);
- document.forms[0].onsubmit = () => {
- var name = $('input[name=mkdir]').value;
-
- if (!name) return false;
-
- name = encodeURIComponent(name);
-
- req('MKCOL', current_url + name).then(() => openListing(current_url + name + '/'));
- return false;
- };
- };
-
- $('.mkfile').onclick = () => {
- openDialog(mkfile_dialog);
- var t = $('input[name=mkfile]');
- t.value = '.md';
- t.focus();
- t.selectionStart = t.selectionEnd = 0;
- document.forms[0].onsubmit = () => {
- var name = t.value;
-
- if (!name) return false;
-
- name = encodeURIComponent(name);
-
- return reqAndReload('PUT', current_url + name, '');
- };
- };
-
- var select = $('.sortorder');
- select.value = sort_order;
- select.onchange = () => {
- sort_order = select.value;
- window.localStorage.setItem('sort_order', sort_order);
- reloadListing();
- };
-
- var fi = $('input[type=file]');
-
- $('.uploadfile').onclick = () => fi.click();
-
- fi.onchange = () => {
- if (!fi.files.length) return;
-
- var body = new Blob(fi.files);
- var name = fi.files[0].name;
-
- name = encodeURIComponent(name);
-
- return reqAndReload('PUT', current_url + name, body);
- };
};
var current_url = url;