file.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. /*
  2. * Copyright 2011 Wolfgang Koller - http://www.gofg.at/
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * FileError interface
  18. * http://www.w3.org/TR/file-system-api/#the-fileerror-interface
  19. */
  20. function FileError() {
  21. }
  22. FileError.cast = function( p_code ) {
  23. var fe = new FileError();
  24. fe.code = p_code;
  25. return fe;
  26. }
  27. FileError.prototype.code = 0;
  28. FileError.NOT_FOUND_ERR = 1;
  29. FileError.SECURITY_ERR = 2;
  30. FileError.ABORT_ERR = 3;
  31. FileError.NOT_READABLE_ERR = 4;
  32. FileError.ENCODING_ERR = 5;
  33. FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
  34. FileError.INVALID_STATE_ERR = 7;
  35. FileError.SYNTAX_ERR = 8;
  36. FileError.INVALID_MODIFICATION_ERR = 9;
  37. FileError.QUOTA_EXCEEDED_ERR = 10;
  38. FileError.TYPE_MISMATCH_ERR = 11;
  39. FileError.PATH_EXISTS_ERR = 12;
  40. /**
  41. * FileException interface
  42. * http://www.w3.org/TR/FileAPI/#dfn-FileException
  43. */
  44. //use this one as FileError name conflict
  45. function FileException() {
  46. }
  47. FileException.cast = function( p_code ) {
  48. var fe = new FileException();
  49. fe.code = p_code;
  50. return fe;
  51. }
  52. FileException.prototype.code = 0;
  53. FileException.NOT_FOUND_ERR = 1;
  54. FileException.SECURITY_ERR = 2;
  55. FileException.ABORT_ERR = 3;
  56. FileException.NOT_READABLE_ERR = 4;
  57. FileException.ENCODING_ERR = 5;
  58. FileException.NO_MODIFICATION_ALLOWED_ERR = 6;
  59. FileException.INVALID_STATE_ERR = 7;
  60. FileException.SYNTAX_ERR = 8;
  61. FileException.INVALID_MODIFICATION_ERR = 9;
  62. FileException.QUOTA_EXCEEDED_ERR = 10;
  63. FileException.TYPE_MISMATCH_ERR = 11;
  64. FileException.PATH_EXISTS_ERR = 12;
  65. /**
  66. * FileMetadata (Metadata) interface
  67. * http://www.w3.org/TR/file-system-api/#idl-def-Metadata
  68. */
  69. function Metadata(p_modificationDate ) {
  70. this.modificationTime = p_modificationDate || null;
  71. return this;
  72. }
  73. Metadata.cast = function( p_modificationDate ) {
  74. var md = new Metadata(p_modificationDate);
  75. return md;
  76. }
  77. function Flags(create, exclusive) {
  78. this.create = create || false;
  79. this.exclusive = exclusive || false;
  80. };
  81. Flags.cast = function( p_modificationDate ) {
  82. var md = new Metadata(p_modificationDate);
  83. return md;
  84. }
  85. Flags.cast = function(create, exclusive) {
  86. var that = new Flags(create, exclusive);
  87. return that;
  88. };
  89. /**
  90. * Entry interface
  91. * http://www.w3.org/TR/file-system-api/#idl-def-Entry
  92. */
  93. function Entry() {
  94. }
  95. Entry.prototype.isFile = false;
  96. Entry.prototype.isDirectory = false;
  97. Entry.prototype.name = "";
  98. Entry.prototype.fullPath = "";//fullpath for cordova-test = realFullPath - "/"
  99. Entry.prototype.filesystem = null;
  100. Entry.prototype.getMetadata = function( successCallback, errorCallback ) {
  101. // Get metadata for this entry
  102. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "getMetadata", [this.fullPath]);
  103. }
  104. Entry.prototype.setMetadata = function( successCallback, errorCallback ) {
  105. //Cordova.exec(successCallback, errorCallback, "com.cordova.File", "setMetadata", [this.fullPath]);
  106. }
  107. /**
  108. * Copies or Move a file to a new location
  109. *
  110. * @param {Entry} parent the directory to which to copy the entry
  111. * @param {DOMString} newName the new name of the entry, defaults to the current name
  112. */
  113. //Entry.prototype.moveTo = function( parent, newName, successCallback, errorCallback ) {
  114. // }
  115. //Entry.prototype.copyTo = function( parent, newName, successCallback, errorCallback ) {
  116. // }
  117. Entry.prototype.toURL = function( mimeType ) {
  118. return "file://" + this.fullPath;
  119. }
  120. Entry.prototype.remove = function( successCallback, errorCallback ) {
  121. // Remove this entry
  122. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "remove", [this.fullPath]);
  123. }
  124. Entry.prototype.getParent = function( successCallback, errorCallback ) {
  125. // Ask the system for our parent
  126. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "getParent", [this.fullPath]);
  127. }
  128. /**
  129. * FileInfo (File) interface
  130. * (had to call the 'File' object FileInfo since there were name conflicts)
  131. * http://dev.w3.org/2006/webapi/FileAPI/#dfn-file
  132. */
  133. //function FileInfo() {
  134. //}
  135. //FileInfo.cast = function( p_name, p_fullPath, p_type, p_lastModifiedDate, p_size ) {
  136. // var f = new FileInfo();
  137. // f.name = p_name;
  138. // f.fullPath = p_fullPath;
  139. // f.type = p_type;
  140. // f.lastModifiedDate = p_lastModifiedDate;
  141. // f.size = p_size;
  142. // return f;
  143. // }
  144. //FileInfo.prototype.name = "";
  145. //FileInfo.prototype.fullPath = "";
  146. //FileInfo.prototype.type = "unknown/unknown";
  147. //FileInfo.prototype.lastModifiedDate = null;
  148. //FileInfo.prototype.size = 0;
  149. //Rework, have to overwrite it to pass the test-cast,
  150. function File(name, fullPath, type, lastModifiedDate, size) {
  151. this.name = name || null;
  152. this.fullPath = fullPath || null;
  153. this.type = type || null;
  154. this.lastModifiedDate = lastModifiedDate || null;
  155. this.size = size || 0;
  156. }
  157. File.cast = function( p_name, p_fullPath, p_type, p_lastModifiedDate, p_size ) {
  158. var f = new File(p_name, p_fullPath, p_type, p_lastModifiedDate, p_size);
  159. return f;
  160. }
  161. /**
  162. * FileSaver interface
  163. * http://www.w3.org/TR/file-writer-api/#idl-def-FileSaver
  164. */
  165. function FileSaver() {
  166. }
  167. FileSaver.createEvent = function( p_type, p_target ) {
  168. var evt = {
  169. "type": p_type,
  170. "target": p_target
  171. };
  172. return evt;
  173. }
  174. FileSaver.prototype.abort = function() {
  175. if( this.readyState == FileSaver.INIT || this.readyState == FileSaver.DONE ) throw FileException.cast(FileException.INVALID_STATE_ERR);
  176. this.error = FileError.cast(FileError.ABORT_ERR);
  177. this.readyState = FileSaver.DONE;
  178. if( typeof this.onerror === "function" ) this.onerror(FileSaver.createEvent("error", this));
  179. if( typeof this.onabort === "function" ) this.onabort(FileSaver.createEvent("abort", this));
  180. if( typeof this.onwriteend === "function" ) this.onwriteend(FileSaver.createEvent("writeend", this));
  181. }
  182. FileSaver.INIT = 0;
  183. FileSaver.WRITING = 1;
  184. FileSaver.DONE = 2;
  185. FileSaver.prototype.readyState = FileSaver.INIT;
  186. FileSaver.prototype.error = new FileError();
  187. FileSaver.prototype.onwritestart = null;
  188. FileSaver.prototype.onprogress = null;
  189. FileSaver.prototype.onwrite = null;
  190. FileSaver.prototype.onabort = null;
  191. FileSaver.prototype.onerror = null;
  192. FileSaver.prototype.onwriteend = null;
  193. //FileSaver.prototype.fullPath = ""; // Not W3C conform, but we need the path for handling!
  194. /**
  195. * FileWriter interface
  196. * (derives from FileSaver)
  197. * http://www.w3.org/TR/file-writer-api/#idl-def-FileWriter
  198. */
  199. function FileWriter(p_file) {
  200. this.fullPath = p_file.fullPath || "";
  201. return this;
  202. }
  203. FileWriter.cast = function( p_fullPath, p_length ) {
  204. var tmpFile = new File(null,p_fullPath,null, null,null);
  205. var fw = new FileWriter(tmpFile);
  206. return fw;
  207. }
  208. FileWriter.prototype = new FileSaver();
  209. FileWriter.prototype.fullPath = "";
  210. FileWriter.prototype.position = 0;
  211. FileWriter.prototype.length = 0;
  212. FileWriter.prototype.write = function( data ) {
  213. //console.log( 'Calling write: ' + this.position + " / " + this.length );
  214. // Check if we are able to write
  215. if( this.readyState == FileSaver.WRITING ) throw FileException.cast(FileException.INVALID_STATE_ERR);
  216. // We are writing now
  217. this.readyState = FileSaver.WRITING;
  218. // Emit the start event
  219. if( typeof this.onwritestart === "function" ) this.onwritestart( FileSaver.createEvent("writestart", this) );
  220. // Finally do the writing
  221. var me = this;
  222. Cordova.exec(function(p_position, p_length) {
  223. // Update position & length for file
  224. me.position = p_position;
  225. me.length = p_length;
  226. // Update state
  227. me.readyState = FileSaver.DONE;
  228. // Dispatch missing events
  229. if( typeof me.onwrite === "function" ) me.onwrite( FileSaver.createEvent("write", me) );
  230. if( typeof me.onwriteend === "function" ) me.onwriteend( FileSaver.createEvent("writeend", me) );
  231. }, function( p_fileError, p_position, p_length ) {
  232. // Update position & length for file
  233. me.position = p_position;
  234. me.length = p_length;
  235. // Set error object & update state
  236. me.error = p_fileError;
  237. me.readyState = FileSaver.DONE;
  238. // Dispatch missing events
  239. if( typeof me.onerror === "function" ) me.onerror( FileWriter.createEvent("error", me) );
  240. if( typeof me.onwriteend === "function" ) me.onwriteend( FileWriter.createEvent("writeend", me) );
  241. }, "com.cordova.File", "write", [this.fullPath, this.position, data]);
  242. }
  243. FileWriter.prototype.seek = function( offset ) {
  244. //console.log( 'Calling seek: ' + offset + " / " + this.position + " / " + this.length + " / " + this.readyState );
  245. if( this.readyState == FileSaver.WRITING ) throw FileException.cast(FileException.INVALID_STATE_ERR);
  246. if( offset < 0 ) {
  247. this.position = Math.max(offset + this.length, 0);
  248. }
  249. else if( offset > this.length ) {
  250. this.position = this.length;
  251. }
  252. else {
  253. this.position = offset;
  254. }
  255. }
  256. FileWriter.prototype.truncate = function( size ) {
  257. // Check if we are able to write
  258. if( this.readyState == FileSaver.WRITING ) throw FileException.cast(FileException.INVALID_STATE_ERR);
  259. // We are writing now
  260. this.readyState = FileSaver.WRITING;
  261. // Emit the start event
  262. if( typeof this.onwritestart === "function" ) this.onwritestart( FileSaver.createEvent("writestart", this) );
  263. // Finally do the writing
  264. var me = this;
  265. Cordova.exec(function(p_position, p_length) {
  266. // Update position & length for file
  267. me.position = p_position;
  268. me.length = p_length;
  269. // Update state
  270. me.readyState = FileSaver.DONE;
  271. // Dispatch missing events
  272. if( typeof me.onwrite === "function" ) me.onwrite( FileSaver.createEvent("write", me) );
  273. if( typeof me.onwriteend === "function" ) me.onwriteend( FileSaver.createEvent("writeend", me) );
  274. }, function( p_fileError, p_position, p_length ) {
  275. // Update position & length for file
  276. me.position = p_position;
  277. me.length = p_length;
  278. // Set error object & update state
  279. me.error = p_fileError;
  280. me.readyState = FileSaver.DONE;
  281. // Dispatch missing events
  282. if( typeof me.onerror === "function" ) me.onerror( FileSaver.createEvent("error", me) );
  283. if( typeof me.onwriteend === "function" ) me.onwriteend( FileSaver.createEvent("writeend", me) );
  284. }, "com.cordova.File", "truncate", [this.fullPath, size]);
  285. }
  286. /**
  287. * FileReader interface
  288. * http://www.w3.org/TR/FileAPI/#dfn-filereader
  289. */
  290. function FileReader() {
  291. }
  292. FileReader.EMPTY = 0;
  293. FileReader.LOADING = 1;
  294. FileReader.DONE = 2;
  295. FileReader.prototype.readyState = FileReader.EMPTY;
  296. FileReader.prototype.result = "";
  297. FileReader.prototype.error = new FileError();
  298. FileReader.prototype.onloadstart = null;
  299. FileReader.prototype.onprogress = null;
  300. FileReader.prototype.onload = null;
  301. FileReader.prototype.onabort = null;
  302. FileReader.prototype.onerror = null;
  303. FileReader.prototype.onloadend = null;
  304. FileReader.prototype.readAsArrayBuffer = function( file ) {
  305. }
  306. FileReader.prototype.readAsBinaryString = function( file ) {
  307. }
  308. FileReader.prototype.readAsText = function( file ) {
  309. this.readyState = FileReader.EMPTY;
  310. this.result = null;
  311. this.readyState = FileReader.LOADING;
  312. if( typeof this.onloadstart === "function" ) this.onloadstart( FileSaver.createEvent( "loadstart", this) );
  313. var me = this;
  314. // Lets read the file...
  315. Cordova.exec(function( p_data ) {
  316. me.readyState = FileReader.DONE;
  317. me.result = atob( p_data );
  318. if( typeof me.onload === "function" ) me.onload( FileSaver.createEvent( "load", me) );
  319. if( typeof me.onloadend === "function" ) me.onloadend( FileSaver.createEvent( "loadend", me) );
  320. }, function( p_fileError ) {
  321. me.readyState = FileReader.DONE;
  322. me.result = null;
  323. me.error = p_fileError;
  324. if( typeof me.onloadend === "function" ) me.onloadend( FileSaver.createEvent( "loadend", me) );
  325. if( typeof me.onerror === "function" ) me.onerror( FileSaver.createEvent( "error", me) );
  326. }, "com.cordova.File", "readAsText", [file.fullPath]);
  327. }
  328. FileReader.prototype.readAsDataURL = function( file ) {
  329. this.readyState = FileReader.EMPTY;
  330. this.result = null;
  331. this.readyState = FileReader.LOADING;
  332. if( typeof this.onloadstart === "function" ) this.onloadstart( FileSaver.createEvent( "loadstart", this) );
  333. var me = this;
  334. // Lets read the file...
  335. Cordova.exec(function( p_data ) {
  336. me.readyState = FileReader.DONE;
  337. me.result = p_data;
  338. if( typeof me.onloadend === "function" ) me.onloadend( FileSaver.createEvent( "loadend", me) );
  339. }, function( p_fileError ) {
  340. me.readyState = FileReader.DONE;
  341. me.result = null;
  342. me.error = p_fileError;
  343. if( typeof me.onloadend === "function" ) me.onloadend( FileSaver.createEvent( "loadend", me) );
  344. if( typeof me.onerror === "function" ) me.onerror( FileSaver.createEvent( "error", me) );
  345. }, "com.cordova.File", "readAsDataURL", [file.fullPath]);
  346. }
  347. FileReader.prototype.abort = function() {
  348. this.readyState = FileReader.DONE;
  349. this.result = null;
  350. this.error = FileError.cast( FileError.ABORT_ERR );
  351. if( typeof this.onerror === "function" ) this.onerror( FileSaver.createEvent( "error", me) ) ;
  352. if( typeof this.onabort === "function" ) this.onabort( FileSaver.createEvent( "abort", me) ) ;
  353. if( typeof this.onloadend === "function" ) this.onloadend( FileSaver.createEvent( "loadend", me) ) ;
  354. }
  355. /**
  356. * FileEntry interface
  357. * (derives from Entry)
  358. * http://www.w3.org/TR/file-system-api/#the-fileentry-interface
  359. */
  360. function FileEntry() {
  361. this.isFile = true;
  362. this.isDirectory = false;
  363. }
  364. FileEntry.cast = function( filename, path ) {
  365. var fe = new FileEntry();
  366. fe.name = filename;
  367. fe.fullPath = path;
  368. return fe;
  369. }
  370. FileEntry.prototype = new Entry();
  371. FileEntry.prototype.createWriter = function( successCallback, errorCallback ) {
  372. this.file( function(p_file) {
  373. successCallback(FileWriter.cast(p_file.fullPath, p_file.size));
  374. }, errorCallback);
  375. }
  376. FileEntry.prototype.file = function( successCallback, errorCallback ) {
  377. // Lets get the fileinfo
  378. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "file", [this.fullPath]);
  379. }
  380. FileEntry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
  381. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "copyFile", [this.fullPath, parent.fullPath, newName]);
  382. };
  383. FileEntry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
  384. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "moveFile", [this.fullPath, parent.fullPath, newName]);
  385. };
  386. /**
  387. * DirectoryReader interface
  388. * http://www.w3.org/TR/file-system-api/#the-directoryreader-interface
  389. */
  390. function DirectoryReader() {
  391. }
  392. DirectoryReader.cast = function( p_fullPath ) {
  393. var dr = new DirectoryReader();
  394. dr.fullPath = p_fullPath;
  395. return dr;
  396. }
  397. DirectoryReader.prototype.fullPath = ""; // Not W3C conform, but required
  398. DirectoryReader.prototype.readEntries = function( successCallback, errorCallback ) {
  399. // Get all entries for the directory
  400. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "readEntries", [this.fullPath]);
  401. }
  402. /**
  403. * DirectoryEntry interface
  404. * (derives from Entry)
  405. * http://www.w3.org/TR/file-system-api/#the-directoryentry-interface
  406. */
  407. function DirectoryEntry() {
  408. this.isFile = false;
  409. this.isDirectory = true;
  410. }
  411. DirectoryEntry.cast = function( dirname, path ) {
  412. var de = new DirectoryEntry();
  413. de.name = dirname;
  414. de.fullPath = path;
  415. return de;
  416. }
  417. DirectoryEntry.prototype = new Entry();
  418. DirectoryEntry.prototype.createReader = function() {
  419. return DirectoryReader.cast(this.fullPath);
  420. }
  421. DirectoryEntry.prototype.getFile = function( path, options, successCallback, errorCallback ) {
  422. var requestPath = path;
  423. // Check for a relative path
  424. if( requestPath.charAt(0) != '/' ) requestPath = this.fullPath + "/" + requestPath;
  425. // Lets get the file
  426. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "getFile", [requestPath, options]);
  427. }
  428. DirectoryEntry.prototype.getDirectory = function( path, options, successCallback, errorCallback ) {
  429. var requestPath = path;
  430. // Check for a relative path
  431. if( requestPath.charAt(0) != '/' ) requestPath = this.fullPath + "/" + requestPath;
  432. // Lets get the directory
  433. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "getDirectory", [requestPath, options]);
  434. }
  435. DirectoryEntry.prototype.removeRecursively = function( successCallback, errorCallback ) {
  436. // Remove the directory
  437. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "removeRecursively", [this.fullPath]);
  438. }
  439. DirectoryEntry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
  440. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "copyDir", [this.fullPath, parent.fullPath, newName]);
  441. };
  442. DirectoryEntry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
  443. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "moveDir", [this.fullPath, parent.fullPath, newName]);
  444. };
  445. /**
  446. * FileSystem interface
  447. * http://www.w3.org/TR/file-system-api/#the-filesystem-interface
  448. */
  449. function FileSystem() {
  450. }
  451. FileSystem.cast = function( fsname, dirname, path ) {
  452. var fs = new FileSystem();
  453. fs.name = fsname;
  454. fs.root = DirectoryEntry.cast(dirname, path);
  455. return fs;
  456. }
  457. FileSystem.prototype.name = "";
  458. FileSystem.prototype.root = null; // Should be a DirectoryEntry
  459. /**
  460. * LocalFileSystem interface
  461. * http://www.w3.org/TR/file-system-api/#using-localfilesystem
  462. */
  463. function LocalFileSystem() {
  464. }
  465. LocalFileSystem.TEMPORARY = 0;
  466. LocalFileSystem.PERSISTENT = 1;
  467. LocalFileSystem.prototype.requestFileSystem = function( type, size, successCallback, errorCallback ) {
  468. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "requestFileSystem", [type,size]);
  469. }
  470. LocalFileSystem.prototype.resolveLocalFileSystemURL = function( url, successCallback, errorCallback ) {
  471. Cordova.exec(successCallback, errorCallback, "com.cordova.File", "resolveLocalFileSystemURL", [url]);
  472. }
  473. /**
  474. * Let window implement the localfilesystem
  475. */
  476. Cordova.addConstructor( "com.cordova.File", function () {
  477. var localFileSystem = new LocalFileSystem();
  478. window.requestFileSystem = localFileSystem.requestFileSystem;
  479. window.resolveLocalFileSystemURI = localFileSystem.resolveLocalFileSystemURL;
  480. } );