From d9986c54340c2a52142b7aaec4ae8cb0cb21a118 Mon Sep 17 00:00:00 2001 From: bohwaz Date: Mon, 10 Oct 2022 14:01:20 +0200 Subject: [PATCH] Move JS client to a separate repo --- .gitignore | 8 ++ Makefile | 6 +- README.md | 4 +- lib/KaraDAV/Server.php | 9 ++ lib/KaraDAV/WebDAV.php | 17 +++- www/files.css | 173 -------------------------------- www/files.js | 218 ----------------------------------------- 7 files changed, 37 insertions(+), 398 deletions(-) create mode 100644 .gitignore delete mode 100644 www/files.css delete mode 100644 www/files.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ec7987 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.gitignore +data/ +www/webdav.css +www/webdav.js +config.local.php +error.log +debug.log +lib/KD2/ \ No newline at end of file diff --git a/Makefile b/Makefile index 7ba82c4..34a9342 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,8 @@ -deps: +js-deps: + wget -O www/webdav.js https://raw.githubusercontent.com/kd2org/webdav-manager.js/main/webdav.js + wget -O www/webdav.css https://raw.githubusercontent.com/kd2org/webdav-manager.js/main/webdav.css + +php-deps: wget -O lib/KD2/WebDAV.php 'https://fossil.kd2.org/kd2fw/doc/tip/src/lib/KD2/WebDAV.php' wget -O lib/KD2/WebDAV_NextCloud.php 'https://fossil.kd2.org/kd2fw/doc/tip/src/lib/KD2/WebDAV_NextCloud.php' diff --git a/README.md b/README.md index 3b48ac4..c3366cf 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ Although this is a demo, this can be used as a simple but powerful file sharing This server features: -* User-friendly directory listings for file browsing with a web browser: - * Upload directly from browser +* User-friendly directory listings for file browsing with a web browser, using [WebDAV Manager.js](https://github.com/kd2org/webdav-manager.js) + * Upload directly from browser, using paste, or drag and drop * Rename * Delete * Create and edit text file diff --git a/lib/KaraDAV/Server.php b/lib/KaraDAV/Server.php index e72a0b3..0d20b04 100644 --- a/lib/KaraDAV/Server.php +++ b/lib/KaraDAV/Server.php @@ -17,6 +17,15 @@ class Server public function route(?string $uri = null): bool { + header('Access-Control-Allow-Origin: *', true); + $method = $_SERVER['REQUEST_METHOD'] ?? null; + + // Always say YES to OPTIONS + if ($method == 'OPTIONS') { + $this->dav->http_options(); + return true; + } + $nc = new NextCloud($this->dav, $this->users); if ($r = $nc->route($uri)) { diff --git a/lib/KaraDAV/WebDAV.php b/lib/KaraDAV/WebDAV.php index 637fea7..6de2d45 100644 --- a/lib/KaraDAV/WebDAV.php +++ b/lib/KaraDAV/WebDAV.php @@ -6,15 +6,24 @@ use KD2\WebDAV\Server as WebDAV_Server; class WebDAV extends WebDAV_Server { - protected function html_directory(string $uri, iterable $list, array $strings = self::LANGUAGE_STRINGS): ?string + protected function html_directory(string $uri, iterable $list): ?string { - $out = parent::html_directory($uri, $list, $strings); + $out = parent::html_directory($uri, $list); if (null !== $out) { - $out = str_replace('', sprintf('', WWW_URL), $out); - $out = str_replace('', sprintf('', WWW_URL), $out); + $out = str_replace('', sprintf('', WWW_URL), $out); } return $out; } + + public function http_options(): void + { + parent::http_options(); + + header('Access-Control-Allow-Origin: *'); + header('Access-Control-Allow-Credentials: true'); + header('Access-Control-Allow-Headers: Authorization, *'); + header('Access-Control-Allow-Methods: GET,HEAD,PUT,DELETE,COPY,MOVE,PROPFIND,MKCOL,LOCK,UNLOCK'); + } } diff --git a/www/files.css b/www/files.css deleted file mode 100644 index fe7e730..0000000 --- a/www/files.css +++ /dev/null @@ -1,173 +0,0 @@ -body { - text-align: center; -} - -table { - margin: 2em auto; -} - -table tr:nth-child(even) { - background: #eee; -} - -input[type=button], input[type=submit] { - font-size: 1.2em; - padding: .3em .5em; - margin: 0 .3em; - border: none; - background: #ccc; - border-radius: .2em; - cursor: pointer; -} - -td input[type=button], td input[type=submit] { - font-size: 1em; -} - -input[type=text], textarea { - font-size: 1.2em; - padding: .3em .5em; - border: none; - background: #fff; - border-radius: .2em; - width: calc(100% - 1em); -} - -input:focus, textarea:focus { - box-shadow: 0px 0px 5px blue; - outline: 1px solid #999; -} - -input[type=button]:hover, input[type=submit]:hover { - color: darkred; - text-decoration: underline; - background: #fff; - box-shadow: 0px 0px 5px #000; -} - -.close { - text-align: right; - margin: 0; -} - -.close input { - font-size: .8em; -} - -input[type=submit] { - float: right; -} - -dialog { - position: absolute; - top: 1em; - right: 1em; - bottom: 1em; - left: 1em; - box-shadow: 0px 0px 5px #000; - background: #eee; - border: none; - border-radius: .5em; -} - -dialog form div { - clear: both; - margin: 2em 0; - text-align: center; -} - -.a { - margin: 1em 0; -} - -#mdp div, #mdp textarea { - width: calc(100% - 1em); - padding: .5em; - font-size: 1em; - height: calc(100% - 1em); - text-align: left; - margin: 0; -} - -#md { - overflow: hidden; - overflow-x: auto; -} - -#mdp { - display: grid; - grid-template-columns: 1fr 1fr; - grid-gap: .2em; - background: #ddd; - height: 82vh; -} - -dialog.preview { - height: calc(100%); - width: calc(100%); - top: 0; - left: 0; - right: 0; - bottom: 0; - padding: 0; - border-radius: 0; - background: #ddd; - overflow: hidden; -} - -iframe, .md_preview { - overflow: auto; - position: absolute; - top: 2em; - left: 0; - width: calc(100vw); - height: calc(100% - 2em); - padding: 0; - margin: 0; - border: none; -} - -.preview form { - height: calc(100% - 2em); - display: flex; - align-items: center; - justify-content: center; -} - -.preview form > div { - height: 100%; - margin: 0; - display: flex; - align-items: center; - justify-content: center; -} - -.md_preview { - width: calc(100vw - 2em); - height: calc(100vh - 2em); - padding: 1em; - text-align: left; -} - -.preview .close { - height: 2em; - text-align: center; - font-size: 1em; - display: block; - width: 100%; - margin: 0; - padding: 0; - border-radius: 0; - background: #fff; - color: #000; - box-shadow: 0px 0px 5px #000; -} - -.preview img { - max-width: 95%; - max-height: 95%; -} - -input[name=rename] { - width: 30em; -} \ No newline at end of file diff --git a/www/files.js b/www/files.js deleted file mode 100644 index 229b7ab..0000000 --- a/www/files.js +++ /dev/null @@ -1,218 +0,0 @@ -// Microdown -// https://github.com/commit-intl/micro-down -const microdown=function(){function l(n,e,r){return"<"+n+(r?" "+Object.keys(r).map(function(n){return r[n]?n+'="'+(a(r[n])||"")+'"':""}).join(" "):"")+">"+e+""}function c(n,e){return e=n.match(/^[+-]/m)?"ul":"ol",n?"<"+e+">"+n.replace(/(?:[+-]|\d+\.) +(.*)\n?(([ \t].*\n?)*)/g,function(n,e,r){return"
  • "+g(e+"\n"+(t=r||"").replace(new RegExp("^"+(t.match(/^\s+/)||"")[0],"gm"),"").replace(o,c))+"
  • ";var t})+"":""}function e(r,t,u,c){return function(n,e){return n=n.replace(t,u),l(r,c?c(n):n)}}function t(n,u){return f(n,[//g,"\x3c!--$1--\x3e",/^("""|```)(.*)\n((.*\n)*?)\1/gm,function(n,e,r,t){return'"""'===e?l("div",p(t,u),{class:r}):u&&u.preCode?l("pre",l("code",a(t),{class:r})):l("pre",a(t),{class:r})},/(^>.*\n?)+/gm,e("blockquote",/^> ?(.*)$/gm,"$1",r),/((^|\n)\|.+)+/g,e("table",/^.*(\n\|---.*?)?$/gm,function(n,t){return e("tr",/\|(-?)([^|]*)\1(\|$)?/gm,function(n,e,r){return l(e||t?"th":"td",g(r))})(n.slice(0,n.length-(t||"").length))}),o,c,/#\[([^\]]+?)]/g,'',/^(#+) +(.*)(?:$)/gm,function(n,e,r){return l("h"+e.length,g(r))},/^(===+|---+)(?=\s*$)/gm,"
    "],p,u)}var i=this,a=function(n){return n?n.replace(/"/g,""").replace(//g,">"):""},o=/(?:(^|\n)([+-]|\d+\.) +(.*(\n[ \t]+.*)*))+/g,g=function c(n,i){var o=[];return n=(n||"").trim().replace(/`([^`]*)`/g,function(n,e){return"\\"+o.push(l("code",a(e)))}).replace(/[!&]?\[([!&]?\[.*?\)|[^\]]*?)]\((.*?)( .*?)?\)|(\w+:\/\/[$\-.+!*'()/,\w]+)/g,function(n,e,r,t,u){return u?i?n:"\\"+o.push(l("a",u,{href:u})):"&"==n[0]?(e=e.match(/^(.+),(.+),([^ \]]+)( ?.+?)?$/),"\\"+o.push(l("iframe","",{width:e[1],height:e[2],frameborder:e[3],class:e[4],src:r,title:t}))):"\\"+o.push("!"==n[0]?l("img","",{src:r,alt:e,title:t}):l("a",c(e,1),{href:r,title:t}))}),n=function r(n){return n.replace(/\\(\d+)/g,function(n,e){return r(o[Number.parseInt(e)-1])})}(i?n:r(n))},r=function t(n){return f(n,[/([*_]{1,3})((.|\n)+?)\1/g,function(n,e,r){return e=e.length,r=t(r),1"],t)},f=function(n,e,r,t){for(var u,c=0;c/g, ">") - .replace(/"/g, """) - .replace(/'/g, "'"); -} - -const url = location.pathname; - -const PREVIEW_TYPES = /^image\/(png|webp|svg|jpeg|jpg|gif|png)|^application\/pdf|^text\/|^audio\/|^video\//; - -const upload_form = `
    - - - - -
    `; - -const file_buttons = ` - `; - -const edit_button = ``; - -const mkdir_dialog = ``; -const mkfile_dialog = ``; -const rename_dialog = ``; -const edit_dialog = ``; -const markdown_dialog = `
    `; -const delete_dialog = `

    Confirm delete ?

    `; - -const dialog_tpl = `

    %s
    %b
    `; - -const req = (method, url, body, headers) => { - fetch(url, {method, body, headers}).then((r) => location.reload()); - return false; -}; - -var evt, evt2; - -const dialog = (hash, html, ok_btn = true) => { - location.hash = '#' + hash; - var tpl = dialog_tpl.replace(/%b/, ok_btn ? '

    ' : ''); - $('body').insertAdjacentHTML('beforeend', tpl.replace(/%s/, html)); - $('.close input').onclick = close; - evt = window.addEventListener('keyup', (e) => { - if (e.key != 'Escape') return; - e.preventDefault(); - close(); - return false; - }); - evt2 = window.addEventListener('hashchange', (e) => { - if (location.hash == '') { - close(); - } - }); - if (a = $('dialog form input, dialog form textarea')) a.focus(); -}; - -const close = () => { - if (!$('dialog')) return; - $('dialog').remove(); - window.removeEventListener('keyup', evt); - evt = null; - window.removeEventListener('hashchange', evt2); - evt2 = null; - location.hash = ''; -}; - -const $ = (a) => document.querySelector(a); - -$('h1').insertAdjacentHTML('afterend', upload_form); - -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 type = !dir ? $$('td:nth-child(3)').innerText : 'dir'; - - // For back link - if (dir && $$('a').getAttribute('href').indexOf('..') != -1) { - dir.setAttribute('colspan', 4); - return; - } - - // Add rename/delete buttons - tr.insertAdjacentHTML('beforeend', file_buttons); - - if (type.match(PREVIEW_TYPES)) { - $$('a').onclick = () => { - if (file_url.match(/\.md$/)) { - dialog(file_name, '
    ', false); - fetch(file_url).then((r) => r.text().then((t) => { - $('.md_preview').innerHTML = microdown.parse(html(t)); - })); - } - else if (type.match(/^image\//)) { - dialog(file_name, ``, false); - } - else if (type.match(/^audio\//)) { - dialog(file_name, `