diff --git a/Sunfish/ShareWeb/$sunfish/$index.html b/Sunfish/ShareWeb/$sunfish/$index.html index d1e8d4b..1e23acf 100644 --- a/Sunfish/ShareWeb/$sunfish/$index.html +++ b/Sunfish/ShareWeb/$sunfish/$index.html @@ -6,13 +6,14 @@ - + + {Include} - + -{@Icon}{Icon}{/}{Name} +{@Icon}{Icon}{/}{Name} diff --git a/Sunfish/ShareWeb/$sunfish/konsole.js b/Sunfish/ShareWeb/$sunfish/konsole.js new file mode 100644 index 0000000..a9e0b69 --- /dev/null +++ b/Sunfish/ShareWeb/$sunfish/konsole.js @@ -0,0 +1,257 @@ +function Konsole() { + var ktab, kpanel, kin, kout; + + function init() { + build(); + install(); + } + + function build() { + ktab = document.createElement("div"); + ktab.style.position = "fixed"; + ktab.style.top = "0"; + ktab.style.right = "20px"; + ktab.style.width = "20px"; + ktab.style.height = "30px"; + ktab.style.fontFamily = "sans-serif"; + ktab.style.textAlign = "center"; + ktab.style.paddingTop = "5px"; + ktab.style.backgroundColor = "#bb5530"; + ktab.style.color = "white"; + ktab.style.borderBottomLeftRadius = "13px"; + ktab.style.borderBottomRightRadius = "3px"; + ktab.style.zIndex = "100"; + ktab.innerText = "K"; + ktab.addEventListener("click", function () { + if (kpanel.style.display == "none") + open(); + else + close(); + }); + kpanel = document.createElement("div"); + kpanel.style.position = "fixed"; + kpanel.style.top = "0"; + kpanel.style.left = "32px"; + kpanel.style.right = "32px"; + kpanel.style.bottom = "32px"; + kpanel.style.backgroundColor = "#e9e3df"; + kpanel.style.color = "white"; + kpanel.style.borderBottomLeftRadius = "39px"; + kpanel.style.borderBottomRightRadius = "9px"; + kpanel.style.fontFamily = "sans-serif"; + kpanel.style.color = "black"; + kpanel.style.display = "none"; + kpanel.style.zIndex = "99"; + var kinp = document.createElement("div"); + kinp.style.position = "absolute"; + kinp.style.left = "32px"; + kinp.style.right = "16px"; + kinp.style.bottom = "16px"; + kin = document.createElement("input"); + kin.style.width = "100%"; + kin.addEventListener("keypress", function (e) { + if (e.which == 13) + try { + var cmd = kin.value.trim(); + if (cmd == "") + return; + kin.value = ""; + exec(cmd); + } catch (e) { + error(e); + } + }); + kinp.appendChild(kin); + kpanel.appendChild(kinp); + kout = document.createElement("div"); + kout.style.position = "absolute"; + kout.style.top = "16px"; + kout.style.left = "16px"; + kout.style.right = "16px"; + kout.style.bottom = "48px"; + kout.style.overflow = "auto"; + kpanel.appendChild(kout); + } + + function install() { + if (!console) + console = {}; + function kk(name, type) { + console["_k_" + name] = console[name]; + console[name] = function (par) { + out(type, par); + console["_k_" + name](par); + } + } + kk("info", "i"); + kk("warn", "w"); + kk("log", "l"); + kk("debug", "d"); + kk("error", "e"); + window.onerror=function(err){ + ktab.style.backgroundColor = "tomato"; + out("e", err); + } + } + + function rowDiv(type, child) { + var d = document.createElement("div"); + var s = document.createElement("div"); + s.style.display = "inline-block"; + s.style.width = "24px"; + s.style.textAlign = "center"; + s.style.fontWeight = "bold"; + s.style.verticalAlign = "top"; + switch (type) { + case "!": + case "e": + s.style.color = "tomato"; + break; + case "<": + s.style.color = "#7bc012"; + break; + case ">": + s.style.color = "#00459e"; + break; + } + s.innerText = type; + d.appendChild(s); + var di = document.createElement("div"); + di.style.display = "inline-block"; + if (typeof child == "string") + di.innerText = child; + else + di.appendChild(child); + d.appendChild(di); + kout.appendChild(d); + } + + function error(s) { + if (s.stack) + rowDiv("!", s.stack); + else + rowDiv("!", "" + s); + } + + function writeIn(s) { + rowDiv(">", s); + } + + function dump(o, into, expanded) { + if (o === null || o === undefined) { + var d = document.createElement("div"); + d.style.color = "#777777"; + d.innerText = "<" + o + ">"; + into.appendChild(d); + return; + } + switch (typeof o) { + case "string": { + var d = document.createElement("div"); + d.style.color = "#009900"; + d.innerText = '"' + o + '"'; + into.appendChild(d); + } + break; + case "null": + case "undefined": { + var d = document.createElement("div"); + d.style.color = "#999999"; + d.innerText = "<" + o + ">"; + into.appendChild(d); + } + break; + case "number": + case "boolean": { + var d = document.createElement("div"); + d.innerText = o; + into.appendChild(d); + } + break; + case "object": + if (expanded) { + var r = document.createElement("div"); + var d = document.createElement("span"); + d.innerText = "{"; + r.appendChild(d); + for (var k in o) { + d = document.createElement("div"); + var s = document.createElement("span"); + s.style.verticalAlign = "top"; + s.style.color = "#554455"; + s.innerText = k + ":"; + d.appendChild(s); + s = document.createElement("span"); + s.style.display = "inline-block"; + dump(o[k], s, false); + d.appendChild(s); + r.appendChild(d); + } + d = document.createElement("span"); + d.innerText = "}"; + r.appendChild(d); + into.appendChild(r); + } else { + var d = document.createElement("div"); + d.style.backgroundColor = "#C9C9C9"; + d.style.borderRadius = "5px"; + d.style.cursor = "pointer"; + d.innerText = ""; + into.appendChild(d); + d.addEventListener("click", function () { + into.removeChild(d); + dump(o, into, true); + }); + } + break; + case "function": { + var d = document.createElement("div"); + d.style.color = "#000099"; + d.innerText = ""; + into.appendChild(d); + } + break; + default: + throw new Error("Cómo: " + typeof o) + } + } + + function out(type, data) { + var row = document.createElement("div"); + row.className = "object"; + row.style.display = "inline-block" + dump(data, row, true); + rowDiv(type, row); + } + + function exec(cmd) { + writeIn(cmd); + out("<", eval(cmd)); + } + + function showTab() { + document.body.appendChild(ktab); + } + + function hideTab() { + document.body.removeChild(ktab); + } + + function open(obj) { + document.body.appendChild(kpanel); + kpanel.style.display = ""; + ktab.style.backgroundColor = "#bb5530"; + } + + function close() { + kpanel.style.display = "none"; + } + + init(); + this.open = open; + this.close = close; + this.showTab = showTab; + this.hideTab = hideTab; +} + +var konsole = new Konsole(); \ No newline at end of file diff --git a/Sunfish/ShareWeb/$sunfish/style.css b/Sunfish/ShareWeb/$sunfish/style.css index 425ca79..ae8b2e0 100644 --- a/Sunfish/ShareWeb/$sunfish/style.css +++ b/Sunfish/ShareWeb/$sunfish/style.css @@ -67,7 +67,7 @@ color: #777777; } -#main-location>a>i.material-icons { +#main-location>a>i.material-icons-round { font-size: 1.3rem; vertical-align: bottom; } @@ -125,13 +125,23 @@ .item-actions { position: absolute; - bottom: 0.5rem; + bottom: 0.1rem; right: 0rem; + padding-right: 0.5rem; } -.item-actions i.material-icons { +.item-actions i.material-icons-round { font-size: 1.1rem; color: #aaaaaa; + margin-left: 0.3rem; +} + +.desktop .item-actions { + display: none; +} + +.desktop .item:hover .item-actions { + display: unset; } .popup { @@ -140,21 +150,78 @@ left: 50%; width: 30rem; max-width: 90%; - background-color: #201a12be; + background-color: rgba(39, 36, 31, 0.822); font-family: 'Roboto Condensed', sans-serif; font-weight: bold; color: white; padding: 1rem; margin-left: -15rem; - margin-top: -2rem; - border-radius: 1rem; + margin-top: -5rem; + border-radius: 0.5rem; } -.popup button { +.popup.error { + background-color: rgba(116, 11, 3, 0.822); +} + +.popup>.body { + padding-bottom: 1rem; + font-size: 1.1rem; +} + +.popup>.buttons { + text-align: right; +} + +.popup>.body>.input>input { + display: block; + width: 100%; +} + +.popup-wall { + z-index: 200; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.199); +} + +button { background-color: #e2d9cd; font-family: 'Open Sans', sans-serif; font-weight: bold; color: #424242; - border:0; + border: 0; border-radius: 1rem; + margin-left: 0.5rem; + padding: 0.3rem 1rem; + outline: none; +} + +button:hover { + background-color: #beb7ae; +} + +button.warning { + background-color: tomato; +} + +button.warning:hover { + background-color: #d4523b; +} + +input { + border: 0; + background-color: whitesmoke; + border-radius: 1rem; + font-family: 'Open Sans', sans-serif; + margin-top: 1rem; + padding: 0.3rem 1rem; + outline: none; +} + +input:hover { + background-color: #cecece; } \ No newline at end of file diff --git a/Sunfish/ShareWeb/$sunfish/sunfish-directory.js b/Sunfish/ShareWeb/$sunfish/sunfish-directory.js new file mode 100644 index 0000000..e232912 --- /dev/null +++ b/Sunfish/ShareWeb/$sunfish/sunfish-directory.js @@ -0,0 +1,46 @@ +sunfish.deleteFile = function (sender, file, isfolder) { + var ask; + var eitem=sender.parentElement.parentElement; + if (isfolder) + ask = "Sure to delete folder " + file + " and all its contents? can not be undone."; + else + ask = "Sure to delete " + file + "? can not be undone."; + sunfish.ask(ask, + { b: 'Cancel' }, + { + b: 'Delete', class: 'warning', do: function () { + var unlock = sunfish.lock("deleting..."); + sunfish.ajax(document.location.href + file + "?action=delete", { + ok: function (result) { + if (result == "OK"){ + unlock(); + eitem.parentNode.removeChild(eitem); + }else { + unlock(); + sunfish.error("Error deleting file", function () { + document.location.reload(); + }); + } + } + }) + } + } + + ); +} + +sunfish.renameFile = function (sender, file) { + var eitem=sender.parentElement.parentElement; + sunfish.askString('Rename to:', file, function (newName) { + sunfish.ajax(document.location.href + file + "?action=rename&to=" + newName, { + ok: function (result) { + if (result == "OK"){ + eitem.querySelector("div.item-name").innerText=newName; + }else + sunfish.error("Error renaming file", function () { + document.location.reload(); + }); + } + }); + }); +} \ No newline at end of file diff --git a/Sunfish/ShareWeb/$sunfish/sunfish.js b/Sunfish/ShareWeb/$sunfish/sunfish.js index 9a1d3dc..87838fb 100644 --- a/Sunfish/ShareWeb/$sunfish/sunfish.js +++ b/Sunfish/ShareWeb/$sunfish/sunfish.js @@ -1,4 +1,17 @@ function Sunfish() { + var mobile; + function init() { + mobileCheck = function () { + var check = false; + (function (a) { + if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true; + })(navigator.userAgent || navigator.vendor || window.opera); + return check; + }; + mobile = mobileCheck(); + document.body.className = mobile ? "mobile" : "desktop"; + konsole.showTab(); + } function build(def, into) { var el; @@ -12,11 +25,16 @@ var childs = def._; delete def.$; delete def._; - for (var i in def) - el[i] = def[i]; + for (var i in def) { + if (i == "style") + for (var sn in def) + el.style[sn] = def[sn]; + else + el[i] = def[i]; + } if (childs) if (typeof childs == "string") - build(childs, el); + el.appendChild(document.createTextNode(childs)); else for (var i in childs) build(childs[i], el); @@ -25,17 +43,24 @@ return el; } - function ask(question, bt1, bt2, bt3, bt4, bt5) { - var def = { $: "div", className: "popup", _: [{ $: "div", _: question }] }; + function ask(question, bt1, bt2, bt3, bt4, bt5, iserror) { + var wall = build({ $: "div", className: "popup-wall" }, document.body); + var def = { + $: "div", className: iserror ? "popup error" : "popup", _: [ + { $: "div", className: "body", _: [question] }, + { $: "div", className: "buttons", _: [] } + ] + }; var el; function addbt(bt) { if (bt) { if (bt.go) bt.do = function () { document.location = bt.go }; - def._.push({ - $: "button", _: bt.b, onclick: function () { - bt.do(); - document.body.removeChild(el); + def._[1]._.push({ + $: "button", className: bt.class, _: bt.b, + onclick: function () { + bt.do && bt.do(); + document.body.removeChild(wall); } }); } @@ -45,11 +70,71 @@ addbt(bt3); addbt(bt4); addbt(bt5); - el=build(def, document.body); + return el = build(def, wall); } + function askString(text, def, cb) { + var input; + var dialog = ask({ $: "div", className: "input", _: [text, { $: "input", id: "askInput", value: def }] }, { b: 'Cancel' }, { + b: 'Ok', class: "ok", do: function () { + var value = input.value; + cb && cb(value); + } + }); + input = dialog.querySelector("input#askInput"); + input.focus(); + input.selectionStart = 0; + input.selectionEnd = input.value.length; + input.onkeypress = function (e) { + if (e.keyCode == 13) + dialog.querySelector("button.ok").click(); + }; + } + + function say(text, cb) { + ask(text, { b: 'Ok', do: cb }); + } + + function error(text, cb) { + ask(text, { b: 'Ok', do: cb }, null, null, null, null, true); + } + + function lock(text) { + var wall = build({ $: "div", className: "popup-wall" }, document.body); + var def = { + $: "div", className: "popup", _: [ + { $: "div", className: "body", _: [text] } + ] + }; + build(def, wall); + return function () { + document.body.removeChild(wall); + } + } + + function go(to) { + document.location = to + } + + function ajax(url, ctrl) { + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) + ctrl.ok && ctrl.ok(xhr.responseText, xhr); + }; + xhr.open(ctrl.method || 'GET', url); + xhr.send(); + } + + this.init = init; this.build = build; this.ask = ask; + this.askString = askString; + this.say = say; + this.error = error; + this.lock = lock; + this.go = go; + this.ajax = ajax; } var sunfish = new Sunfish(); diff --git a/Sunfish/Sunfish/ApiMethod.cs b/Sunfish/Sunfish/ApiMethod.cs deleted file mode 100644 index 4c97583..0000000 --- a/Sunfish/Sunfish/ApiMethod.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace DolphinWebXplorer2 -{ - [AttributeUsage(AttributeTargets.Method)] - public class ApiMethod : Attribute - { - public ApiMethod(string name) - { - Name = name; - } - - public string Name { get; } - } -} diff --git a/Sunfish/Sunfish/Middleware/ApiRest.cs b/Sunfish/Sunfish/Middleware/ApiRest.cs deleted file mode 100644 index 82955f0..0000000 --- a/Sunfish/Sunfish/Middleware/ApiRest.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace DolphinWebXplorer2.Middleware -{ - public class ApiRest - { - //JsonNet.Serialize - public static void WriteError(string text, HttpCall call) - { - call.Write("{\"error\":\"" + text.Replace("\"", "\\\"") + "\"}"); - } - } -} diff --git a/Sunfish/Sunfish/Middleware/VFSFolder.cs b/Sunfish/Sunfish/Middleware/VFSFolder.cs index ca62830..89e3417 100644 --- a/Sunfish/Sunfish/Middleware/VFSFolder.cs +++ b/Sunfish/Sunfish/Middleware/VFSFolder.cs @@ -14,5 +14,8 @@ public abstract VFSItem GetItem(string path); public abstract string[] ListFiles(string path); public abstract string[] ListDirectories(string path); + public abstract bool DeleteFile(string path); + public abstract bool DeleteFolder(string path); + public abstract bool Rename(string from, string to); } } diff --git a/Sunfish/Sunfish/Middleware/VFSFolderFileSystem.cs b/Sunfish/Sunfish/Middleware/VFSFolderFileSystem.cs index 7b46287..b30297d 100644 --- a/Sunfish/Sunfish/Middleware/VFSFolderFileSystem.cs +++ b/Sunfish/Sunfish/Middleware/VFSFolderFileSystem.cs @@ -68,6 +68,59 @@ return lst.ToArray(); } + public override bool DeleteFile(string path) + { + string fpath = Path.Combine(basePath, path); + try + { + File.Delete(fpath); + return true; + } + catch + { + return false; + } + } + + public override bool DeleteFolder(string path) + { + string fpath = Path.Combine(basePath, path); + try + { + FSDeleteFolder(fpath); + return true; + } + catch + { + return false; + } + } + + public override bool Rename(string from, string to) + { + string ffrom = Path.Combine(basePath, from); + string realbase = Path.GetDirectoryName(ffrom); + string tto= Path.Combine(realbase, to); + try + { + Directory.Move(ffrom, tto); + return true; + } + catch + { + return false; + } + } + + private void FSDeleteFolder(string path) + { + foreach (string d in Directory.GetDirectories(path)) + FSDeleteFolder(d); + foreach (string d in Directory.GetFiles(path)) + File.Delete(d); + Directory.Delete(path); + } + public string GetFSPath(string path) { return Path.Combine(basePath, path); diff --git a/Sunfish/Sunfish/Middleware/VFSItem.cs b/Sunfish/Sunfish/Middleware/VFSItem.cs index ed05419..6911dab 100644 --- a/Sunfish/Sunfish/Middleware/VFSItem.cs +++ b/Sunfish/Sunfish/Middleware/VFSItem.cs @@ -9,7 +9,6 @@ { public class VFSItem { - public VFSItem(VFSFolder vfolder, string path, bool isFolder, long length) { Folder = vfolder; @@ -39,11 +38,23 @@ return Folder.ListFiles(Path); } + public bool Delete() + { + if (Directory) + return Folder.DeleteFolder(Path); + else + return Folder.DeleteFile(Path); + } + + public bool RenameTo(string newName) + { + return Folder.Rename(Path, newName); + } + public string Path { get; } public string Name { get; } public bool Directory { get; } public long Length { get; } - public VFSFolder Folder { get; } } } diff --git a/Sunfish/Sunfish/Program.cs b/Sunfish/Sunfish/Program.cs index 325ebf9..fa2d796 100644 --- a/Sunfish/Sunfish/Program.cs +++ b/Sunfish/Sunfish/Program.cs @@ -7,7 +7,7 @@ { static class Program { - public static string VERSION = "2.0b1"; + public static string VERSION = "2.0b3"; private static Form1 mainform; /// /// Punto de entrada principal para la aplicación. diff --git a/Sunfish/Sunfish/Services/RootService.cs b/Sunfish/Sunfish/Services/RootService.cs index ce669de..7149208 100644 --- a/Sunfish/Sunfish/Services/RootService.cs +++ b/Sunfish/Sunfish/Services/RootService.cs @@ -11,7 +11,6 @@ class RootService : SunfishService { public const string DIR_COMMON = "/$sunfish/"; - public const string DIR_API = "api/"; static RootService() { @@ -66,45 +65,7 @@ else if (path.StartsWith(DIR_COMMON)) { path = path.Substring(DIR_COMMON.Length); - if (path.StartsWith(DIR_API)) - { - // API - path = "/" + path.Substring(DIR_API.Length); - SunfishService servc = Sunfish.GetServiceForPath(ref path); - if (servc == null || servc is RootService) - { - ApiRest.WriteError("Service does not exists", call); - } - else - { - if (path.StartsWith("/")) - path = path.Substring(1); - if (path == "") - { - string meta; - if (!call.Parameters.TryGetValue("format", out meta)) - meta = "json"; - switch (meta) - { - case "js": - ApiRest.WriteError("Not implemented", call); - break; - case "json": - ApiRest.WriteError("Not implemented", call); - break; - default: - ApiRest.WriteError("Format only supports 'js' and 'json'.", call); - break; - } - } - else - { - //call method (path is method name) - } - } - - } - else if (path == "Sunfish.exe") + if (path == "Sunfish.exe") { // Self copy call.Response.ContentType = "application/x-msdownload"; diff --git a/Sunfish/Sunfish/Services/WebService.cs b/Sunfish/Sunfish/Services/WebService.cs index 7335dcd..7647340 100644 --- a/Sunfish/Sunfish/Services/WebService.cs +++ b/Sunfish/Sunfish/Services/WebService.cs @@ -1,5 +1,4 @@ using DolphinWebXplorer2.Middleware; -using Json.Net; using System; using System.Collections.Generic; using System.Drawing; @@ -43,19 +42,6 @@ ErrorPage(500, call, text); } - //private void DownloadAt(string path, HttpCall call) - //{ - // using (Stream s = vfs.OpenRead(path)) - // { - // if (s == null) - // { - // Error500(call, "Problem transfering file"); - // return; - // } - // call.Out.BaseStream.TransferFrom(s); - // } - //} - private void DownloadAt(VFSItem item, HttpCall call) { using (Stream s = item.OpenRead()) @@ -72,12 +58,12 @@ public override void Process(string path, HttpCall call) { - string meta; - if (!call.Parameters.TryGetValue("meta", out meta)) - meta = null; - else if (string.IsNullOrEmpty(meta)) - meta = null; - switch (meta) + string action; + if (!call.Parameters.TryGetValue("action", out action)) + action = null; + else if (string.IsNullOrEmpty(action)) + action = null; + switch (action) { case null: ProcessGET(path, call); @@ -85,6 +71,12 @@ case "icon": ProcessIcon(path, call); break; + case "delete": + ProcessDelete(path, call); + break; + case "rename": + ProcessRename(path, call); + break; default: call.HTTPBadRequest(); break; @@ -170,6 +162,37 @@ } } + private void ProcessDelete(string path, HttpCall call) + { + VFSItem fil = vfs.GetItem(path); + if (fil != null) + call.Write(fil.Delete() ? "OK" : "KO"); + else + call.Write("KO"); + } + + private void ProcessRename(string path, HttpCall call) + { + char[] forbiddenTo = { '/', '\\' }; + string to; + if (!call.Parameters.TryGetValue("to", out to)) + { + call.Write("KO (missing to)"); + return; + } + if (to.IndexOfAny(forbiddenTo) >= 0 || to == "." || to == "..") + { + call.Write("KO (forbidden)"); + return; + } + + VFSItem fil = vfs.GetItem(path); + if (fil != null) + call.Write(fil.RenameTo(to) ? "OK" : "KO"); + else + call.Write("KO"); + } + public void WriteIcon(Icon image, HttpCall call) { call.Response.ContentType = "image/vnd.microsoft.icon"; @@ -206,7 +229,21 @@ Icon = "/$sunfish/folder.png", Name = d, Description = "Directory", - Link = d + "/" + Link = d + "/", + Actions = new WebUILink[]{ + readOnly?null:new WebUILink() + { + Icon="drive_file_rename_outline", + Tooltip="Rename", + Click="sunfish.renameFile(this,'"+d+"');" + }, + allowDelete?new WebUILink() + { + Icon="delete", + Tooltip="Delete folder", + Click="sunfish.deleteFile(this,'"+d+"',true);" + }:null + } }); } fileList.Clear(); @@ -217,17 +254,28 @@ { items.Add(new WebUILink() { - Icon = d + "?meta=icon", + Icon = d + "?action=icon", Name = d, Description = "File", Link = d, Actions = new WebUILink[]{ + allowExec?new WebUILink() + { + Icon="api", + Tooltip="Open in server", + Link=d+"?action=open" + }:null, + readOnly?null:new WebUILink() + { + Icon="drive_file_rename_outline", + Tooltip="Rename", + Click="sunfish.renameFile(this,'"+d+"');" + }, allowDelete?new WebUILink() { Icon="delete", Tooltip="Delete file", - //Link="?action=delete" - Click="sunfish.ask('Sure to delete?',{b:'Cancel'},{b:'Delete',color:'red',go:'?action=delete&file="+d+"'});" + Click="sunfish.deleteFile(this,'"+d+"',false);" }:null } }); ; @@ -236,7 +284,8 @@ Dictionary data = new Dictionary(); data["Breadcrumb"] = GetBreadcrumb(path); //data["Actions"] = actions; - data["Items"] = items; + data["Items"] = items; + data["Include"] = ""; WebUI.WriteTemplate("directory-index", call, data); } @@ -270,16 +319,6 @@ { } - #region API - - [ApiMethod("rename")] - public bool ApiMove(string from, string to) - { - return false; - } - - #endregion - public override string Description => "For Webpages or file sharing"; } } diff --git a/Sunfish/Sunfish/Services/WebServiceConfigurator.cs b/Sunfish/Sunfish/Services/WebServiceConfigurator.cs index 6b02872..b3a3b71 100644 --- a/Sunfish/Sunfish/Services/WebServiceConfigurator.cs +++ b/Sunfish/Sunfish/Services/WebServiceConfigurator.cs @@ -23,9 +23,9 @@ { Elements = new ConfigurationElement[] { - new ConfigurationString(CFG_PATH,"Web path") + new ConfigurationString(CFG_PATH,"Directory") { - Tooltip = "Folder, zip or web-file path of site document root", + Tooltip = "Folder of site document root", IsDirectoiryPath = true, IsFilePath = true, Mandatory = true diff --git a/Sunfish/Sunfish/Sunfish.cs b/Sunfish/Sunfish/Sunfish.cs index 67988c2..cd58b9a 100644 --- a/Sunfish/Sunfish/Sunfish.cs +++ b/Sunfish/Sunfish/Sunfish.cs @@ -12,10 +12,10 @@ { class SunfishConfiguration { - public int Port = 90; - public bool Active = false; - public bool SunfishRoot = true; - public List Services = new List(); + public int Port { get; set; }= 90; + public bool Active { get; set; } = false; + public bool SunfishRoot { get; set; } = true; + public List Services { get; set; } = new List(); } public const string DEFAULT_CONF_FILE = "sunfish2"; @@ -32,24 +32,27 @@ static void Load() { - if (!File.Exists(DEFAULT_CONF_FILE)) - return; - - string json = File.ReadAllText(DEFAULT_CONF_FILE); - conf = JsonNet.Deserialize(json); - if (conf.Services == null) - conf.Services = new List(); - sroot.ShowMenu = conf.SunfishRoot; - foreach (SunfishServiceConfiguration ssc in conf.Services) + try { - srvs.Add(SunfishService.Instance(ssc)); + if (!File.Exists(DEFAULT_CONF_FILE)) + return; + conf = new SunfishConfiguration(); + conf = JsonNet.Deserialize(File.ReadAllText(DEFAULT_CONF_FILE)); + if (conf.Services == null) + conf.Services = new List(); + sroot.ShowMenu = conf.SunfishRoot; + foreach (SunfishServiceConfiguration ssc in conf.Services) + { + srvs.Add(SunfishService.Instance(ssc)); + } + if (conf.Active) + { + //Bypass set active check + conf.Active = false; + SetActive(true); + } } - if (conf.Active) - { - //Bypass set active check - conf.Active = false; - SetActive(true); - } + catch { } } public static void Save() diff --git a/Sunfish/Sunfish/Sunfish.csproj b/Sunfish/Sunfish/Sunfish.csproj index 19a8a8b..7a2be48 100644 --- a/Sunfish/Sunfish/Sunfish.csproj +++ b/Sunfish/Sunfish/Sunfish.csproj @@ -79,7 +79,6 @@ - @@ -105,12 +104,9 @@ - - - diff --git a/Sunfish/Sunfish/SunfishService.cs b/Sunfish/Sunfish/SunfishService.cs index 8449b05..ca793fb 100644 --- a/Sunfish/Sunfish/SunfishService.cs +++ b/Sunfish/Sunfish/SunfishService.cs @@ -85,7 +85,6 @@ } public abstract void Process(string path, HttpCall call); - protected abstract void Start(); protected abstract void Stop(); diff --git a/Sunfish/Sunfish/SunfishServiceConfiguration.cs b/Sunfish/Sunfish/SunfishServiceConfiguration.cs index 5f4f0fa..a01de08 100644 --- a/Sunfish/Sunfish/SunfishServiceConfiguration.cs +++ b/Sunfish/Sunfish/SunfishServiceConfiguration.cs @@ -8,7 +8,7 @@ { object value; if (Settings.TryGetValue(key, out value)) - return (T) value; + return (T)value; return def; }