file_operation.html 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. <html>
  2. <head>
  3. <title locale="title">File Operation</title>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
  6. <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
  7. <script type="text/javascript" src="../../script/jquery.min.js"></script>
  8. <script type="text/javascript" src="../../script/semantic/semantic.min.js"></script>
  9. <script type="text/javascript" src="../../script/ao_module.js"></script>
  10. <script type="text/javascript" src="../../script/applocale.js"></script>
  11. <style>
  12. body{
  13. overflow: hidden;
  14. }
  15. .banner{
  16. background-color:#4287f5;
  17. height:50px;
  18. padding:12px;
  19. padding-left:20px;
  20. padding-top:16px;
  21. }
  22. #opricon{
  23. position:absolute;
  24. top:0px;
  25. right:0px;
  26. width:80px;
  27. height:80px;
  28. }
  29. .title{
  30. color:white;
  31. font-size:130%;
  32. }
  33. .content{
  34. padding:12px;
  35. }
  36. .info{
  37. margin-top:3px;
  38. white-space: nowrap;
  39. overflow: hidden;
  40. text-overflow: ellipsis;
  41. }
  42. </style>
  43. </head>
  44. <body>
  45. <div class="banner">
  46. <div class="title" locale="banner/title">Calculating Operation</div>
  47. <img id="opricon" src="img/loading.png" class="ui image"></img>
  48. </div>
  49. <div class="content">
  50. <div class="info"><span locale="info/from">From:</span> <span id="src"></span></div>
  51. <div class="info"><span locale="info/to">To:</span> <span id="dest"></span></div>
  52. <div class="info"><span locale="info/progress">Progress:</span> <span id="progress"> <i class="loading spinner icon"></i> <span>Calculating</span></div>
  53. <div class="ui active small progress" style="margin-top:18px;">
  54. <div id="progressbar" class="bar" style="width:100%; background-color:#4287f5;"></div>
  55. </div>
  56. </div>
  57. <div class="ui modal" id="duplicateAction">
  58. <div class="content">
  59. <div class="description" style="padding: 0px !important;">
  60. <p><i class="big exclamation triangle icon"></i> <span locale="dup/question">File with same name already exists. <b>Which action should be taken?</b></span></p><br>
  61. </div>
  62. </div>
  63. <div class="actions">
  64. <div locale="dup/overwrite" class="ui labeled button" onclick="continueProcess('overwrite');">
  65. Overwrite
  66. </div>
  67. <div locale="dup/skip" class="ui labeled button" onclick="continueProcess('skip');">
  68. Skip
  69. </div>
  70. <div locale="dup/renameAndKeep" class="ui labeled button" style="color: #2fb55c;" onclick="continueProcess('keep');">
  71. Rename & Keep
  72. </div>
  73. </div>
  74. </div>
  75. <script>
  76. /*
  77. ArOZ Online File Operation Listener
  78. Usage: Pass in the following JSON object as hash with encodeURIComponent after JSON stringify
  79. {
  80. opr: {move / copy / zip / unzip / download / zipAndDown / unzipAndOpen},
  81. src: {filelist, allow multiple files},
  82. dest: {filepath},
  83. //Optional paramters
  84. overwriteMode: {skip / overwrite / keep},
  85. callbackWindowID: {floatWindow ID},
  86. callbackFunction: {target Window Function Name as String}
  87. }
  88. **For download opr, it will first buffer into the browser memory.
  89. It is not recommended for files > 2GB (Firefox Limit)
  90. Example callbackFunction: "refreshList()" (string)
  91. */
  92. var operationConfig = null;
  93. var opr = "";
  94. var maxPathDisplayLength = 40;
  95. var legacyMode = !('WebSocket' in window || 'MozWebSocket' in window); //Use AJAX instead of WebSocket if legacy mode is activated
  96. var enterErrorMode = false;
  97. //Initalized floatWindow events
  98. ao_module_setFixedWindowSize();
  99. ao_module_setWindowSize(400,220);
  100. if (applocale){
  101. //Applocale found. Do localization
  102. applocale.init("../locale/file_operation.json", function(){
  103. applocale.translate();
  104. init();
  105. });
  106. }else{
  107. //Applocale not found. Is this a trim down version of ArozOS?
  108. applocale = {
  109. getString: function(key, original){
  110. return original;
  111. }
  112. }
  113. init();
  114. }
  115. function init(){
  116. console.log("Checking launch parameters...");
  117. if (window.location.hash.length > 0){
  118. //OK to proceed
  119. try{
  120. operationConfig = JSON.parse(decodeURIComponent(window.location.hash.substring(1)));
  121. //Check if there are any missing paratmers
  122. configValid = true;
  123. if (typeof operationConfig.opr == "undefined"){ configValid = false; }
  124. if (typeof operationConfig.src == "undefined"){ configValid = false; }
  125. if (typeof operationConfig.dest == "undefined"){ configValid = false; }
  126. if (!configValid){
  127. console.log("Invalid file operation config. Please see the file_operation.html source code for the correct config json object.")
  128. ao_module_close();
  129. return;
  130. }
  131. //Parse the missing argument if there are any
  132. if (typeof operationConfig.overwriteMode == "undefined"){
  133. operationConfig.overwriteMode = "skip";
  134. }
  135. //Update 17-12-2020, ask the user for overwrite mode if file duplicate exists
  136. if (operationConfig.overwriteMode == "ask"){
  137. //Check if any file duplication before proceeding
  138. console.log(operationConfig.src);
  139. $.ajax({
  140. url: "../../system/file_system/listDir",
  141. data: {dir: operationConfig.dest},
  142. success: function(filelist){
  143. //Check for duplication
  144. var srcFilenameList = [];
  145. operationConfig.src.forEach(srcpath => {
  146. var filename = srcpath.split("/").pop();
  147. srcFilenameList.push(filename);
  148. })
  149. var duplicateFound = filelist.some(function(file){
  150. return srcFilenameList.includes(file.Filename);
  151. });
  152. console.log(filelist);
  153. console.log(operationConfig.src);
  154. if (duplicateFound){
  155. //Duplication found.
  156. $("#duplicateAction").modal({
  157. closable: false
  158. }).modal("show");
  159. }else{
  160. //Duplication not found. Start the operation with default mode
  161. operationConfig.overwriteMode = "skip";
  162. processOperations(operationConfig);
  163. }
  164. }
  165. })
  166. }else{
  167. //All information are defined. Process it now.
  168. processOperations(operationConfig)
  169. }
  170. }catch(ex){
  171. //Failed.
  172. console.log("Argument parse error", ex);
  173. }
  174. }else{
  175. alert("Invalid use of File Operation Listener.")
  176. ao_module_close();
  177. }
  178. }
  179. function continueProcess(duplicateMode){
  180. operationConfig.overwriteMode = duplicateMode;
  181. $("#duplicateAction").modal("hide");
  182. processOperations(operationConfig)
  183. }
  184. function processOperations(operationConfig){
  185. //Update the display information
  186. $("#src").text(operationConfig.src);
  187. $("#dest").text(operationConfig.dest);
  188. opr = operationConfig.opr;
  189. updateTitle(operationConfig.src.length, operationConfig.opr);
  190. //Check which type of the oprs is about. And assign the related functions to start
  191. if (operationConfig.opr == "move"){
  192. $("#opricon").attr("src","img/move.gif");
  193. cut(operationConfig.src, operationConfig.dest, operationConfig.overwriteMode);
  194. }else if (operationConfig.opr == "copy"){
  195. $("#opricon").attr("src","img/copy.gif");
  196. copyopr(operationConfig.src, operationConfig.dest, operationConfig.overwriteMode);
  197. }else if (operationConfig.opr == "zip"){
  198. $("#opricon").attr("src","img/zip.gif");
  199. zip(operationConfig.src, operationConfig.dest, operationConfig.overwriteMode);
  200. }else if (operationConfig.opr == "unzip"){
  201. $("#opricon").attr("src","img/unzip.gif");
  202. unzip(operationConfig.src, operationConfig.dest, operationConfig.overwriteMode);
  203. }else if (operationConfig.opr == "unzipAndOpen"){
  204. $("#opricon").attr("src","img/unzip.gif");
  205. unzip(operationConfig.src, operationConfig.dest, operationConfig.overwriteMode, function(){
  206. //Open the target directory
  207. });
  208. }
  209. }
  210. //Unzip zip
  211. function unzip(srcList, dest, overwriteMode, callback=undefined){
  212. if (legacyMode){
  213. //Run in legacy mode
  214. requestCSRFToken(function(token){
  215. $.ajax({
  216. type: 'POST',
  217. url: `../../system/file_system/fileOpr`,
  218. data: {opr: "unzip" ,src: JSON.stringify(srcList), dest: dest, csrft: token},
  219. success: function(data){
  220. handleFinish(data);
  221. }
  222. });
  223. });
  224. }else{
  225. //Filter all + sign in the list
  226. var filteredSrcList = [];
  227. srcList.forEach(src => {
  228. filteredSrcList.push(src.split("+").join("{{plug_sign}}"));
  229. });
  230. //Open WebSocket
  231. var endpoint = getWSEndpoint() + `?opr=unzip&src=${encodeURIComponent(JSON.stringify(filteredSrcList))}&dest=${encodeURIComponent(dest)}&existsresp=${overwriteMode}`
  232. console.log(endpoint);
  233. var ws = new WebSocket(endpoint);
  234. ws.onopen = function(){
  235. //Do nothing. Just listen to the progress update
  236. };
  237. ws.onmessage = function (evt) {
  238. var data = evt.data;
  239. var progress = JSON.parse(data);
  240. console.log(progress);
  241. if (progress.Error != ""){
  242. //Something went wrong
  243. $("#progressbar").css("background-color", "#eb3f28");
  244. $("#opricon").attr("src", "img/error.png");
  245. enterErrorMode = true;
  246. alert(progress.Error);
  247. }else{
  248. //Update the progress display
  249. $("#progressbar").css("width", progress.Progress + "%");
  250. var currentSrc = truncate(progress.LatestFile, maxPathDisplayLength);
  251. var filteredDest = operationConfig.dest.trim();
  252. if (filteredDest.substr(filteredDest.length -1, 1) != "/"){
  253. filteredDest += "/"
  254. }
  255. var currentDest = truncate(filteredDest + progress.LatestFile, maxPathDisplayLength);
  256. $("#src").text(currentSrc);
  257. $("#dest").text(currentDest);
  258. $("#progress").text(progress.Progress + "%")
  259. if (progress.Progress == 100){
  260. //Set progress bar to green
  261. $("#progressbar").css("background-color", "#2bba35");
  262. }
  263. }
  264. };
  265. ws.onclose = function() {
  266. if (!enterErrorMode){
  267. $("#progressbar").css("background-color", "#2bba35");
  268. $("#progressbar").css("width", "100%");
  269. $("#progress").text("100%");
  270. $("#opricon").attr("src", "img/done.png")
  271. setTimeout(function(){
  272. if (operationConfig.opr == "unzipAndOpen"){
  273. //If open after unzip is required
  274. ao_module_openPath(operationConfig.dest);
  275. }
  276. ao_module_close();
  277. }, 100);
  278. }
  279. };
  280. ws.onerror = function(event){
  281. console.error("WebSocket error observed:", event);
  282. legacyMode = true;
  283. console.log("Falling back to Legacy Mode");
  284. unzip(srcList, dest, overwriteMode, callback);
  285. }
  286. }
  287. }
  288. //Create zip
  289. function zip(srcList, dest, overwriteMode){
  290. if (legacyMode){
  291. //Run in legacy mode
  292. requestCSRFToken(function(token){
  293. $.ajax({
  294. type: 'POST',
  295. url: `../../system/file_system/fileOpr`,
  296. data: {opr: "zip" ,src: JSON.stringify(srcList), dest: dest, csrft: token},
  297. success: function(data){
  298. handleFinish(data);
  299. }
  300. });
  301. });
  302. }else{
  303. //Replace all + sign with tag
  304. var filteredSrcList = [];
  305. srcList.forEach(src => {
  306. filteredSrcList.push(src.split("+").join("{{plug_sign}}"));
  307. })
  308. //Start WebSocket connection
  309. var endpoint = getWSEndpoint() + `?opr=zip&src=${encodeURIComponent(JSON.stringify(filteredSrcList))}&dest=${encodeURIComponent(dest)}&existsresp=${overwriteMode}`
  310. console.log(endpoint);
  311. var ws = new WebSocket(endpoint);
  312. var srcZipRoot = "";
  313. ws.onopen = function() {
  314. console.log("File Operation WebSocket opened")
  315. //Emulate the src folder
  316. var srcDir = srcList[0].split("/");
  317. srcDir.pop();
  318. srcDir = srcDir.join("/");
  319. srcZipRoot = srcDir;
  320. var currentSrc = truncate(srcDir, maxPathDisplayLength);
  321. $("#src").text(currentSrc);
  322. //Emulate the dest folder
  323. var destFolderName = dest.substr(0, dest.length - 1).split('/').pop();
  324. destFolderName += ".zip";
  325. var currentDest = truncate(dest + destFolderName, maxPathDisplayLength);
  326. $("#dest").text(currentDest);
  327. };
  328. ws.onmessage = function (evt) {
  329. var data = evt.data;
  330. var progress = JSON.parse(data);
  331. if (progress.Error != ""){
  332. //Something went wrong
  333. $("#progressbar").css("background-color", "#eb3f28");
  334. enterErrorMode = true;
  335. alert(progress.Error);
  336. }else{
  337. //Update the progress display
  338. $("#progressbar").css("width", progress.Progress + "%");
  339. var currentSrc = truncate(srcZipRoot + "/" + progress.LatestFile, maxPathDisplayLength);
  340. var filteredDest = operationConfig.dest.trim();
  341. if (filteredDest.substr(filteredDest.length -1, 1) != "/"){
  342. filteredDest += "/"
  343. }
  344. var currentDest = truncate(filteredDest + progress.LatestFile, maxPathDisplayLength);
  345. $("#src").text(currentSrc);
  346. $("#dest").text(currentDest);
  347. $("#progress").text(progress.Progress + "%")
  348. if (progress.Progress == 100){
  349. //Set progress bar to green
  350. $("#progressbar").css("background-color", "#2bba35");
  351. }
  352. }
  353. };
  354. ws.onclose = function() {
  355. //Transfer finished! Set OK and close in 1 second
  356. if (!enterErrorMode){
  357. $("#progressbar").css("background-color", "#2bba35");
  358. $("#progressbar").css("width", "100%");
  359. $("#progress").text("100%")
  360. handleFinish({});
  361. }
  362. };
  363. ws.onerror = function(event){
  364. console.error("WebSocket error observed:", event);
  365. legacyMode = true;
  366. console.log("Falling back to Legacy Mode");
  367. zip(srcList, dest, overwriteMode);
  368. }
  369. }
  370. }
  371. function cut(srcList, dest, overwriteMode){
  372. if (legacyMode){
  373. console.log("WebSocket not found, Running in legacy mode");
  374. requestCSRFToken(function(token){
  375. $.ajax({
  376. type: 'POST',
  377. url: `../../system/file_system/fileOpr`,
  378. data: {opr: "move" ,src: JSON.stringify(srcList), dest: dest,existsresp: overwriteMode, csrft: token},
  379. success: function(data){
  380. handleFinish(data);
  381. }
  382. });
  383. });
  384. }else{
  385. //Replace all + sign in srclist with {{plus_sign}}
  386. var filteredSrcList = [];
  387. srcList.forEach(src => {
  388. filteredSrcList.push(src.split("+").join("{{plug_sign}}"));
  389. })
  390. //Use Websocket for operation updates
  391. var endpoint = getWSEndpoint() + `?opr=move&src=${encodeURIComponent(JSON.stringify(filteredSrcList))}&dest=${encodeURIComponent(dest)}&existsresp=${overwriteMode}`
  392. console.log(endpoint);
  393. var ws = new WebSocket(endpoint);
  394. ws.onopen = function() {
  395. console.log("File Operation WebSocket opened")
  396. };
  397. ws.onmessage = function (evt) {
  398. var data = evt.data;
  399. var progress = JSON.parse(data);
  400. if (progress.Error != ""){
  401. $("#progressbar").css("background-color", "#eb3f28");
  402. enterErrorMode = true;
  403. alert(progress.Error);
  404. }else{
  405. $("#progressbar").css("width", progress.Progress + "%");
  406. var currentSrc = truncate(operationConfig.src + "/" + progress.LatestFile, maxPathDisplayLength);
  407. var filteredDest = operationConfig.dest.trim();
  408. if (filteredDest.substr(filteredDest.length -1, 1) != "/"){
  409. filteredDest += "/"
  410. }
  411. var currentDest = truncate(filteredDest + progress.LatestFile, maxPathDisplayLength);
  412. $("#src").text(currentSrc);
  413. $("#dest").text(currentDest);
  414. $("#progress").text(progress.Progress + "%")
  415. if (progress.Progress == 100){
  416. //Set progress bar to green
  417. $("#progressbar").css("background-color", "#2bba35");
  418. }
  419. }
  420. };
  421. ws.onclose = function() {
  422. //Transfer finished! Set OK and close in 1 second
  423. if (!enterErrorMode){
  424. $("#progressbar").css("background-color", "#2bba35");
  425. $("#progressbar").css("width", "100%");
  426. $("#progress").text("100%")
  427. handleFinish({});
  428. }
  429. };
  430. ws.onerror = function(event){
  431. console.error("WebSocket error observed:", event);
  432. console.log("Falling back to Legacy Mode")
  433. legacyMode = true;
  434. cut(srcList, dest, overwriteMode)
  435. }
  436. }
  437. }
  438. function copyopr(srcList, dest, overwriteMode){
  439. if (legacyMode){
  440. //Open operation in legacy mode
  441. console.log("WebSocket not found, Running in legacy mode");
  442. requestCSRFToken(function(token){
  443. $.ajax({
  444. type: 'POST',
  445. url: `../../system/file_system/fileOpr`,
  446. data: {opr: "copy" ,src: JSON.stringify(srcList), dest: dest,existsresp: overwriteMode , csrft: token},
  447. success: function(data){
  448. handleFinish(data);
  449. }
  450. });
  451. });
  452. }else{
  453. var filteredSrcList = [];
  454. srcList.forEach(src => {
  455. filteredSrcList.push(src.split("+").join("{{plug_sign}}"));
  456. })
  457. //Use Websocket for operation updates
  458. var endpoint = getWSEndpoint() + `?opr=copy&src=${encodeURIComponent(JSON.stringify(filteredSrcList))}&dest=${encodeURIComponent(dest)}&existsresp=${overwriteMode}`
  459. var ws = new WebSocket(endpoint);
  460. ws.onopen = function() {
  461. console.log("File Operation WebSocket opened")
  462. };
  463. ws.onmessage = function (evt) {
  464. var data = evt.data;
  465. var progress = JSON.parse(data);
  466. if (progress.Error != ""){
  467. $("#progressbar").css("background-color", "#eb3f28");
  468. enterErrorMode = true;
  469. alert(progress.Error);
  470. }else{
  471. $("#progressbar").css("width", progress.Progress + "%");
  472. var currentSrc = truncate(operationConfig.src + "/" + progress.LatestFile, maxPathDisplayLength);
  473. var filteredDest = operationConfig.dest.trim();
  474. if (filteredDest.substr(filteredDest.length -1, 1) != "/"){
  475. filteredDest += "/"
  476. }
  477. var currentDest = truncate(filteredDest + progress.LatestFile, maxPathDisplayLength);
  478. $("#src").text(currentSrc);
  479. $("#dest").text(currentDest);
  480. $("#progress").text(progress.Progress + "%")
  481. if (progress.Progress == 100){
  482. //Set progress bar to green
  483. $("#progressbar").css("background-color", "#2bba35");
  484. }
  485. }
  486. };
  487. ws.onclose = function() {
  488. //Transfer finished! Set OK and close in 1 second
  489. if (!enterErrorMode){
  490. $("#progressbar").css("background-color", "#2bba35");
  491. $("#progressbar").css("width", "100%");
  492. $("#progress").text("100%");
  493. handleFinish({});
  494. }
  495. };
  496. ws.onerror = function(event){
  497. console.error("WebSocket error observed:", event);
  498. console.log("Falling back to Legacy Mode")
  499. legacyMode = true;
  500. copyopr(srcList, dest, overwriteMode)
  501. }
  502. }
  503. }
  504. var truncate = function (fullStr, strLen, separator) {
  505. if (fullStr.length <= strLen) return fullStr;
  506. separator = separator || '...';
  507. var sepLen = separator.length,
  508. charsToShow = strLen - sepLen,
  509. frontChars = Math.ceil(charsToShow/2),
  510. backChars = Math.floor(charsToShow/2);
  511. return fullStr.substr(0, frontChars) +
  512. separator +
  513. fullStr.substr(fullStr.length - backChars);
  514. };
  515. function getWSEndpoint(){
  516. //Open opeartion in websocket
  517. let protocol = "wss://";
  518. if (location.protocol !== 'https:') {
  519. protocol = "ws://";
  520. }
  521. var port = window.location.port;
  522. if (window.location.port == ""){
  523. if (location.protocol !== 'https:') {
  524. port = "80";
  525. }else{
  526. port = "443";
  527. }
  528. }
  529. wsControlEndpoint = (protocol + window.location.hostname + ":" + port + "/system/file_system/ws/fileOpr");
  530. return wsControlEndpoint;
  531. }
  532. function updateTitle(fileNumber, opr){
  533. var title = "";
  534. if (opr == "move"){
  535. title = applocale.getString("title/moving","Moving ");
  536. }else if (opr == "copy"){
  537. title = applocale.getString("title/copying","Copying ");
  538. }else if (opr == "zip" || opr == "zipAndDownload"){
  539. title = applocale.getString("title/zipping","Zipping ");
  540. }else if (opr == "download"){
  541. title = applocale.getString("title/downloading","Downloading ");
  542. }else if (opr == "unzip" || opr == "unzipAndOpen"){
  543. title = applocale.getString("title/unzipping","Unzipping ");
  544. }
  545. title += fileNumber + " ";
  546. if (fileNumber == 1){
  547. title += applocale.getString("title/file"," File");
  548. }else{
  549. title += applocale.getString("title/files"," Files");
  550. }
  551. $(".title").text(title);
  552. }
  553. function handleFinish(data){
  554. if (data.error !== undefined){
  555. $("#progressbar").css("background-color","#db2828");
  556. $("#progressbar").parent().removeClass('active');
  557. $(".title").html(`<i class="remove icon"></i>` + applocale.getString("error/" + data.error,data.error));
  558. enterErrorMode = true;
  559. return
  560. }else{
  561. $("#progressbar").css("background-color","#21ba45");
  562. $("#progressbar").parent().removeClass('active');
  563. if (opr == "move" || opr == "copy" || opr == "zip" || opr == "unzip"){
  564. //Action completed. close window.
  565. setTimeout(function(){
  566. //Do callback if exists
  567. if (operationConfig.callbackWindowID == "desktop"){
  568. //Special call from desktop
  569. parent.eval(operationConfig.callbackFunction);
  570. }else if (operationConfig.callbackWindowID !== undefined && operationConfig.callbackFunction !== undefined){
  571. var callbackWindowObject = parent.getFloatWindowByID(operationConfig.callbackWindowID)
  572. var windowObject = $(callbackWindowObject).find("iframe")[0];
  573. if (windowObject == undefined || windowObject == null){
  574. //Caller no longer exists.
  575. }else{
  576. //Caller still exists. Do callback events
  577. //console.log(windowObject.contentWindow, operationConfig.callbackFunction);
  578. windowObject.contentWindow.eval(operationConfig.callbackFunction);
  579. }
  580. }
  581. //If the target or src is desktop, refresh desktop as well
  582. if(pathIsOnDesktop(operationConfig.dest) || pathIsOnDesktop(operationConfig.src[0])){
  583. if (ao_module_virtualDesktop){
  584. parent.refresh(undefined, true);
  585. }
  586. }
  587. if (!enterErrorMode){
  588. ao_module_close();
  589. }
  590. }, 1000);
  591. }else if (opr == "download"){
  592. //Create download from buffer
  593. }else if (opr == "zipAndDown"){
  594. //Download
  595. }else if (opr == "unzipAndOpen"){
  596. //Unzip and open the target directory
  597. setTimeout(function(){
  598. //Open the target directory
  599. ao_module_openPath(operationConfig.dest);
  600. //Close the window
  601. ao_module_close();
  602. }, 1000);
  603. }
  604. }
  605. console.log(data);
  606. }
  607. function pathIsOnDesktop(path){
  608. var filteredDest = path;
  609. if (filteredDest.substr(filteredDest.length - 1) == "/"){
  610. filteredDest = filteredDest.substr(0, filteredDest.length - 1);
  611. }
  612. var dirChunk = filteredDest.split("/");
  613. console.log(dirChunk);
  614. if (dirChunk.length == 2 || dirChunk.length == 3){
  615. if (dirChunk[0].toLowerCase() == "user:" && dirChunk[1].toLowerCase() == "desktop"){
  616. //This is a direct access desktop file
  617. return true;
  618. }
  619. }
  620. return false;
  621. }
  622. function requestCSRFToken(callback){
  623. $.ajax({
  624. url: "../../system/csrf/new",
  625. success: function(token){
  626. callback(token);
  627. }
  628. })
  629. }
  630. </script>
  631. </body>
  632. </html>