2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 var privUtils_ = xwalk.utils;
18 var privilege_ = privUtils_.privilege;
19 var type_ = privUtils_.type;
20 var converter_ = privUtils_.converter;
21 var validator_ = privUtils_.validator;
22 var types_ = validator_.Types;
23 var native_ = new xwalk.utils.NativeManager(extension);
25 function SetReadOnlyProperty(obj, n, v) {
26 Object.defineProperty(obj, n, { value: v, writable: false });
29 var FileSystemStorageType = { INTERNAL: 'INTERNAL', EXTERNAL: 'EXTERNAL' };
31 var FileSystemStorageState = {
34 UNMOUNTABLE: 'UNMOUNTABLE'
37 var FileMode = { a: 'a', r: 'r', rw: 'rw', rwo: 'rwo', w: 'w' };
39 var BaseSeekPosition = { BEGIN: 'BEGIN', CURRENT: 'CURRENT', END: 'END' };
41 var tizen24home = '/opt/usr/media';
43 // this variable need to match same variable in
44 // common/filesystem/filesystem_provider_storage.cc
45 var kVirtualRootImages = 'images';
47 var commonFS_ = (function() {
48 var cacheReady = false;
49 var listenerRegistered = false;
50 var cacheVirtualToReal = {};
51 var cacheStorages = [];
52 var uriPrefix = 'file://';
53 // special condition for previous versions paths
54 // (global paths usage issue workaround)
55 var isAppForEarlierVersion = privUtils_.isAppVersionEarlierThan('3.0');
56 var homeDir = undefined;
58 function clearCache() {
59 cacheVirtualToReal = {};
64 // initalize home directory for correct mapping global paths from tizen 2.4
65 // (global paths usage issue workaround)
66 function initHomeDir(aPath) {
67 if (homeDir || !isAppForEarlierVersion) {
70 var imagesPath = cacheVirtualToReal[kVirtualRootImages].path;
72 if (imagesPath[imagesPath.length - 1] === '/') {
85 function initCache() {
89 var result = native_.callSync('FilesystemFetchAllStorages', {});
90 if (native_.isFailure(result)) {
91 throw native_.getErrorObject(result);
93 var virtualRoots = native_.getResultObject(result);
95 for (var i = 0; i < virtualRoots.length; ++i) {
96 cacheVirtualToReal[virtualRoots[i].name] = {
97 path: virtualRoots[i].path,
98 label: virtualRoots[i].name,
99 type: virtualRoots[i].type,
100 state: virtualRoots[i].state
103 // initalize home directory for correct mapping global paths from tizen 2.4
104 // (global paths usage issue workaround)
107 var result = native_.callSync('FileSystemManagerFetchStorages', {});
108 if (native_.isFailure(result)) {
109 throw native_.getErrorObject(result);
112 var storages = native_.getResultObject(result);
113 for (var i = 0; i < storages.length; ++i) {
115 path: storages[i].path,
116 label: storages[i].name,
117 type: storages[i].type,
118 state: storages[i].state,
119 storage_id: storages[i].storage_id
123 if (!listenerRegistered) {
125 tizen.filesystem.addStorageStateChangeListener(function() {
128 listenerRegistered = true;
131 'Failed to register storage change listener, ' +
132 'storage information may be corrupted: ' +
141 function setVirtualPath(name, path, type, state) {
143 cacheVirtualToReal[name] = { path: path, label: name, type: type, state: state };
144 console.log('name : ' + name + ', setVirtualPath : ' + cacheVirtualToReal[name]);
147 function mergeMultipleSlashes(str) {
148 var retStr = str.replace(/(^(file\:\/\/\/)|^(file\:\/\/)|\/)\/{0,}/g, '$1');
152 function removeDotsFromPath(str) {
153 if (str === undefined) {
157 var _pathTokens = str.split('/');
158 var _correctDir = [];
159 var _fileRealPath = _pathTokens[0];
160 _correctDir.push(_pathTokens[0]);
161 for (var i = 1; i < _pathTokens.length; ++i) {
162 if (_pathTokens[i] == '..') {
163 if (_fileRealPath == '') {
164 _fileRealPath = undefined;
167 var _lastDir = _correctDir.pop();
168 _fileRealPath = _fileRealPath.substring(
170 _fileRealPath.length - _lastDir.length - 1
172 } else if (_pathTokens[i] != '.') {
173 _fileRealPath += '/' + _pathTokens[i];
174 _correctDir.push(_pathTokens[i]);
177 return _fileRealPath;
180 function checkPathWithoutDots(aPath) {
181 if (-1 !== aPath.indexOf('/../')) {
184 if (-1 !== aPath.indexOf('/./')) {
187 // check if path ends with '/.' or '/..'
188 if (aPath.match(/\/\.\.?$/)) {
191 // check if path starts with './' or '../'
192 if (aPath.match(/^\.\.?\//)) {
198 function convertForEarlierVersionPath(aPath) {
199 if (isAppForEarlierVersion) {
200 if (aPath && aPath.indexOf(tizen24home) === 0) {
201 privUtils_.log('Converting 2.4 style path to 3.0 pattern');
202 aPath = homeDir + aPath.substr(tizen24home.length);
208 function toRealPath(aPath) {
209 var _fileRealPath = '';
211 aPath = mergeMultipleSlashes(aPath);
213 if (aPath.indexOf(uriPrefix) === 0) {
214 _fileRealPath = aPath.substr(uriPrefix.length);
215 } else if (aPath[0] !== '/') {
219 var _pathTokens = aPath.split('/');
221 if (cacheVirtualToReal[_pathTokens[0]]) {
222 _fileRealPath = cacheVirtualToReal[_pathTokens[0]].path;
223 for (var i = 1; i < _pathTokens.length; ++i) {
224 _fileRealPath += '/' + _pathTokens[i];
227 // If path token is not present in cache then it is invalid
228 _fileRealPath = undefined;
230 for (var j = 0; j < cacheStorages.length; ++j) {
231 if (cacheStorages[j].label === _pathTokens[0]) {
232 _fileRealPath = cacheStorages[j].path;
233 for (var i = 1; i < _pathTokens.length; ++i) {
234 _fileRealPath += '/' + _pathTokens[i];
241 _fileRealPath = aPath;
243 // removeDotsFromPath execution here, results with '.' and '..' beeing
244 // supported in paths, next methods throw an error when getting argument
245 // with '.' or '..' in it
246 // (see commonFS_.checkPathWithoutDots() method)
247 _fileRealPath = removeDotsFromPath(_fileRealPath);
248 // convert path to be compatibile with previous version of Tizen
249 // (global paths usage issue workaround)
250 _fileRealPath = convertForEarlierVersionPath(_fileRealPath);
251 // if path is valid try to cut last '/' if it is present
253 _fileRealPath = mergeMultipleSlashes(_fileRealPath);
255 return _fileRealPath;
258 function toVirtualPath(aPath) {
259 aPath = mergeMultipleSlashes(aPath);
260 var _virtualPath = aPath;
262 if (_virtualPath.indexOf(uriPrefix) === 0) {
263 _virtualPath = _virtualPath.substr(uriPrefix.length);
267 // find virtual root with longest path
269 var foundVirtualRoot;
270 var foundVirtualPath;
271 for (var virtual_root in cacheVirtualToReal) {
272 var real_root_path = cacheVirtualToReal[virtual_root].path;
273 if (_virtualPath.indexOf(real_root_path, 0) === 0) {
274 var currentLength = real_root_path.length;
275 if (currentLength > foundLength) {
276 foundLength = currentLength;
277 foundVirtualRoot = virtual_root;
278 foundVirtualPath = real_root_path;
282 if (foundLength != 0) {
283 return _virtualPath.replace(foundVirtualPath, foundVirtualRoot);
288 function getFileInfo(aStatObj, secondIter, aMode) {
291 _fileParentPath = '',
293 var aPath = toVirtualPath(aStatObj.path);
295 _result.readOnly = aStatObj.readOnly;
296 _result.isFile = aStatObj.isFile;
297 _result.isDirectory = aStatObj.isDirectory;
298 _result.created = new Date(aStatObj.ctime * 1000);
299 _result.modified = new Date(aStatObj.mtime * 1000);
300 _result.fullPath = aPath;
301 _result.fileSize = aStatObj.size;
302 _result.mode = aMode;
303 if (_result.isDirectory) {
305 _result.length = aStatObj.nlink;
310 _result.length = undefined;
313 _pathTokens = aPath.split('/');
314 if (_pathTokens.length > 1) {
315 var last = _pathTokens.length - 1;
317 if (_pathTokens[last] === '') {
318 // 'abc/d/e/' case with trailing '/' sign
319 last = _pathTokens.length - 2;
322 for (i = 0; i < last; ++i) {
323 _fileParentPath += _pathTokens[i] + '/';
326 _result.path = _fileParentPath;
327 _result.name = secondIter
329 : _pathTokens[last] + lastToken;
330 _result.parent = secondIter ? null : _fileParentPath;
333 _result.path = _pathTokens[last] + lastToken;
335 _result.parent = secondIter ? null : _fileParentPath;
338 _result.parent = null;
339 _result.path = aPath;
345 function isLocationAllowed(aPath) {
350 if (aPath.indexOf(cacheVirtualToReal.ringtones.path) === 0) {
353 if (aPath.indexOf(cacheVirtualToReal['wgt-package'].path) === 0) {
360 function toCanonicalPath(path) {
361 var result = native_.callSync('FileSystemManagerGetCanonicalPath', {
364 if (native_.isFailure(result)) {
365 throw native_.getErrorObject(result);
368 return native_.getResultObject(result);
371 function f_isSubDir(fullPathToCheck, fullPath) {
372 var fullCanonicalPathToCheck = toCanonicalPath(toRealPath(fullPathToCheck));
373 var fullCanonicalPath = toCanonicalPath(toRealPath(fullPath));
375 if (fullCanonicalPathToCheck === fullCanonicalPath) {
379 return fullCanonicalPathToCheck.indexOf(fullCanonicalPath) === 0;
382 function f_isCorrectRelativePath(relativePath) {
384 0 !== relativePath.indexOf('/') &&
385 0 !== relativePath.indexOf('\\') &&
386 -1 === relativePath.indexOf('?') &&
387 -1 === relativePath.indexOf('*') &&
388 -1 === relativePath.indexOf(':') &&
389 -1 === relativePath.indexOf('"') &&
390 -1 === relativePath.indexOf('<') &&
391 -1 === relativePath.indexOf('>')
395 function cloneStorage(storage) {
396 return { label: storage.label, type: storage.type, state: storage.state };
399 function getStorage(label) {
401 for (var i = 0; i < cacheStorages.length; ++i) {
402 if (cacheStorages[i].label === label) {
403 return cloneStorage(cacheStorages[i]);
407 for (var key in cacheVirtualToReal) {
408 if (cacheVirtualToReal.hasOwnProperty(key)) {
409 if (cacheVirtualToReal[key].label === label) {
410 return cloneStorage(cacheVirtualToReal[key]);
418 function getAllStorages() {
421 for (var i = 0; i < cacheStorages.length; ++i) {
422 ret.push(cloneStorage(cacheStorages[i]));
425 for (var key in cacheVirtualToReal) {
426 if (cacheVirtualToReal.hasOwnProperty(key)) {
428 for (var i = 0; i < cacheStorages.length; ++i) {
429 if (key === ret[i].label) {
434 if (found === false) {
435 ret.push(cloneStorage(cacheVirtualToReal[key]));
444 clearCache: clearCache,
445 checkPathWithoutDots: checkPathWithoutDots,
446 toRealPath: toRealPath,
447 toVirtualPath: toVirtualPath,
448 getFileInfo: getFileInfo,
449 isLocationAllowed: isLocationAllowed,
450 f_isSubDir: f_isSubDir,
451 f_isCorrectRelativePath: f_isCorrectRelativePath,
452 getStorage: getStorage,
453 getAllStorages: getAllStorages,
454 mergeMultipleSlashes: mergeMultipleSlashes,
455 setVirtualPath : setVirtualPath