|
|
<!DOCTYPE html> |
|
|
|
|
|
<html> |
|
|
<head> |
|
|
<script> |
|
|
var lastMsg, allowed=false, dir=null, noThumbs=null; |
|
|
|
|
|
var locStor = {}; |
|
|
|
|
|
function go() { |
|
|
console.log("deviceStorage"); |
|
|
var free = false; |
|
|
|
|
|
window.addEventListener("message", onMessage,false); |
|
|
|
|
|
|
|
|
var idb = { req: window["indexedDB"].open("deviceStorage") }; |
|
|
idb.req["onupgradeneeded"] = function(e) { |
|
|
|
|
|
var db = e.target.result; |
|
|
var os = db["createObjectStore"]("rsrc", { "keyPath": "k" }); |
|
|
} |
|
|
idb.req["onsuccess"] = function(e) { |
|
|
var db = locStor.db = e.target.result; |
|
|
var os = db["transaction"](["rsrc"], "readwrite")["objectStore"]("rsrc"); |
|
|
|
|
|
var req = os["get"]("fs0"); |
|
|
req["onsuccess"] = function(e) { |
|
|
if(e.target.result) { |
|
|
if(localStorage.getItem("forget")=="1") { |
|
|
localStorage.removeItem("forget"); |
|
|
} |
|
|
else { |
|
|
locStor.fset = e.target.result["fset"]; |
|
|
|
|
|
dir = locStor.fset; |
|
|
} |
|
|
|
|
|
} |
|
|
}; |
|
|
} |
|
|
|
|
|
allowed=false; send("ready",false); |
|
|
|
|
|
} |
|
|
|
|
|
async function makeFolder(path) { |
|
|
path = __getPath(path); |
|
|
var fld = dir; for(var i=0; i<path.length-1; i++) fld = await fld.getDirectoryHandle(path[i]); |
|
|
|
|
|
var dirHandle = await fld.getDirectoryHandle(path[path.length-1], { create: true }); |
|
|
send("0",""); |
|
|
} |
|
|
|
|
|
async function deleteFile(path) { |
|
|
path = __getPath(path); |
|
|
var fld = dir; for(var i=0; i<path.length-1; i++) fld = await fld.getDirectoryHandle(path[i]); |
|
|
|
|
|
await fld.removeEntry(path[path.length-1], { recursive: true }); |
|
|
send("0",""); |
|
|
} |
|
|
|
|
|
async function saveFile (path, buff) { |
|
|
path = __getPath(path); |
|
|
var fld = dir; for(var i=0; i<path.length-1; i++) fld = await fld.getDirectoryHandle(path[i]); |
|
|
|
|
|
var han = await fld.getFileHandle(path[path.length-1],{create:true}); |
|
|
|
|
|
var wrt = await han.createWritable(); |
|
|
await wrt.write(buff); |
|
|
await wrt.close(); |
|
|
send("0",""); |
|
|
} |
|
|
async function printFile(path) { |
|
|
path = __getPath(path); |
|
|
var fld = dir; for(var i=0; i<path.length-1; i++) fld = await fld.getDirectoryHandle(path[i]); |
|
|
|
|
|
var han = await fld.getFileHandle(path[path.length-1]); |
|
|
var fil = await han.getFile(); |
|
|
var buf = await fil.arrayBuffer(); |
|
|
window.parent.postMessage(buf,"*"); |
|
|
} |
|
|
|
|
|
var fmap,left,fls, gtime, timg; |
|
|
async function printFolder(path) { |
|
|
path = __getPath(path); |
|
|
var fld = dir; for(var i=0; i<path.length; i++) fld = await fld.getDirectoryHandle(path[i]); |
|
|
|
|
|
fls = []; fmap={}; left=0; timg=0; gtime=Date.now(); |
|
|
var time = Date.now(), cnt=0, gotFile=false; |
|
|
for await (var entry of fld.values()) { |
|
|
var file = [entry.name,-1]; fls.push(file); |
|
|
|
|
|
|
|
|
if(entry.kind=="file") { |
|
|
gotFile=true; |
|
|
fmap[entry.name]=fls.length-1; left++; |
|
|
entry.getFile().then(fileLoaded); |
|
|
|
|
|
} |
|
|
} |
|
|
if(!gotFile) send("0",fls); |
|
|
} |
|
|
async function fileLoaded(fil) { |
|
|
file = fls[fmap[fil.name]]; |
|
|
await makeFile(fil,file); left--; |
|
|
if(left==0) { |
|
|
console.log(Date.now()-gtime, timg); |
|
|
send("0",fls); |
|
|
} |
|
|
} |
|
|
|
|
|
async function makeFile(fil, file) { |
|
|
var np = fil.name.split("."), ext = (np.length==1 ? "" : np.pop()).toLowerCase(); |
|
|
file[1]=fil.size; |
|
|
file.push(~~(fil.lastModified/1000)); |
|
|
if(ext=="jpeg") ext="jpg"; |
|
|
if(ext=="tiff") ext="tif"; |
|
|
if(["dng","cr2","nef","arw","3fr","fff","gpr"].indexOf(ext)!=-1) ext="tif"; |
|
|
|
|
|
if(noThumbs) ext="---"; |
|
|
var thmb=null; |
|
|
if(thmb==null && (ext=="jpg" || ext=="tif")) { |
|
|
var lim = 130000; |
|
|
var buf = await fil.slice(0,(lim*1.5>fil.size) ? fil.size : lim).arrayBuffer(); |
|
|
if(ext=="jpg" && buf.byteLength==fil.size) thmb = bufToUrl(buf, "jpg"); |
|
|
else thmb=findJPG(fil.name,buf); |
|
|
} |
|
|
|
|
|
if(thmb==null && (ext=="psd" || ext=="psb")) { |
|
|
var buf = await fil.slice(0,4096).arrayBuffer(); |
|
|
buf = new Uint8Array(buf); |
|
|
var off = 26; |
|
|
var clen = readUint(buf,off); off+=4; |
|
|
off+=clen; |
|
|
var rlen = readUint(buf,off); off+=4; |
|
|
|
|
|
if(off+rlen<=4096) buf=buf.slice(off,off+rlen); |
|
|
else buf = new Uint8Array(await fil.slice(off,off+rlen).arrayBuffer()); |
|
|
|
|
|
off = 0; |
|
|
while(off<buf.length) { |
|
|
var sign = readASCII(buf,off,4); off+=4; |
|
|
var resID = readUshort(buf,off); off+=2; |
|
|
var sz = buf[off]; |
|
|
off+=sz+(1-(sz&1))+1; |
|
|
|
|
|
var asiz = readUint(buf,off); off+=4; |
|
|
if(resID==1036) { |
|
|
|
|
|
var tsz = readUint(buf,off+20); |
|
|
var io = off+28; |
|
|
thmb = bufToUrl(buf.slice(io,io+tsz).buffer,"jpg"); |
|
|
break; |
|
|
} |
|
|
off+=asiz+(asiz&1); |
|
|
} |
|
|
} |
|
|
if(thmb==null && fil.size<100000 && ["png","svg","bmp","gif","webp"].indexOf(ext)!=-1) { |
|
|
var buf = await fil.arrayBuffer(); |
|
|
if(ext=="png") { |
|
|
var data=new Uint8Array(buf), off=16; |
|
|
var bf = new Uint8Array(4), dim=[]; |
|
|
for(var i=0; i<2; i++) { |
|
|
for(var j=0; j<4; j++) bf[j] = data[off+3-j]; |
|
|
dim.push((new Uint32Array(bf.buffer))[0]); |
|
|
} |
|
|
if(dim[0]*dim[1]<1e6) thmb=bufToUrl(buf,ext); |
|
|
} |
|
|
else thmb=bufToUrl(buf,ext); |
|
|
} |
|
|
if(thmb) { file.push(thmb); timg++; } |
|
|
} |
|
|
|
|
|
function findJPG(name, buf) { |
|
|
buf = new Uint8Array(buf); |
|
|
var d8=-1, d9=-1, end=buf.length-1; |
|
|
var ints = []; |
|
|
for(var i=2; i<end; i++) { |
|
|
if(buf[i]==255) { |
|
|
var b1=buf[i+1], b2=buf[i+2], b3 = buf[i+3]; |
|
|
|
|
|
if (d8==-1 && b1==0xd8 && b2==0xff) d8=i; |
|
|
else if(d8!=-1 && b1==0xd9) { d9=i; ints.push(d8,d9); d8=d9=-1; } |
|
|
} |
|
|
} |
|
|
if(ints.length!=0) { |
|
|
d8=ints[0]; d9=ints[1]; |
|
|
return bufToUrl(buf.slice(d8, d9+2).buffer, "jpg"); |
|
|
} |
|
|
} |
|
|
|
|
|
var u8 = new Uint8Array(4); |
|
|
var u16 = new Uint16Array(u8.buffer); |
|
|
var u32 = new Uint32Array(u8.buffer); |
|
|
function readASCII (b, o, l) { var out=""; for(var i=0; i<l; i++) out+=String.fromCharCode(b[o+i]); return out; } |
|
|
function readUshort(b, o) { u8[0]=b[o+1]; u8[1]=b[o]; return u16[0]; } |
|
|
function readUint (b, o) { u8[0]=b[o+3]; u8[1]=b[o+2]; u8[2]=b[o+1]; u8[3]=b[o]; return u32[0]; } |
|
|
function bufToUrl(buf, ext) { |
|
|
var str=[]; buf=new Uint8Array(buf); |
|
|
for(var i=0; i<buf.length; i++) str.push(String.fromCharCode(buf[i])); |
|
|
return "data:image/"+ext+(ext=="svg"?"+xml":"")+";base64,"+btoa(str.join("")) |
|
|
} |
|
|
|
|
|
async function askPermissions() { |
|
|
if(dir) { |
|
|
if(await dir.requestPermission({mode:"readwrite"})!="granted") { send("1","You must give us access to some folder."); return; } |
|
|
} |
|
|
else { |
|
|
try { dir = await window.showDirectoryPicker(); } |
|
|
catch(e) { console.log(e); send("1","You must give us access to some folder."); return; } |
|
|
locStor.fset = dir; |
|
|
|
|
|
var os = locStor.db["transaction"](["rsrc"], "readwrite")["objectStore"]("rsrc"); |
|
|
var ooo=os["put"]({ "k":"fs0", "fset":locStor.fset }); |
|
|
ooo.onerror = function(e) { console.log(e); alert("Storing failed. Browser says: "+e["target"]["error"]["message"],7000); } |
|
|
} |
|
|
allowed = true; printFolder("/"); |
|
|
} |
|
|
|
|
|
function onMessage(e) { |
|
|
if((typeof e.data) == "string") { |
|
|
|
|
|
|
|
|
if(window.showDirectoryPicker==null) { send("1","Your browser can not perform this feature."); return; } |
|
|
|
|
|
var msg = null; |
|
|
try { msg = JSON.parse(e.data); } catch(e) { return; } |
|
|
if(msg.code==null) return; |
|
|
|
|
|
if(!allowed) { askPermissions(); return; } |
|
|
|
|
|
|
|
|
if(msg.code=="show") { |
|
|
noThumbs=msg.nothumbs; |
|
|
printFolder(msg.prm); |
|
|
} |
|
|
else if(msg.code=="load") { |
|
|
printFile(msg.prm); |
|
|
} |
|
|
else if(msg.code=="delete") { |
|
|
deleteFile(msg.prm); |
|
|
} |
|
|
else if(msg.code=="save" && msg.prm.endsWith("/")) makeFolder(msg.prm.slice(0,-1)); |
|
|
else if(msg.code=="forget") { console.log("forget message"); localStorage.setItem("forget", "1"); send("0",""); } |
|
|
else if(msg.code=="rename") { |
|
|
send("1","We can not rename files in your coputer yet."); |
|
|
} |
|
|
|
|
|
lastMsg=msg; |
|
|
} |
|
|
else { |
|
|
if(lastMsg.code=="save") saveFile(lastMsg.prm, e.data); |
|
|
} |
|
|
} |
|
|
|
|
|
function __getPath(path) { |
|
|
var pth = []; if(path.length>1) pth=path.slice(1).split("/"); |
|
|
return pth; |
|
|
} |
|
|
|
|
|
function send(code,prm) { |
|
|
var time = Date.now(); |
|
|
var str = JSON.stringify({"code":code, "prm":prm}); |
|
|
|
|
|
window.parent.postMessage(str,"*"); |
|
|
} |
|
|
</script> |
|
|
</head> |
|
|
<body onload="go()"></body> |
|
|
</html> |