Improved file upload to device.

Ylian Saint-Hilaire committed Aug 13, 2020 at 12:29 UTC 204cca9ef67c1b206bd8dd2bfe8268b6b914a955
5 files changed +301 -355
agents/meshcore.js
+35 -25
@@ -1268,7 +1268,7 @@ function createMeshCore(agent) {
1268 */
1269
1270 // If there is a upload or download active on this connection, close the file
1271 - if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; }
1271 + if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; delete this.httprequest.uploadFileid; delete this.httprequest.uploadFilePath; }
1272 if (this.httprequest.downloadFile) { fs.closeSync(this.httprequest.downloadFile); delete this.httprequest.downloadFile; }
1273
1274 // Clean up WebRTC
@@ -1291,31 +1291,18 @@ function createMeshCore(agent) {
1291 //sendConsoleText('OnTunnelData, ' + data.length + ', ' + typeof data + ', ' + data);
1292
1293 // If this is upload data, save it to file
1294 - if (this.httprequest.uploadFile) {
1295 - if (typeof data == 'object') {
1296 - // Save the data to file being uploaded.
1297 - if (this.httprequest.uploadFile) {
1298 - try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { sendConsoleText('FileSave ERROR'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1299 - this.write(Buffer.from(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data.
1300 - }
1301 - } else if (typeof data == 'string') {
1302 - // Close the file and confirm. We need to make this added round trip since websocket deflate compression can cause the last message before a websocket close to not be received.
1303 - if (this.httprequest.uploadFile) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; }
1304 - this.write(Buffer.from(JSON.stringify({ action: 'uploaddone', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
1305 - this.end();
1294 + if ((this.httprequest.uploadFile) && (typeof data == 'object') && (data[0] != 123)) {
1295 + // Save the data to file being uploaded.
1296 + if (data[0] == 0) {
1297 + // If data starts with zero, skip the first byte. This is used to escape binary file data from JSON.
1298 + try { fs.writeSync(this.httprequest.uploadFile, data, 1, data.length - 1); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1299 + } else {
1300 + // If data does not start with zero, save as-is.
1301 + try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { sendConsoleText('FileUpload Error'); this.write(Buffer.from(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
1302 }
1303 + this.write(Buffer.from(JSON.stringify({ action: 'uploadack', reqid: this.httprequest.uploadFileid }))); // Ask for more data.
1304 return;
1305 }
1309 - /*
1310 - // If this is a download, send more of the file
1311 - if (this.httprequest.downloadFile) {
1312 - var buf = Buffer.alloc(4096);
1313 - var len = fs.readSync(this.httprequest.downloadFile, buf, 0, 4096, null);
1314 - this.httprequest.downloadFilePtr += len;
1315 - if (len > 0) { this.write(buf.slice(0, len)); } else { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; this.end(); }
1316 - return;
1317 - }
1318 - */
1306
1307 if (this.httprequest.state == 0) {
1308 // Check if this is a relay connection
@@ -1867,8 +1854,7 @@ function createMeshCore(agent) {
1854 this.on('data', onTunnelControlData);
1855 //this.write('MeshCore KVM Hello!1');
1856
1870 - } else if (this.httprequest.protocol == 5)
1871 - {
1857 + } else if (this.httprequest.protocol == 5) {
1858 //
1859 // Remote Files
1860 //
@@ -2104,12 +2090,36 @@ function createMeshCore(agent) {
2090 if (this.httprequest.uploadFile != null) { fs.closeSync(this.httprequest.uploadFile); delete this.httprequest.uploadFile; }
2091 if (cmd.path == undefined) break;
2092 var filepath = cmd.name ? obj.path.join(cmd.path, cmd.name) : cmd.path;
2093 + this.httprequest.uploadFilePath = filepath;
2094 MeshServerLog('Upload: \"' + filepath + '\"', this.httprequest);
2095 try { this.httprequest.uploadFile = fs.openSync(filepath, 'wbN'); } catch (e) { this.write(Buffer.from(JSON.stringify({ action: 'uploaderror', reqid: cmd.reqid }))); break; }
2096 this.httprequest.uploadFileid = cmd.reqid;
2097 if (this.httprequest.uploadFile) { this.write(Buffer.from(JSON.stringify({ action: 'uploadstart', reqid: this.httprequest.uploadFileid }))); }
2098 break;
2099 }
2100 + case 'uploaddone': {
2101 + // Indicates that an upload is done
2102 + if (this.httprequest.uploadFile) {
2103 + fs.closeSync(this.httprequest.uploadFile);
2104 + this.write(Buffer.from(JSON.stringify({ action: 'uploaddone', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
2105 + delete this.httprequest.uploadFile;
2106 + delete this.httprequest.uploadFileid;
2107 + delete this.httprequest.uploadFilePath;
2108 + }
2109 + break;
2110 + }
2111 + case 'uploadcancel': {
2112 + // Indicates that an upload is canceled
2113 + if (this.httprequest.uploadFile) {
2114 + fs.closeSync(this.httprequest.uploadFile);
2115 + fs.unlinkSync(this.httprequest.uploadFilePath);
2116 + this.write(Buffer.from(JSON.stringify({ action: 'uploadcancel', reqid: this.httprequest.uploadFileid }))); // Indicate that we closed the file.
2117 + delete this.httprequest.uploadFile;
2118 + delete this.httprequest.uploadFileid;
2119 + delete this.httprequest.uploadFilePath;
2120 + }
2121 + break;
2122 + }
2123 case 'copy': {
2124 // Copy a bunch of files from scpath to dspath
2125 for (var i in cmd.names) {
public/scripts/amt-wsman-0.2.0-min.js
+1 -1
@@ -1 +1 @@
1 -var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return'<w:SelectorSet><w:Selector Name="InstanceID">'+e.InstanceID+"</w:Selector></w:SelectorSet>";var s="<w:SelectorSet>";for(var r in e)if(e.hasOwnProperty(r)){if(s+='<w:Selector Name="'+r+'">',e[r].ReferenceParameters){s+="<a:EndpointReference>",s+="<a:Address>"+e[r].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+e[r].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o<a.length;o++)s+="<w:Selector"+l(a[o])+">"+a[o].Value+"</w:Selector>";else s+="<w:Selector"+l(a)+">"+a.Value+"</w:Selector>";s+="</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>"}else s+=e[r];s+="</w:Selector>"}return s+="</w:SelectorSet>"}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns="http://www.w3.org/2003/05/soap-envelope" '+a+"><Header><a:Action>"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,d,c){var m="",i="";null!=d&&null!=c&&(m="<t:IssuedTokens><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>"+d+'</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">'+c+"</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>",i='<Auth Profile="http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/secprofile/http/digest"/>'),l=null!=l&&null!=l?"<a:ReferenceParameters>"+l+"</a:ReferenceParameters>":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(n)+m+'</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/'+s+'"><e:NotifyTo><a:Address>'+r+"</a:Address></e:NotifyTo>"+i+"</e:Delivery><e:Expires>PT0.000000S</e:Expires></e:Subscribe>";p.PerformAjax(u+"</Body></Envelope>",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(o)+"</Header><Body><e:Unsubscribe/>";p.PerformAjax(t+"</Body></Envelope>",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>"+w(t)+"</Header><Body>"+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="<r:"+r+' xmlns:r="'+e+'">';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+="<r:"+o+"><a:Address>"+s[o].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+s[o].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n<t.length;n++)a+="<w:Selector"+l(t[n])+">"+t[n].Value+"</w:Selector>";else a+="<w:Selector"+l(t)+">"+t.Value+"</w:Selector>";a+="</w:SelectorSet></a:ReferenceParameters></r:"+o+">"}else if(Array.isArray(s[o]))for(n=0;n<s[o].length;n++)a+="<r:"+o+">"+s[o][n].toString()+"</r:"+o+">";else a+="<r:"+o+">"+s[o].toString()+"</r:"+o+">";return a+="</r:"+r+">"}(e,s);p.PerformAjax(n+"</Body></Envelope>",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(t)+"</Header><Body><g:"+n+' xmlns:g="'+e+'">';for(var d in s)l+="<g:"+d+">"+s[d]+"</g:"+d+">";p.PerformAjax(l+"</g:"+n+"></Body></Envelope>",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout></Header><Body><r:"+t+' xmlns:r="'+e+'">'+s+"</r:"+t+"></Body></Envelope>",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(s)+"</Header><Body /></Envelope>";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var d in r)if(null!=r[d])if(Array.isArray(r[d]))for(var c in r[d])l+="<r:"+d+">"+r[d][c]+"</r:"+d+">";else l+="<r:"+d+">"+r[d]+"</r:"+d+">";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+"</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(n)+"</Header><Body><r:"+s+'_INPUT xmlns:r="'+e+'">'+r+"</r:"+s+"_INPUT></Body></Envelope>",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" /></Body></Envelope>',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration"><EnumerationContext>'+s+"</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o<a.childNodes.length;o++){var t=a.childNodes[o];r.Header[t.localName]=t.textContent}var n=s.getElementsByTagName("Body")[0];return(n=n||s.getElementsByTagName("a:Body")[0])?(0<n.childNodes.length&&((e=n.childNodes[0].localName).indexOf("_OUTPUT")==e.length-7&&(e=e.substring(0,e.length-7)),r.Header.Method=e,r.Body=function e(s){var r,a={};for(var o=0;o<s.childNodes.length;o++){var t=s.childNodes[o];"true"==(r=0==t.childElementCount?t.textContent:e(t))&&(r=!0),"false"==r&&(r=!1);var n=r;if(0<t.attributes.length){n={Value:r};for(var l=0;l<t.attributes.length;l++)n["@"+t.attributes[l].name]=t.attributes[l].value}a[t.localName]instanceof Array?a[t.localName].push(n):null==a[t.localName]?a[t.localName]=n:a[t.localName]=[a[t.localName],n]}return a}(n.childNodes[0])),r):null}catch(e){return console.log("Unable to parse XML: "+s),null}},p}
\ No newline at end of file
1 +var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return'<w:SelectorSet><w:Selector Name="InstanceID">'+e.InstanceID+"</w:Selector></w:SelectorSet>";var s="<w:SelectorSet>";for(var r in e)if(e.hasOwnProperty(r)){if(s+='<w:Selector Name="'+r+'">',e[r].ReferenceParameters){s+="<a:EndpointReference>",s+="<a:Address>"+e[r].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+e[r].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o<a.length;o++)s+="<w:Selector"+l(a[o])+">"+a[o].Value+"</w:Selector>";else s+="<w:Selector"+l(a)+">"+a.Value+"</w:Selector>";s+="</w:SelectorSet></a:ReferenceParameters></a:EndpointReference>"}else s+=e[r];s+="</w:Selector>"}return s+="</w:SelectorSet>"}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns="http://www.w3.org/2003/05/soap-envelope" '+a+"><Header><a:Action>"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,c,d){var m="",i="";null!=c&&null!=d&&(m="<t:IssuedTokens><t:RequestSecurityTokenResponse><t:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</t:TokenType><t:RequestedSecurityToken><se:UsernameToken><se:Username>"+c+'</se:Username><se:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#PasswordText">'+d+"</se:Password></se:UsernameToken></t:RequestedSecurityToken></t:RequestSecurityTokenResponse></t:IssuedTokens>",i='<Auth Profile="http://schemas.xmlsoap.org/ws/2004/08/eventing/DeliveryModes/secprofile/http/digest"/>'),l=null!=l&&null!=l?"<a:ReferenceParameters>"+l+"</a:ReferenceParameters>":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(n)+m+'</Header><Body><e:Subscribe><e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/'+s+'"><e:NotifyTo><a:Address>'+r+"</a:Address></e:NotifyTo>"+i+"</e:Delivery><e:Expires>PT0.000000S</e:Expires></e:Subscribe>";p.PerformAjax(u+"</Body></Envelope>",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo>"+w(o)+"</Header><Body><e:Unsubscribe/>";p.PerformAjax(t+"</Body></Envelope>",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout>"+w(t)+"</Header><Body>"+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="<r:"+r+' xmlns:r="'+e+'">';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+="<r:"+o+"><a:Address>"+s[o].Address+"</a:Address><a:ReferenceParameters><w:ResourceURI>"+s[o].ReferenceParameters.ResourceURI+"</w:ResourceURI><w:SelectorSet>";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n<t.length;n++)a+="<w:Selector"+l(t[n])+">"+t[n].Value+"</w:Selector>";else a+="<w:Selector"+l(t)+">"+t.Value+"</w:Selector>";a+="</w:SelectorSet></a:ReferenceParameters></r:"+o+">"}else if(Array.isArray(s[o]))for(n=0;n<s[o].length;n++)a+="<r:"+o+">"+s[o][n].toString()+"</r:"+o+">";else a+="<r:"+o+">"+s[o].toString()+"</r:"+o+">";return a+="</r:"+r+">"}(e,s);p.PerformAjax(n+"</Body></Envelope>",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(t)+"</Header><Body><g:"+n+' xmlns:g="'+e+'">';for(var c in s)l+="<g:"+c+">"+s[c]+"</g:"+c+">";p.PerformAjax(l+"</g:"+n+"></Body></Envelope>",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60.000S</w:OperationTimeout></Header><Body><r:"+t+' xmlns:r="'+e+'">'+s+"</r:"+t+"></Body></Envelope>",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(s)+"</Header><Body /></Envelope>";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body /></Envelope>",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var c in r)if(null!=r[c])if(Array.isArray(r[c]))for(var d in r[c])l+="<r:"+c+">"+r[c][d]+"</r:"+c+">";else l+="<r:"+c+">"+r[c]+"</r:"+c+">";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+"</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++"</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout>"+w(n)+"</Header><Body><r:"+s+'_INPUT xmlns:r="'+e+'">'+r+"</r:"+s+"_INPUT></Body></Envelope>",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Enumerate xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration" /></Body></Envelope>',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull</a:Action><a:To>"+p.Address+"</a:To><w:ResourceURI>"+e+"</w:ResourceURI><a:MessageID>"+p.NextMessageId+++'</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><w:OperationTimeout>PT60S</w:OperationTimeout></Header><Body><Pull xmlns="http://schemas.xmlsoap.org/ws/2004/09/enumeration"><EnumerationContext>'+s+"</EnumerationContext><MaxElements>999</MaxElements><MaxCharacters>99999</MaxCharacters></Pull></Body></Envelope>",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o<a.childNodes.length;o++){var t=a.childNodes[o];r.Header[t.localName]=t.textContent}var n=s.getElementsByTagName("Body")[0];return(n=n||s.getElementsByTagName("a:Body")[0])?(0<n.childNodes.length&&((e=n.childNodes[0].localName).indexOf("_OUTPUT")==e.length-7&&(e=e.substring(0,e.length-7)),r.Header.Method=e,r.Body=function e(s){var r,a={};for(var o=0;o<s.childNodes.length;o++){var t=s.childNodes[o];"true"==(r=0==t.childElementCount?t.textContent:e(t))&&(r=!0),"false"==r&&(r=!1);var n=r;if(0<t.attributes.length){n={Value:r};for(var l=0;l<t.attributes.length;l++)n["@"+t.attributes[l].name]=t.attributes[l].value}a[t.localName]instanceof Array?a[t.localName].push(n):null==a[t.localName]?a[t.localName]=n:a[t.localName]=[a[t.localName],n]}return a}(n.childNodes[0])),r):null}catch(e){return console.log("Unable to parse XML: "+s),null}},p}
\ No newline at end of file
translate/translate.json
+128 -125
@@ -439,7 +439,7 @@
439 "ru": ", ",
440 "zh-chs": ",",
441 "xloc": [
442 - "default-mobile.handlebars->9->446",
442 + "default-mobile.handlebars->9->449",
443 "default.handlebars->27->1439"
444 ]
445 },
@@ -733,7 +733,7 @@
733 "fi": "1 tavu",
734 "xloc": [
735 "default-mobile.handlebars->9->118",
736 - "default-mobile.handlebars->9->450",
736 + "default-mobile.handlebars->9->453",
737 "default.handlebars->27->1499"
738 ]
739 },
@@ -2369,7 +2369,7 @@
2369 "xloc": [
2370 "default-mobile.handlebars->9->226",
2371 "default-mobile.handlebars->9->228",
2372 - "default-mobile.handlebars->9->355",
2372 + "default-mobile.handlebars->9->358",
2373 "default.handlebars->27->553",
2374 "default.handlebars->27->555",
2375 "default.handlebars->27->930"
@@ -2688,7 +2688,7 @@
2688 "zh-chs": "添加用戶",
2689 "fi": "Lisää Käyttäjä",
2690 "xloc": [
2691 - "default-mobile.handlebars->9->395",
2691 + "default-mobile.handlebars->9->398",
2692 "default.handlebars->27->648"
2693 ]
2694 },
@@ -2757,7 +2757,7 @@
2757 "zh-chs": "将用户添加到设备组",
2758 "fi": "Lisää käyttäjä laiteryhmään",
2759 "xloc": [
2760 - "default-mobile.handlebars->9->424"
2760 + "default-mobile.handlebars->9->427"
2761 ]
2762 },
2763 {
@@ -2996,7 +2996,7 @@
2996 "ru": "Режим управления администратора (ACM)",
2997 "zh-chs": "管理員控制模式(ACM)",
2998 "xloc": [
2999 - "default-mobile.handlebars->9->357",
2999 + "default-mobile.handlebars->9->360",
3000 "default.handlebars->27->932"
3001 ]
3002 },
@@ -3014,7 +3014,7 @@
3014 "ru": "Учетные данные администратора",
3015 "zh-chs": "管理員憑證",
3016 "xloc": [
3017 - "default-mobile.handlebars->9->363",
3017 + "default-mobile.handlebars->9->366",
3018 "default.handlebars->27->938"
3019 ]
3020 },
@@ -3200,7 +3200,7 @@
3200 "zh-chs": "代理控制台",
3201 "fi": "Agentin konsoli",
3202 "xloc": [
3203 - "default-mobile.handlebars->9->430",
3203 + "default-mobile.handlebars->9->433",
3204 "default.handlebars->27->1422"
3205 ]
3206 },
@@ -4178,7 +4178,7 @@
4178 "zh-chs": "建築",
4179 "fi": "Arkkitehtuuri",
4180 "xloc": [
4181 - "default-mobile.handlebars->9->327",
4181 + "default-mobile.handlebars->9->330",
4182 "default.handlebars->27->892"
4183 ]
4184 },
@@ -4215,7 +4215,7 @@
4215 "zh-chs": "您確定要刪除組{0}嗎?刪除設備組還將刪除該組中有關設備的所有信息。",
4216 "fi": "Haluatko varmasti poistaa ryhmän {0}? Laiteryhmän poistaminen poistaa myös kaikki tämän ryhmän laitteiden tiedot.",
4217 "xloc": [
4218 - "default-mobile.handlebars->9->401",
4218 + "default-mobile.handlebars->9->404",
4219 "default.handlebars->27->1348"
4220 ]
4221 },
@@ -4555,7 +4555,7 @@
4555 "ru": "BIOS",
4556 "zh-chs": "的BIOS",
4557 "xloc": [
4558 - "default-mobile.handlebars->9->369",
4558 + "default-mobile.handlebars->9->372",
4559 "default.handlebars->27->944"
4560 ]
4561 },
@@ -5054,7 +5054,7 @@
5054 "ru": "CPU",
5055 "zh-chs": "CPU",
5056 "xloc": [
5057 - "default-mobile.handlebars->9->375",
5057 + "default-mobile.handlebars->9->378",
5058 "default.handlebars->27->950"
5059 ]
5060 },
@@ -5234,8 +5234,8 @@
5234 "zh-chs": "容量",
5235 "fi": "Kapasiteetti",
5236 "xloc": [
5237 - "default-mobile.handlebars->9->383",
5238 - "default-mobile.handlebars->9->385",
5237 + "default-mobile.handlebars->9->386",
5238 + "default-mobile.handlebars->9->388",
5239 "default.handlebars->27->958",
5240 "default.handlebars->27->960"
5241 ]
@@ -5255,7 +5255,7 @@
5255 "zh-chs": "容量/速度",
5256 "fi": "Kapasiteetti / Nopeus",
5257 "xloc": [
5258 - "default-mobile.handlebars->9->378",
5258 + "default-mobile.handlebars->9->381",
5259 "default.handlebars->27->953"
5260 ]
5261 },
@@ -5585,8 +5585,8 @@
5585 "ru": "Чаты и уведомления",
5586 "zh-chs": "聊天並通知",
5587 "xloc": [
5588 - "default-mobile.handlebars->9->422",
5589 - "default-mobile.handlebars->9->440",
5588 + "default-mobile.handlebars->9->425",
5589 + "default-mobile.handlebars->9->443",
5590 "default.handlebars->27->1398",
5591 "default.handlebars->27->1433"
5592 ]
@@ -6125,7 +6125,7 @@
6125 "ru": "Режим управления клиентом (CCM)",
6126 "zh-chs": "客戶端控制模式(CCM)",
6127 "xloc": [
6128 - "default-mobile.handlebars->9->356",
6128 + "default-mobile.handlebars->9->359",
6129 "default.handlebars->27->931"
6130 ]
6131 },
@@ -6287,7 +6287,7 @@
6287 "fi": "Varmista",
6288 "xloc": [
6289 "default-mobile.handlebars->9->276",
6290 - "default-mobile.handlebars->9->402",
6290 + "default-mobile.handlebars->9->405",
6291 "default.handlebars->27->1349",
6292 "default.handlebars->27->1579",
6293 "default.handlebars->27->1657",
@@ -6662,7 +6662,7 @@
6662 "ru": "Подтвердить удаление пользователя {0}?",
6663 "zh-chs": "確認刪除用戶{0}?",
6664 "xloc": [
6665 - "default-mobile.handlebars->9->449"
6665 + "default-mobile.handlebars->9->452"
6666 ]
6667 },
6668 {
@@ -6832,7 +6832,7 @@
6832 "ru": "Подключено сейчас",
6833 "zh-chs": "現在已連接",
6834 "xloc": [
6835 - "default-mobile.handlebars->9->331",
6835 + "default-mobile.handlebars->9->334",
6836 "default.handlebars->27->896"
6837 ]
6838 },
@@ -6868,7 +6868,7 @@
6868 "zh-chs": "正在連線...",
6869 "xloc": [
6870 "default-mobile.handlebars->9->2",
6871 - "default-mobile.handlebars->9->324",
6871 + "default-mobile.handlebars->9->327",
6872 "default-mobile.handlebars->9->37",
6873 "default.handlebars->27->233",
6874 "default.handlebars->27->236",
@@ -7964,8 +7964,8 @@
7964 "ru": "Удалить группу",
7965 "zh-chs": "刪除群組",
7966 "xloc": [
7967 - "default-mobile.handlebars->9->400",
7967 "default-mobile.handlebars->9->403",
7968 + "default-mobile.handlebars->9->406",
7969 "default.handlebars->27->1320",
7970 "default.handlebars->27->1350"
7971 ]
@@ -8309,9 +8309,9 @@
8309 "default-mobile.handlebars->9->221",
8310 "default-mobile.handlebars->9->222",
8311 "default-mobile.handlebars->9->280",
8312 - "default-mobile.handlebars->9->337",
8313 - "default-mobile.handlebars->9->392",
8314 - "default-mobile.handlebars->9->405",
8312 + "default-mobile.handlebars->9->340",
8313 + "default-mobile.handlebars->9->395",
8314 + "default-mobile.handlebars->9->408",
8315 "default.handlebars->27->1241",
8316 "default.handlebars->27->1269",
8317 "default.handlebars->27->1352",
@@ -8620,7 +8620,7 @@
8620 "ru": "Пользователь группы устройств",
8621 "zh-chs": "設備組用戶",
8622 "xloc": [
8623 - "default-mobile.handlebars->9->447",
8623 + "default-mobile.handlebars->9->450",
8624 "default.handlebars->27->1440"
8625 ]
8626 },
@@ -10106,9 +10106,9 @@
10106 "zh-chs": "編輯設備組",
10107 "fi": "Muokkaa laiteryhmää",
10108 "xloc": [
10109 - "default-mobile.handlebars->9->406",
10110 - "default-mobile.handlebars->9->408",
10111 - "default-mobile.handlebars->9->426",
10109 + "default-mobile.handlebars->9->409",
10110 + "default-mobile.handlebars->9->411",
10111 + "default-mobile.handlebars->9->429",
10112 "default.handlebars->27->1353",
10113 "default.handlebars->27->1383",
10114 "default.handlebars->27->1406",
@@ -10181,7 +10181,7 @@
10181 "ru": "Редактировать примечания устройства",
10182 "zh-chs": "編輯設備說明",
10183 "xloc": [
10184 - "default-mobile.handlebars->9->420",
10184 + "default-mobile.handlebars->9->423",
10185 "default.handlebars->27->1396"
10186 ]
10187 },
@@ -10275,7 +10275,7 @@
10275 "zh-chs": "編輯筆記",
10276 "fi": "Muokkaa muistiinpanoja",
10277 "xloc": [
10278 - "default-mobile.handlebars->9->433",
10278 + "default-mobile.handlebars->9->436",
10279 "default.handlebars->27->1425"
10280 ]
10281 },
@@ -12055,9 +12055,9 @@
12055 "fi": "Täysi Järjestelmänvalvoja",
12056 "xloc": [
12057 "default-mobile.handlebars->9->105",
12058 - "default-mobile.handlebars->9->398",
12059 - "default-mobile.handlebars->9->407",
12060 - "default-mobile.handlebars->9->425",
12058 + "default-mobile.handlebars->9->401",
12059 + "default-mobile.handlebars->9->410",
12060 + "default-mobile.handlebars->9->428",
12061 "default.handlebars->27->1250",
12062 "default.handlebars->27->1382",
12063 "default.handlebars->27->1633"
@@ -12176,7 +12176,7 @@
12176 "nl": "GPU",
12177 "zh-chs": "显卡",
12178 "xloc": [
12179 - "default-mobile.handlebars->9->376",
12179 + "default-mobile.handlebars->9->379",
12180 "default.handlebars->27->951"
12181 ]
12182 },
@@ -13195,8 +13195,8 @@
13195 "ru": "IP: {0}",
13196 "zh-chs": "IP:{0}",
13197 "xloc": [
13198 - "default-mobile.handlebars->9->345",
13199 - "default-mobile.handlebars->9->349",
13198 + "default-mobile.handlebars->9->348",
13199 + "default-mobile.handlebars->9->352",
13200 "default.handlebars->27->910",
13201 "default.handlebars->27->920",
13202 "default.handlebars->27->924"
@@ -13216,8 +13216,8 @@
13216 "ru": "IP: {0}, маска: {1}, шлюз: {2}",
13217 "zh-chs": "IP:{0},掩碼:{1},網關:{2}",
13218 "xloc": [
13219 - "default-mobile.handlebars->9->343",
13220 - "default-mobile.handlebars->9->347",
13219 + "default-mobile.handlebars->9->346",
13220 + "default-mobile.handlebars->9->350",
13221 "default.handlebars->27->908",
13222 "default.handlebars->27->918",
13223 "default.handlebars->27->922"
@@ -13237,8 +13237,8 @@
13237 "ru": "Уровень IPv4",
13238 "zh-chs": "IPv4層",
13239 "xloc": [
13240 - "default-mobile.handlebars->9->342",
13241 - "default-mobile.handlebars->9->344",
13240 + "default-mobile.handlebars->9->345",
13241 + "default-mobile.handlebars->9->347",
13242 "default.handlebars->27->907",
13243 "default.handlebars->27->909",
13244 "default.handlebars->27->917",
@@ -13306,8 +13306,8 @@
13306 "nl": "IPv6 Layer",
13307 "es": "Capa IPv6",
13308 "xloc": [
13309 - "default-mobile.handlebars->9->346",
13310 - "default-mobile.handlebars->9->348",
13309 + "default-mobile.handlebars->9->349",
13310 + "default-mobile.handlebars->9->351",
13311 "default.handlebars->27->921",
13312 "default.handlebars->27->923"
13313 ]
@@ -13385,7 +13385,7 @@
13385 "ru": "Идентификатор",
13386 "zh-chs": "識別碼",
13387 "xloc": [
13388 - "default-mobile.handlebars->9->374",
13388 + "default-mobile.handlebars->9->377",
13389 "default.handlebars->27->949"
13390 ]
13391 },
@@ -14171,7 +14171,7 @@
14171 "ru": "Только Intel&reg; AMT, без агента",
14172 "zh-chs": "僅限英特爾&reg;AMT,無代理",
14173 "xloc": [
14174 - "default-mobile.handlebars->9->389",
14174 + "default-mobile.handlebars->9->392",
14175 "default.handlebars->27->1240",
14176 "default.handlebars->27->1266"
14177 ]
@@ -14207,7 +14207,7 @@
14207 "ru": "Intel&reg; Active Management Technology (Intel&reg; AMT)",
14208 "zh-chs": "英特爾&reg;主動管理技術(英特爾&reg;AMT)",
14209 "xloc": [
14210 - "default-mobile.handlebars->9->366",
14210 + "default-mobile.handlebars->9->369",
14211 "default.handlebars->27->941"
14212 ]
14213 },
@@ -15069,7 +15069,7 @@
15069 "ru": "Известный",
15070 "zh-chs": "已知的",
15071 "xloc": [
15072 - "default-mobile.handlebars->9->365",
15072 + "default-mobile.handlebars->9->368",
15073 "default.handlebars->27->940"
15074 ]
15075 },
@@ -15417,9 +15417,9 @@
15417 "ru": "Последний адрес агента",
15418 "zh-chs": "最後代理商地址",
15419 "xloc": [
15420 - "default-mobile.handlebars->9->333",
15421 - "default-mobile.handlebars->9->334",
15422 - "default-mobile.handlebars->9->335",
15420 + "default-mobile.handlebars->9->336",
15421 + "default-mobile.handlebars->9->337",
15422 + "default-mobile.handlebars->9->338",
15423 "default.handlebars->27->69",
15424 "default.handlebars->27->71",
15425 "default.handlebars->27->73",
@@ -15442,8 +15442,8 @@
15442 "ru": "Последнее подключение агента",
15443 "zh-chs": "上次代理連接",
15444 "xloc": [
15445 - "default-mobile.handlebars->9->330",
15446 - "default-mobile.handlebars->9->332",
15445 + "default-mobile.handlebars->9->333",
15446 + "default-mobile.handlebars->9->335",
15447 "default.handlebars->27->68",
15448 "default.handlebars->27->895",
15449 "default.handlebars->27->897"
@@ -15749,7 +15749,7 @@
15749 "ru": "Ограниченный ввод",
15750 "zh-chs": "有限輸入",
15751 "xloc": [
15752 - "default-mobile.handlebars->9->438",
15752 + "default-mobile.handlebars->9->441",
15753 "default.handlebars->27->1431",
15754 "default.handlebars->27->661",
15755 "default.handlebars->27->680"
@@ -15769,7 +15769,7 @@
15769 "ru": "Ограничить элементы ввода",
15770 "zh-chs": "僅限於輸入",
15771 "xloc": [
15772 - "default-mobile.handlebars->9->413",
15772 + "default-mobile.handlebars->9->416",
15773 "default.handlebars->27->1388"
15774 ]
15775 },
@@ -16542,8 +16542,8 @@
16542 "ru": "MAC-уровень",
16543 "zh-chs": "MAC層",
16544 "xloc": [
16545 - "default-mobile.handlebars->9->338",
16546 - "default-mobile.handlebars->9->340",
16545 + "default-mobile.handlebars->9->341",
16546 + "default-mobile.handlebars->9->343",
16547 "default.handlebars->27->903",
16548 "default.handlebars->27->905",
16549 "default.handlebars->27->913",
@@ -16582,7 +16582,7 @@
16582 "ru": "MAC: {0}",
16583 "zh-chs": "MAC:{0}",
16584 "xloc": [
16585 - "default-mobile.handlebars->9->341",
16585 + "default-mobile.handlebars->9->344",
16586 "default.handlebars->27->906",
16587 "default.handlebars->27->916"
16588 ]
@@ -16601,7 +16601,7 @@
16601 "ru": "MAC: {0}, шлюз: {1}",
16602 "zh-chs": "MAC:{0},網關:{1}",
16603 "xloc": [
16604 - "default-mobile.handlebars->9->339",
16604 + "default-mobile.handlebars->9->342",
16605 "default.handlebars->27->904",
16606 "default.handlebars->27->914"
16607 ]
@@ -16925,8 +16925,8 @@
16925 "zh-chs": "管理設備組計算機",
16926 "fi": "Hallitse laiteryhmän tietokoneita",
16927 "xloc": [
16928 - "default-mobile.handlebars->9->410",
16929 - "default-mobile.handlebars->9->428",
16928 + "default-mobile.handlebars->9->413",
16929 + "default-mobile.handlebars->9->431",
16930 "default.handlebars->27->1385",
16931 "default.handlebars->27->1420"
16932 ]
@@ -16946,8 +16946,8 @@
16946 "zh-chs": "管理設備組用戶",
16947 "fi": "Hallitse laiteryhmän käyttäjiä",
16948 "xloc": [
16949 - "default-mobile.handlebars->9->409",
16950 - "default-mobile.handlebars->9->427",
16949 + "default-mobile.handlebars->9->412",
16950 + "default-mobile.handlebars->9->430",
16951 "default.handlebars->27->1384",
16952 "default.handlebars->27->1419"
16953 ]
@@ -17157,7 +17157,7 @@
17157 "ru": "Управляется с помощью программного агента",
17158 "zh-chs": "使用軟件代理進行管理",
17159 "xloc": [
17160 - "default-mobile.handlebars->9->390",
17160 + "default-mobile.handlebars->9->393",
17161 "default.handlebars->27->1267"
17162 ]
17163 },
@@ -17350,7 +17350,7 @@
17350 "ru": "ОЗУ",
17351 "zh-chs": "記憶",
17352 "xloc": [
17353 - "default-mobile.handlebars->9->381",
17353 + "default-mobile.handlebars->9->384",
17354 "default.handlebars->27->1901",
17355 "default.handlebars->27->956",
17356 "default.handlebars->container->column_l->p40->3->1->p40type->3"
@@ -17371,8 +17371,8 @@
17371 "zh-chs": "網格代理",
17372 "xloc": [
17373 "default-mobile.handlebars->9->250",
17374 - "default-mobile.handlebars->9->329",
17375 - "default-mobile.handlebars->9->336",
17374 + "default-mobile.handlebars->9->332",
17375 + "default-mobile.handlebars->9->339",
17376 "default.handlebars->27->378",
17377 "default.handlebars->27->382",
17378 "default.handlebars->27->391",
@@ -17399,7 +17399,7 @@
17399 "ru": "Консоль Mesh Agent",
17400 "zh-chs": "網格代理控制台",
17401 "xloc": [
17402 - "default-mobile.handlebars->9->417",
17402 + "default-mobile.handlebars->9->420",
17403 "default.handlebars->27->1393"
17404 ]
17405 },
@@ -17973,7 +17973,7 @@
17973 "nl": "Model",
17974 "zh-chs": "模型",
17975 "xloc": [
17976 - "default-mobile.handlebars->9->382",
17976 + "default-mobile.handlebars->9->385",
17977 "default.handlebars->27->957"
17978 ]
17979 },
@@ -18043,7 +18043,7 @@
18043 "ru": "Материнская плата",
18044 "zh-chs": "母板",
18045 "xloc": [
18046 - "default-mobile.handlebars->9->377",
18046 + "default-mobile.handlebars->9->380",
18047 "default.handlebars->27->952"
18048 ]
18049 },
@@ -18369,10 +18369,10 @@
18369 "fi": "Nimi",
18370 "xloc": [
18371 "default-mobile.handlebars->9->215",
18372 - "default-mobile.handlebars->9->325",
18373 - "default-mobile.handlebars->9->371",
18374 - "default-mobile.handlebars->9->391",
18375 - "default-mobile.handlebars->9->404",
18372 + "default-mobile.handlebars->9->328",
18373 + "default-mobile.handlebars->9->374",
18374 + "default-mobile.handlebars->9->394",
18375 + "default-mobile.handlebars->9->407",
18376 "default-mobile.handlebars->9->97",
18377 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea3->deskarea3x->DeskTools->5->1->1",
18378 "default.handlebars->27->1237",
@@ -18527,7 +18527,7 @@
18527 "ru": "сетей",
18528 "zh-chs": "聯網",
18529 "xloc": [
18530 - "default-mobile.handlebars->9->350",
18530 + "default-mobile.handlebars->9->353",
18531 "default.handlebars->27->911",
18532 "default.handlebars->27->925"
18533 ]
@@ -18807,7 +18807,7 @@
18807 "ru": "Нет доступа к файлам",
18808 "zh-chs": "沒有文件訪問",
18809 "xloc": [
18810 - "default-mobile.handlebars->9->415",
18810 + "default-mobile.handlebars->9->418",
18811 "default.handlebars->27->1391"
18812 ]
18813 },
@@ -18826,7 +18826,7 @@
18826 "zh-chs": "沒有文件",
18827 "fi": "Ei tiedostoja",
18828 "xloc": [
18829 - "default-mobile.handlebars->9->436",
18829 + "default-mobile.handlebars->9->439",
18830 "default.handlebars->27->1429",
18831 "default.handlebars->27->659",
18832 "default.handlebars->27->678"
@@ -18863,8 +18863,8 @@
18863 "ru": "Нет Intel&reg; AMT",
18864 "zh-chs": "沒有英特爾&reg;AMT",
18865 "xloc": [
18866 - "default-mobile.handlebars->9->416",
18867 - "default-mobile.handlebars->9->437",
18866 + "default-mobile.handlebars->9->419",
18867 + "default-mobile.handlebars->9->440",
18868 "default.handlebars->27->1392",
18869 "default.handlebars->27->1430"
18870 ]
@@ -18989,8 +18989,8 @@
18989 "zh-chs": "沒有權利",
18990 "xloc": [
18991 "default-mobile.handlebars->9->106",
18992 - "default-mobile.handlebars->9->399",
18993 - "default-mobile.handlebars->9->442",
18992 + "default-mobile.handlebars->9->402",
18993 + "default-mobile.handlebars->9->445",
18994 "default.handlebars->27->1251",
18995 "default.handlebars->27->1435",
18996 "default.handlebars->27->671",
@@ -19030,7 +19030,7 @@
19030 "ru": "Нет терминала",
19031 "zh-chs": "沒有終端",
19032 "xloc": [
19033 - "default-mobile.handlebars->9->435",
19033 + "default-mobile.handlebars->9->438",
19034 "default.handlebars->27->1428",
19035 "default.handlebars->27->658",
19036 "default.handlebars->27->677"
@@ -19050,7 +19050,7 @@
19050 "ru": "Нет доступа к терминалу",
19051 "zh-chs": "沒有終端訪問",
19052 "xloc": [
19053 - "default-mobile.handlebars->9->414",
19053 + "default-mobile.handlebars->9->417",
19054 "default.handlebars->27->1390"
19055 ]
19056 },
@@ -19291,7 +19291,7 @@
19291 "ru": "Информации об этом устройстве нет",
19292 "zh-chs": "沒有此設備的信息。",
19293 "xloc": [
19294 - "default-mobile.handlebars->9->387",
19294 + "default-mobile.handlebars->9->390",
19295 "default.handlebars->27->962"
19296 ]
19297 },
@@ -19495,7 +19495,7 @@
19495 "default-mobile.handlebars->9->220",
19496 "default-mobile.handlebars->9->245",
19497 "default-mobile.handlebars->9->297",
19498 - "default-mobile.handlebars->9->393",
19498 + "default-mobile.handlebars->9->396",
19499 "default.handlebars->27->1263",
19500 "default.handlebars->27->1270",
19501 "default.handlebars->27->1274",
@@ -19607,7 +19607,7 @@
19607 "zh-chs": "未激活(輸入)",
19608 "xloc": [
19609 "default-mobile.handlebars->9->225",
19610 - "default-mobile.handlebars->9->354",
19610 + "default-mobile.handlebars->9->357",
19611 "default.handlebars->27->552",
19612 "default.handlebars->27->929"
19613 ]
@@ -19627,7 +19627,7 @@
19627 "zh-chs": "未激活(預)",
19628 "xloc": [
19629 "default-mobile.handlebars->9->224",
19630 - "default-mobile.handlebars->9->353",
19630 + "default-mobile.handlebars->9->356",
19631 "default.handlebars->27->551",
19632 "default.handlebars->27->928"
19633 ]
@@ -19664,7 +19664,7 @@
19664 "ru": "Неизвестный",
19665 "zh-chs": "未知",
19666 "xloc": [
19667 - "default-mobile.handlebars->9->364",
19667 + "default-mobile.handlebars->9->367",
19668 "default.handlebars->27->939"
19669 ]
19670 },
@@ -20198,7 +20198,7 @@
20198 "ru": "Операционная система",
20199 "zh-chs": "操作系統",
20200 "xloc": [
20201 - "default-mobile.handlebars->9->328",
20201 + "default-mobile.handlebars->9->331",
20202 "default.handlebars->27->332",
20203 "default.handlebars->27->365",
20204 "default.handlebars->27->575",
@@ -20381,7 +20381,7 @@
20381 "ru": "Part Number",
20382 "zh-chs": "零件號",
20383 "xloc": [
20384 - "default-mobile.handlebars->9->380",
20384 + "default-mobile.handlebars->9->383",
20385 "default.handlebars->27->955"
20386 ]
20387 },
@@ -20445,7 +20445,7 @@
20445 "zh-chs": "部分權利",
20446 "xloc": [
20447 "default-mobile.handlebars->9->104",
20448 - "default-mobile.handlebars->9->397",
20448 + "default-mobile.handlebars->9->400",
20449 "default.handlebars->27->1249"
20450 ]
20451 },
@@ -20918,7 +20918,7 @@
20918 "zh-chs": "權限",
20919 "fi": "Käyttöoikeudet",
20920 "xloc": [
20921 - "default-mobile.handlebars->9->445",
20921 + "default-mobile.handlebars->9->448",
20922 "default.handlebars->27->1438",
20923 "default.handlebars->27->1545"
20924 ]
@@ -21618,7 +21618,7 @@
21618 "ru": "Предоставление государства",
21619 "zh-chs": "供應國",
21620 "xloc": [
21621 - "default-mobile.handlebars->9->358",
21621 + "default-mobile.handlebars->9->361",
21622 "default.handlebars->27->933"
21623 ]
21624 },
@@ -22302,8 +22302,8 @@
22302 "zh-chs": "遙控",
22303 "fi": "Etähallinta",
22304 "xloc": [
22305 - "default-mobile.handlebars->9->411",
22306 - "default-mobile.handlebars->9->429",
22305 + "default-mobile.handlebars->9->414",
22306 + "default-mobile.handlebars->9->432",
22307 "default.handlebars->27->1386",
22308 "default.handlebars->27->1421"
22309 ]
@@ -22378,7 +22378,7 @@
22378 "ru": "Удаленный пользователь Mesh",
22379 "zh-chs": "遠程網狀用戶",
22380 "xloc": [
22381 - "default-mobile.handlebars->9->448"
22381 + "default-mobile.handlebars->9->451"
22382 ]
22383 },
22384 {
@@ -22410,8 +22410,8 @@
22410 "ru": "Только просмотр экрана без ввода",
22411 "zh-chs": "僅遠程查看",
22412 "xloc": [
22413 - "default-mobile.handlebars->9->412",
22414 - "default-mobile.handlebars->9->434",
22413 + "default-mobile.handlebars->9->415",
22414 + "default-mobile.handlebars->9->437",
22415 "default.handlebars->27->1387",
22416 "default.handlebars->27->1426"
22417 ]
@@ -23796,7 +23796,7 @@
23796 "ru": "Защищено с помощью TLS",
23797 "zh-chs": "使用TLS保護",
23798 "xloc": [
23799 - "default-mobile.handlebars->9->361",
23799 + "default-mobile.handlebars->9->364",
23800 "default.handlebars->27->936"
23801 ]
23802 },
@@ -23816,7 +23816,7 @@
23816 "fi": "Turvallisuus",
23817 "xloc": [
23818 "default-mobile.handlebars->9->270",
23819 - "default-mobile.handlebars->9->360",
23819 + "default-mobile.handlebars->9->363",
23820 "default.handlebars->27->1766",
23821 "default.handlebars->27->286",
23822 "default.handlebars->27->732",
@@ -24042,7 +24042,7 @@
24042 "ru": "Только собственные события",
24043 "zh-chs": "僅自我事件",
24044 "xloc": [
24045 - "default-mobile.handlebars->9->439",
24045 + "default-mobile.handlebars->9->442",
24046 "default.handlebars->27->1432"
24047 ]
24048 },
@@ -24328,7 +24328,7 @@
24328 "ru": "Серийный номер",
24329 "zh-chs": "序列號",
24330 "xloc": [
24331 - "default-mobile.handlebars->9->372",
24331 + "default-mobile.handlebars->9->375",
24332 "default.handlebars->27->947"
24333 ]
24334 },
@@ -24397,8 +24397,8 @@
24397 "ru": "Серверные файлы",
24398 "zh-chs": "服務器文件",
24399 "xloc": [
24400 - "default-mobile.handlebars->9->418",
24401 - "default-mobile.handlebars->9->431",
24400 + "default-mobile.handlebars->9->421",
24401 + "default-mobile.handlebars->9->434",
24402 "default.handlebars->27->1394",
24403 "default.handlebars->27->1423",
24404 "default.handlebars->27->1631",
@@ -25048,7 +25048,7 @@
25048 "ru": "Показывать только собственные события",
25049 "zh-chs": "只顯示自己的事件",
25050 "xloc": [
25051 - "default-mobile.handlebars->9->421",
25051 + "default-mobile.handlebars->9->424",
25052 "default.handlebars->27->1397"
25053 ]
25054 },
@@ -26274,7 +26274,7 @@
26274 "nl": "Opslag",
26275 "zh-chs": "存储",
26276 "xloc": [
26277 - "default-mobile.handlebars->9->386",
26277 + "default-mobile.handlebars->9->389",
26278 "default.handlebars->27->961"
26279 ]
26280 },
@@ -26637,7 +26637,7 @@
26637 "ru": "TLS не настроен",
26638 "zh-chs": "未設置TLS",
26639 "xloc": [
26640 - "default-mobile.handlebars->9->362",
26640 + "default-mobile.handlebars->9->365",
26641 "default.handlebars->27->937"
26642 ]
26643 },
@@ -27938,7 +27938,7 @@
27938 "ru": "Удаленный ввод",
27939 "zh-chs": "類型",
27940 "xloc": [
27941 - "default-mobile.handlebars->9->394",
27941 + "default-mobile.handlebars->9->397",
27942 "default-mobile.handlebars->9->98",
27943 "default.handlebars->27->1238",
27944 "default.handlebars->27->1271",
@@ -28201,7 +28201,7 @@
28201 "ru": "Удаление",
28202 "zh-chs": "卸載",
28203 "xloc": [
28204 - "default-mobile.handlebars->9->441",
28204 + "default-mobile.handlebars->9->444",
28205 "default.handlebars->27->1434",
28206 "default.handlebars->27->670",
28207 "default.handlebars->27->689"
@@ -28221,7 +28221,7 @@
28221 "ru": "Удаление агента",
28222 "zh-chs": "卸載代理",
28223 "xloc": [
28224 - "default-mobile.handlebars->9->423",
28224 + "default-mobile.handlebars->9->426",
28225 "default.handlebars->27->1399",
28226 "default.handlebars->27->444",
28227 "default.handlebars->27->720"
@@ -28261,8 +28261,8 @@
28261 "default-mobile.handlebars->9->204",
28262 "default-mobile.handlebars->9->34",
28263 "default-mobile.handlebars->9->35",
28264 - "default-mobile.handlebars->9->352",
28265 - "default-mobile.handlebars->9->359",
28264 + "default-mobile.handlebars->9->355",
28265 + "default-mobile.handlebars->9->362",
28266 "default-mobile.handlebars->9->6",
28267 "default.handlebars->27->107",
28268 "default.handlebars->27->108",
@@ -28296,7 +28296,7 @@
28296 "ru": "Неизвестно #{0}",
28297 "zh-chs": "未知#{0}",
28298 "xloc": [
28299 - "default-mobile.handlebars->9->388",
28299 + "default-mobile.handlebars->9->391",
28300 "default.handlebars->27->1265"
28301 ]
28302 },
@@ -28534,6 +28534,7 @@
28534 "default-mobile.handlebars->9->126",
28535 "default-mobile.handlebars->9->305",
28536 "default-mobile.handlebars->9->323",
28537 + "default-mobile.handlebars->9->326",
28538 "default.handlebars->27->1507",
28539 "default.handlebars->27->1515",
28540 "default.handlebars->27->860",
@@ -28624,6 +28625,7 @@
28625 "ru": "Загрузка перезапишет 1 файл. Продолжить?",
28626 "zh-chs": "上傳將覆蓋1個文件。繼續?",
28627 "xloc": [
28628 + "default-mobile.handlebars->9->324",
28629 "default.handlebars->27->1516",
28630 "default.handlebars->27->884"
28631 ]
@@ -28642,6 +28644,7 @@
28644 "ru": "Загрузка перезапишет {0} файлов. Продолжить?",
28645 "zh-chs": "上傳將覆蓋{0}個文件。繼續?",
28646 "xloc": [
28647 + "default-mobile.handlebars->9->325",
28648 "default.handlebars->27->1517",
28649 "default.handlebars->27->885"
28650 ]
@@ -28838,7 +28841,7 @@
28841 "ru": "Полномочия пользователя",
28842 "zh-chs": "用戶授權",
28843 "xloc": [
28841 - "default-mobile.handlebars->9->396",
28844 + "default-mobile.handlebars->9->399",
28845 "default.handlebars->27->1317",
28846 "default.handlebars->27->650"
28847 ]
@@ -28925,7 +28928,7 @@
28928 "nl": "Gebruikers ID",
28929 "es": "ID de usuario",
28930 "xloc": [
28928 - "default-mobile.handlebars->9->444"
28931 + "default-mobile.handlebars->9->447"
28932 ]
28933 },
28934 {
@@ -28987,7 +28990,7 @@
28990 "ru": "Имя пользователя",
28991 "zh-chs": "用戶名",
28992 "xloc": [
28990 - "default-mobile.handlebars->9->443",
28993 + "default-mobile.handlebars->9->446",
28994 "default.handlebars->27->1436"
28995 ]
28996 },
@@ -29327,8 +29330,8 @@
29330 "ru": "Вендор",
29331 "zh-chs": "供應商",
29332 "xloc": [
29330 - "default-mobile.handlebars->9->367",
29333 "default-mobile.handlebars->9->370",
29334 + "default-mobile.handlebars->9->373",
29335 "default.handlebars->27->942",
29336 "default.handlebars->27->945"
29337 ]
@@ -29442,10 +29445,10 @@
29445 "zh-chs": "版",
29446 "fi": "Versio",
29447 "xloc": [
29445 - "default-mobile.handlebars->9->326",
29446 - "default-mobile.handlebars->9->351",
29447 - "default-mobile.handlebars->9->368",
29448 - "default-mobile.handlebars->9->373",
29448 + "default-mobile.handlebars->9->329",
29449 + "default-mobile.handlebars->9->354",
29450 + "default-mobile.handlebars->9->371",
29451 + "default-mobile.handlebars->9->376",
29452 "default.handlebars->27->891",
29453 "default.handlebars->27->926",
29454 "default.handlebars->27->943",
@@ -29688,8 +29691,8 @@
29691 "ru": "Разбудить устройства",
29692 "zh-chs": "喚醒設備",
29693 "xloc": [
29691 - "default-mobile.handlebars->9->419",
29692 - "default-mobile.handlebars->9->432",
29694 + "default-mobile.handlebars->9->422",
29695 + "default-mobile.handlebars->9->435",
29696 "default.handlebars->27->1395",
29697 "default.handlebars->27->1424"
29698 ]
@@ -32016,7 +32019,7 @@
32019 "ru": "{0} Mб",
32020 "zh-chs": "{0} Mb",
32021 "xloc": [
32019 - "default-mobile.handlebars->9->384",
32022 + "default-mobile.handlebars->9->387",
32023 "default.handlebars->27->1491",
32024 "default.handlebars->27->959"
32025 ]
@@ -32035,7 +32038,7 @@
32038 "ru": "{0} Мб, {1} Мгц",
32039 "zh-chs": "{0} Mb,{1} Mhz",
32040 "xloc": [
32038 - "default-mobile.handlebars->9->379",
32041 + "default-mobile.handlebars->9->382",
32042 "default.handlebars->27->954"
32043 ]
32044 },
views/default-mobile.handlebars
+88 -76
@@ -3304,27 +3304,31 @@
3304 var p13filetreelocation = [];
3305
3306 function p13gotFiles(data) {
3307 - setSessionActivity();
3308 - //console.log('p13gotFiles', data);
3309 - if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p13gotDownloadBinaryData(data); return; }
3307 + if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p13gotDownloadBinaryData(data); return; } // This is ok because 4 first bytes is a control value.
3308 //console.log('p13gotFiles', data);
3309 data = JSON.parse(decode_utf8(data));
3310 if (data.action == 'download') { p13gotDownloadCommand(data); return; }
3313 - data.path = data.path.replace(/\//g, '\\');
3314 - if ((p13filetree != null) && (data.path == p13filetree.path)) {
3315 - // This is an update to the same folder
3316 - var checkedNames = p13getCheckedNames();
3317 - p13filetree = data;
3318 - p13updateFiles(checkedNames);
3319 - } else {
3320 - // Make both paths use the same seperator not start with /
3321 - var x1 = data.path.replace(/\//g, '\\'), x2 = p13targetpath.replace(/\//g, '\\');
3322 - while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
3323 - while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
3324 - if ((x1 == x2) || ((data.path == '\\') && (p13targetpath == ''))) {
3325 - // This is a different folder
3311 +
3312 + // Process file upload commands
3313 + if ((data.action != null) && (data.action.startsWith('upload'))) { p13gotUploadData(data); return; }
3314 +
3315 + if (data.path != null) {
3316 + data.path = data.path.replace(/\//g, '\\');
3317 + if ((p13filetree != null) && (data.path == p13filetree.path)) {
3318 + // This is an update to the same folder
3319 + var checkedNames = p13getCheckedNames();
3320 p13filetree = data;
3327 - p13updateFiles();
3321 + p13updateFiles(checkedNames);
3322 + } else {
3323 + // Make both paths use the same seperator not start with /
3324 + var x1 = data.path.replace(/\//g, '\\'), x2 = p13targetpath.replace(/\//g, '\\');
3325 + while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
3326 + while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
3327 + if ((x1 == x2) || ((data.path == '\\') && (p13targetpath == ''))) {
3328 + // This is a different folder
3329 + p13filetree = data;
3330 + p13updateFiles();
3331 + }
3332 }
3333 }
3334 }
@@ -3614,35 +3618,35 @@
3618 var uploadFile;
3619 function p13doUploadFiles(files) {
3620 if (xxdialogMode) return;
3621 +
3622 + // Check if we are going to overwrite any files
3623 + var winAgent = ((currentNode.agent.id > 0) && (currentNode.agent.id < 5));
3624 + var targetFiles = [], overWriteCount = 0;
3625 + for (var i in p13filetree.dir) { if (winAgent) { targetFiles.push(p13filetree.dir[i].n.toLowerCase()); } else { targetFiles.push(p13filetree.dir[i].n); } }
3626 + for (var i = 0; i < files.length; i++) {
3627 + if (winAgent) {
3628 + if (targetFiles.indexOf(files[i].name.toLowerCase()) >= 0) { overWriteCount++; }
3629 + } else {
3630 + if (targetFiles.indexOf(files[i].name) >= 0) { overWriteCount++; }
3631 + }
3632 + }
3633 +
3634 + if (overWriteCount == 0) {
3635 + // If no overwrite, go ahead with upload
3636 + p13uploadFileContinue(1, files);
3637 + } else {
3638 + // Otherwise, prompt for confirmation
3639 + setDialogMode(2, "Upload File", 3, p13uploadFileContinue, format((overWriteCount == 1) ? "Upload will overwrite 1 file. Continue?" : "Upload will overwrite {0} files. Continue?", overWriteCount), files);
3640 + }
3641 + }
3642 +
3643 + function p13uploadFileContinue(b, files) {
3644 uploadFile = {};
3645 uploadFile.xpath = p13filetreelocation.join('/');
3646 uploadFile.xfiles = files;
3647 uploadFile.xfilePtr = -1;
3648 setDialogMode(2, "Upload File", 10, p13uploadFileCancel, '<div id=p13dfileName>' + "Connecting..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
3622 - p13uploadReconnect();
3623 - }
3624 -
3625 - function onFileUploadStateChange(xdownloadFile, state) {
3626 - switch (state) {
3627 - case 0:
3628 - p13folderup(9999);
3629 - break;
3630 - case 3:
3631 - p13uploadNextFile();
3632 - break;
3633 - default:
3634 - console.log('Unknown onFileUploadStateChange state', state);
3635 - break;
3636 - }
3637 - }
3638 -
3639 - // Connect again
3640 - function p13uploadReconnect() {
3641 - uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
3642 - uploadFile.ws.attemptWebRTC = false;
3643 - uploadFile.ws.ctrlMsgAllowed = false;
3644 - uploadFile.ws.onStateChanged = onFileUploadStateChange;
3645 - uploadFile.ws.Start(filesNode._id);
3649 + p13uploadNextFile();
3650 }
3651
3652 // Push the next file
@@ -3654,61 +3658,69 @@
3658 QH('p13dfileName', file.name);
3659 Q('d2progressBar').max = file.size;
3660 Q('d2progressBar').value = 0;
3657 -
3658 - uploadFile.xreader = new FileReader();
3659 - uploadFile.xreader.onload = function () {
3660 - uploadFile.xdata = uploadFile.xreader.result;
3661 - uploadFile.ws.sendText({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength });
3662 - };
3663 - uploadFile.xreader.readAsArrayBuffer(file);
3661 + if (file.xdata == null) {
3662 + // Load the data
3663 + uploadFile.xreader = new FileReader();
3664 + uploadFile.xreader.onload = function () {
3665 + uploadFile.xdata = uploadFile.xreader.result;
3666 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
3667 + };
3668 + uploadFile.xreader.readAsArrayBuffer(file);
3669 + } else {
3670 + // Data already loaded
3671 + uploadFile.xdata = file.xdata;
3672 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
3673 + }
3674 } else {
3665 - p13uploadFileCancel();
3675 + p13uploadFileTransferDone();
3676 }
3677 }
3678
3679 // Used to cancel the entire transfer.
3680 function p13uploadFileCancel(button, tag) {
3671 - if (uploadFile != null) {
3672 - if (uploadFile.ws != null) {
3673 - uploadFile.ws.Stop();
3674 - uploadFile.ws = null;
3675 - }
3676 - uploadFile = null;
3677 - }
3678 - setDialogMode(0); // Close any dialog boxes if present
3681 + if (uploadFile != null) { files.sendText(JSON.stringify({ action: 'uploadcancel', reqid: uploadFile.xfilePtr })); uploadFile = null; }
3682 + p13uploadFileTransferDone();
3683 + }
3684 +
3685 + // Used to cancel the entire transfer.
3686 + function p13uploadFileTransferDone() {
3687 + uploadFile = null; // No more files to upload, clean up.
3688 + setDialogMode(0); // Close the dialog box
3689 + p13folderup(9999); // Refresh the current folder
3690 }
3691
3692 // Receive upload ack from the mesh agent, use this to keep sending more data
3682 - function p13gotUploadData(data) {
3683 - var cmd = JSON.parse(data);
3693 + function p13gotUploadData(cmd) {
3694 if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
3685 -
3686 - if (cmd.action == 'uploadstart') {
3687 - p13uploadNextPart(false);
3688 - for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } // Send 8 more blocks of 4 k to full the websocket.
3689 - } else if (cmd.action == 'uploadack') {
3690 - p13uploadNextPart(false);
3691 - } else if (cmd.action == 'uploaderror') {
3692 - p13uploadFileCancel();
3695 + switch (cmd.action) {
3696 + case 'uploadstart': { p13uploadNextPart(false); for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } break; } // Send 8 more blocks of 16k to fill the websocket.
3697 + case 'uploadack': { p13uploadNextPart(false); break; }
3698 + case 'uploaddone': { if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadNextFile(); } else { p13uploadFileTransferDone(); } break; }
3699 + case 'uploaderror': { p13uploadFileCancel(); break; }
3700 }
3701 }
3702
3703 // Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file.
3704 function p13uploadNextPart(dataPriming) {
3698 - var data = uploadFile.xdata;
3699 - var start = uploadFile.xptr;
3700 - var end = uploadFile.xptr + 4096;
3701 - if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
3702 - if (start == data.byteLength) {
3703 - if (uploadFile.ws != null) { uploadFile.ws.Stop(); uploadFile.ws = null; }
3704 - if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadReconnect(); } else { p13uploadFileCancel(); }
3705 + var data = uploadFile.xdata, start = uploadFile.xptr;
3706 + if (start >= data.byteLength) {
3707 + files.sendText(JSON.stringify({ action: 'uploaddone', reqid: uploadFile.xfilePtr }));
3708 } else {
3706 - var datapart = data.slice(start, end);
3707 - uploadFile.ws.send(datapart);
3709 + var end = uploadFile.xptr + 16384;
3710 + if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
3711 + var dataslice = new Uint8Array(data.slice(start, end))
3712 + if ((dataslice[0] == 123) || (dataslice[0] == 0)) {
3713 + var datapart = new Uint8Array(end - start + 1);
3714 + datapart.set(dataslice, 1); // Add a zero char at the start of the send, this will indicate that it's not a JSON command.
3715 + files.send(datapart);
3716 + } else {
3717 + files.send(dataslice); // The data does not start with 0 or 123 "{" so it can't be confused for JSON.
3718 + }
3719 uploadFile.xptr = end;
3720 Q('d2progressBar').value = end;
3721 }
3722 }
3723 +
3724 //
3725 // DEVICE DETAILS
3726 //
views/default.handlebars
+49 -128
@@ -7713,21 +7713,27 @@
7713 //console.log('p13gotFiles', data);
7714 data = JSON.parse(decode_utf8(data));
7715 if (data.action == 'download') { p13gotDownloadCommand(data); return; }
7716 - data.path = data.path.replace(/\//g, '\\');
7717 - if ((p13filetree != null) && (data.path == p13filetree.path)) {
7718 - // This is an update to the same folder
7719 - var checkedNames = p13getCheckedNames();
7720 - p13filetree = data;
7721 - p13updateFiles(checkedNames);
7722 - } else {
7723 - // Make both paths use the same seperator not start with /
7724 - var x1 = data.path.replace(/\//g, '\\'), x2 = p13targetpath.replace(/\//g, '\\');
7725 - while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
7726 - while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
7727 - if ((x1 == x2) || ((data.path == '\\') && (p13targetpath == ''))) {
7728 - // This is a different folder
7716 +
7717 + // Process file upload commands
7718 + if ((data.action != null) && (data.action.startsWith('upload'))) { p13gotUploadData(data); return; }
7719 +
7720 + if (data.path != null) {
7721 + data.path = data.path.replace(/\//g, '\\');
7722 + if ((p13filetree != null) && (data.path == p13filetree.path)) {
7723 + // This is an update to the same folder
7724 + var checkedNames = p13getCheckedNames();
7725 p13filetree = data;
7730 - p13updateFiles();
7726 + p13updateFiles(checkedNames);
7727 + } else {
7728 + // Make both paths use the same seperator not start with /
7729 + var x1 = data.path.replace(/\//g, '\\'), x2 = p13targetpath.replace(/\//g, '\\');
7730 + while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
7731 + while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
7732 + if ((x1 == x2) || ((data.path == '\\') && (p13targetpath == ''))) {
7733 + // This is a different folder
7734 + p13filetree = data;
7735 + p13updateFiles();
7736 + }
7737 }
7738 }
7739 }
@@ -8020,68 +8026,6 @@
8026 p13uploadFileContinue(1, [{ name: tag, size: data.byteLength, type: 'text/plain', xdata: data }]);
8027 }
8028
8023 - /*
8024 - var downloadFile; // Global state for file download
8025 -
8026 - // Called by the html page to start a download, arguments are: path, file name and file size.
8027 - function p13downloadfile(x, y, z) {
8028 - if (xxdialogMode) return;
8029 - downloadFile = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotDownloadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); // Create our websocket file transport
8030 - downloadFile.ctrlMsgAllowed = false;
8031 - downloadFile.onStateChanged = onFileDownloadStateChange;
8032 - downloadFile.xpath = decodeURIComponent(x);
8033 - downloadFile.xfile = decodeURIComponent(y);
8034 - downloadFile.xsize = z;
8035 - downloadFile.xtsize = 0;
8036 - downloadFile.xstate = 0;
8037 - downloadFile.Start(filesNode._id);
8038 - setDialogMode(2, "Download File", 10, p13downloadFileCancel, '<div>' + downloadFile.xfile + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
8039 - }
8040 -
8041 - // Called by the html page to cancel the download
8042 - function p13downloadFileCancel(button, tag) {
8043 - //console.log('p13downloadFileCancel');
8044 - downloadFile.Stop();
8045 - delete downloadFile;
8046 - downloadFile = null;
8047 - }
8048 -
8049 - // Called by the file transport to indicate when the transport connection state has changed
8050 - function onFileDownloadStateChange(xdownloadFile, state) {
8051 - switch (state) {
8052 - case 0: // Transport as disconnected. If this is not part of an abort, we need to save the file
8053 - setDialogMode(0); // Close any dialog boxes if present
8054 - if ((downloadFile != null) && (downloadFile.xstate == 1)) { saveAs(data2blob(downloadFile.xdata), downloadFile.xfile); } // Save the file
8055 - break;
8056 - case 3: // Transport as connected, send a command to indicate we want to start a file download
8057 - downloadFile.send(JSON.stringify({ action: 'download', reqid: 1, path: downloadFile.xpath }));
8058 - break;
8059 - default:
8060 - console.log('Unknown onFileDownloadStateChange state', state);
8061 - break;
8062 - }
8063 - }
8064 -
8065 - // Called by the transport when data is received
8066 - function p13gotDownloadData(data) {
8067 - if (downloadFile.xstate == 0) { // If state is 0, this is a command confirming if the file will be transfered.
8068 - var cmd = JSON.parse(data);
8069 - if (cmd.action == 'downloadstart') { // Yes, the file is about to start
8070 - downloadFile.xstate = 1; // Switch to state 1, we will start receiving the file data
8071 - downloadFile.xdata = ''; // Start with empty data
8072 - downloadFile.send('a'); // Send the first ACK
8073 - } else if (cmd.action == 'downloaderror') { // Problem opening this file, cancel
8074 - p13downloadFileCancel();
8075 - }
8076 - } else { // We are in the process of receiving the file
8077 - downloadFile.xtsize += (data.length); // Add to the total bytes received
8078 - downloadFile.xdata += data; // Append the data
8079 - Q('d2progressBar').value = downloadFile.xtsize; // Change the progress bar
8080 - downloadFile.send('a'); // Send the ACK
8081 - }
8082 - }
8083 - */
8084 -
8029 //
8030 // FILES UPLOAD
8031 //
@@ -8117,28 +8061,7 @@
8061 uploadFile.xfiles = files;
8062 uploadFile.xfilePtr = -1;
8063 setDialogMode(2, "Upload File", 10, p13uploadFileCancel, '<div id=p13dfileName>' + "Connecting..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
8120 - p13uploadReconnect();
8121 - }
8122 -
8123 - function onFileUploadStateChange(xdownloadFile, state) {
8124 - switch (state) {
8125 - case 0:
8126 - setTimeout(function () { p13folderup(9999); }, 200); // Delay the file refresh
8127 - break;
8128 - case 3:
8129 - p13uploadNextFile();
8130 - break;
8131 - default:
8132 - break;
8133 - }
8134 - }
8135 -
8136 - // Connect again
8137 - function p13uploadReconnect() {
8138 - uploadFile.ws = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotUploadData), serverPublicNamePort, authCookie, authRelayCookie, domainUrl);
8139 - uploadFile.ws.attemptWebRTC = false;
8140 - uploadFile.ws.onStateChanged = onFileUploadStateChange;
8141 - uploadFile.ws.Start(filesNode._id);
8064 + p13uploadNextFile();
8065 }
8066
8067 // Push the next file
@@ -8150,66 +8073,64 @@
8073 QH('p13dfileName', file.name);
8074 Q('d2progressBar').max = file.size;
8075 Q('d2progressBar').value = 0;
8153 -
8076 if (file.xdata == null) {
8077 // Load the data
8078 uploadFile.xreader = new FileReader();
8079 uploadFile.xreader.onload = function () {
8080 uploadFile.xdata = uploadFile.xreader.result;
8159 - uploadFile.ws.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
8081 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
8082 };
8083 uploadFile.xreader.readAsArrayBuffer(file);
8084 } else {
8085 // Data already loaded
8086 uploadFile.xdata = file.xdata;
8165 - uploadFile.ws.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
8087 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
8088 }
8089 } else {
8168 - p13uploadFileCancel();
8090 + p13uploadFileTransferDone();
8091 }
8092 }
8093
8094 // Used to cancel the entire transfer.
8095 function p13uploadFileCancel(button, tag) {
8174 - if (uploadFile != null) {
8175 - if (uploadFile.ws != null) {
8176 - uploadFile.ws.Stop();
8177 - uploadFile.ws = null;
8178 - }
8179 - uploadFile = null;
8180 - }
8181 - setDialogMode(0); // Close any dialog boxes if present
8096 + if (uploadFile != null) { files.sendText(JSON.stringify({ action: 'uploadcancel', reqid: uploadFile.xfilePtr })); uploadFile = null; }
8097 + p13uploadFileTransferDone();
8098 + }
8099 +
8100 + // Used to cancel the entire transfer.
8101 + function p13uploadFileTransferDone() {
8102 + uploadFile = null; // No more files to upload, clean up.
8103 + setDialogMode(0); // Close the dialog box
8104 + p13folderup(9999); // Refresh the current folder
8105 }
8106
8107 // Receive upload ack from the mesh agent, use this to keep sending more data
8185 - function p13gotUploadData(data) {
8186 - var cmd = JSON.parse(data);
8108 + function p13gotUploadData(cmd) {
8109 if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
8188 -
8189 - if (cmd.action == 'uploadstart') {
8190 - p13uploadNextPart(false);
8191 - for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } // Send 8 more blocks of 4 k to full the websocket.
8192 - } else if (cmd.action == 'uploadack') {
8193 - p13uploadNextPart(false);
8194 - } else if (cmd.action == 'uploaddone') {
8195 - if (uploadFile.ws != null) { uploadFile.ws.Stop(); uploadFile.ws = null; }
8196 - if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadReconnect(); } else { p13uploadFileCancel(); }
8197 - } else if (cmd.action == 'uploaderror') {
8198 - p13uploadFileCancel();
8110 + switch (cmd.action) {
8111 + case 'uploadstart': { p13uploadNextPart(false); for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } break; } // Send 8 more blocks of 16k to fill the websocket.
8112 + case 'uploadack': { p13uploadNextPart(false); break; }
8113 + case 'uploaddone': { if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadNextFile(); } else { p13uploadFileTransferDone(); } break; }
8114 + case 'uploaderror': { p13uploadFileCancel(); break; }
8115 }
8116 }
8117
8118 // Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file.
8119 function p13uploadNextPart(dataPriming) {
8204 - var data = uploadFile.xdata;
8205 - var start = uploadFile.xptr;
8120 + var data = uploadFile.xdata, start = uploadFile.xptr;
8121 if (start >= data.byteLength) {
8207 - uploadFile.ws.sendCtrlMsg('{"ctrlChannel":"102938","type":"close"}');
8122 + files.sendText(JSON.stringify({ action: 'uploaddone', reqid: uploadFile.xfilePtr }));
8123 } else {
8124 var end = uploadFile.xptr + 16384;
8125 if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
8211 - var datapart = data.slice(start, end);
8212 - uploadFile.ws.send(datapart);
8126 + var dataslice = new Uint8Array(data.slice(start, end))
8127 + if ((dataslice[0] == 123) || (dataslice[0] == 0)) {
8128 + var datapart = new Uint8Array(end - start + 1);
8129 + datapart.set(dataslice, 1); // Add a zero char at the start of the send, this will indicate that it's not a JSON command.
8130 + files.send(datapart);
8131 + } else {
8132 + files.send(dataslice); // The data does not start with 0 or 123 "{" so it can't be confused for JSON.
8133 + }
8134 uploadFile.xptr = end;
8135 Q('d2progressBar').value = end;
8136 }