mirror of
https://scm.univ-tours.fr/22107988t/rappaurio-sae501_502.git
synced 2025-08-28 20:25:58 +02:00
Revert "permet l'ajout des frameworks et des routes"
This reverts commit 361112699c
This commit is contained in:
2772
app/node_modules/cejs/application/storage/EPUB.js
generated
vendored
2772
app/node_modules/cejs/application/storage/EPUB.js
generated
vendored
File diff suppressed because it is too large
Load Diff
1087
app/node_modules/cejs/application/storage/archive.js
generated
vendored
1087
app/node_modules/cejs/application/storage/archive.js
generated
vendored
File diff suppressed because it is too large
Load Diff
967
app/node_modules/cejs/application/storage/file.js
generated
vendored
967
app/node_modules/cejs/application/storage/file.js
generated
vendored
@@ -1,967 +0,0 @@
|
||||
/**
|
||||
* @name CeL file function
|
||||
* @fileoverview 本檔案包含了 file functions。
|
||||
* @since
|
||||
* @see <a href="http://dev.w3.org/2006/webapi/FileAPI/" accessdate="2010/6/20
|
||||
* 14:49">File API</a>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
// 'use asm';
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
// 不採用 if 陳述式,可以避免 Eclipse JSDoc 與 format 多縮排一層。
|
||||
typeof CeL === 'function' && CeL.run({
|
||||
// module name
|
||||
name : 'application.storage.file',
|
||||
|
||||
// Math.log2()
|
||||
require : 'data.code.compatibility.'
|
||||
// .chunk()
|
||||
+ '|data.native.'
|
||||
// MIME_of()
|
||||
// +'|application.net.MIME.'
|
||||
,
|
||||
|
||||
// 設定不匯出的子函式。
|
||||
// no_extend : '*',
|
||||
|
||||
// 為了方便格式化程式碼,因此將 module 函式主體另外抽出。
|
||||
code : module_code
|
||||
});
|
||||
|
||||
function module_code(library_namespace) {
|
||||
|
||||
/**
|
||||
* null module constructor
|
||||
*
|
||||
* @class 檔案操作相關之 function。
|
||||
*/
|
||||
var _// JSDT:_module_
|
||||
= function() {
|
||||
// null module constructor
|
||||
};
|
||||
|
||||
/**
|
||||
* for JSDT: 有 prototype 才會將之當作 Class
|
||||
*/
|
||||
_// JSDT:_module_
|
||||
.prototype = {};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// path處理
|
||||
|
||||
// @see CeL.simplify_path()
|
||||
|
||||
// 去除hostname等,如輸入http://hostname/aaa/bbb/ccc得到aaa/bbb/ccc/
|
||||
// 假如輸入的格式不正確,可能得出不預期的回應值!
|
||||
/*
|
||||
* 對library_namespace.env.path_separator.length>1的情形(嚴謹)
|
||||
*/
|
||||
function deprecated_getPathOnly(p) {
|
||||
// discard hash & search
|
||||
var i = p.lastIndexOf('?'), j = p.lastIndexOf('#'), dirSpL = library_namespace.env.path_separator.length;
|
||||
if (i === -1)
|
||||
i = j;
|
||||
else if (j !== -1 && i > j)
|
||||
i = j;
|
||||
if (i !== -1)
|
||||
p = p.slice(0, i);
|
||||
// 去除http://hostname/等
|
||||
if (p.slice(0, 5) === 'file:///')
|
||||
// 對file:///特別處理!
|
||||
p = p.substr('file:///'.length);
|
||||
else if ((i = p.indexOf(':' + library_namespace.env.path_separator
|
||||
//
|
||||
+ library_namespace.env.path_separator)) !== -1
|
||||
//
|
||||
&& (i = p.indexOf(library_namespace.env.path_separator, i + (':'
|
||||
//
|
||||
+ library_namespace.env.path_separator
|
||||
//
|
||||
+ library_namespace.env.path_separator).length)) !== -1)
|
||||
// http://hostname/path→path
|
||||
p = p.substr(i + dirSpL);
|
||||
else if (p.slice(0, dirSpL) === library_namespace.env.path_separator)
|
||||
// /usr/local/→usr/local/
|
||||
if (p.substr(dirSpL, dirSpL) !== library_namespace.env.path_separator)
|
||||
p = p.substr(dirSpL);
|
||||
else if ((i = p.indexOf(library_namespace.env.path_separator,
|
||||
dirSpL + dirSpL)) > dirSpL + dirSpL)
|
||||
// 去除\\hostname\
|
||||
p = p.substr(i + dirSpL);
|
||||
else if (i !== -1)
|
||||
// \\\zzzz的情形:不合法的路徑
|
||||
throw new Error(1, 'illegal path:' + p);
|
||||
return p;
|
||||
}
|
||||
|
||||
// 對library_namespace.env.path_separator.length==1的情形簡化
|
||||
// getPathOnly[generateCode.dLK]='library_namespace.env.path_separator';//,isFile
|
||||
function getPathOnly(p) {
|
||||
// discard hash & search
|
||||
var i = p.lastIndexOf('?'), j = p.lastIndexOf('#');
|
||||
if (i === -1)
|
||||
i = j;
|
||||
else if (j !== -1 && i > j)
|
||||
i = j;
|
||||
if (i !== -1)
|
||||
p = p.slice(0, i);
|
||||
// 去除http://hostname/等
|
||||
if (p.slice(0, 8) === 'file:///')
|
||||
// 對file:///(應該是file:)特別處理!
|
||||
p = p.substr(8);
|
||||
else if ((i = p.indexOf(':' + library_namespace.env.path_separator
|
||||
+ library_namespace.env.path_separator)) !== -1
|
||||
&& (i = p.indexOf(library_namespace.env.path_separator, i + 3) !== -1))
|
||||
// http://hostname/path→path
|
||||
p = p.substr(i + 1);
|
||||
else if (p.charAt(0) === library_namespace.env.path_separator)
|
||||
// /usr/local/→usr/local/
|
||||
if (p.charAt(1) !== library_namespace.env.path_separator)
|
||||
p = p.substr(1);
|
||||
else if ((i = p.indexOf(library_namespace.env.path_separator, 2)) > 2)
|
||||
// 去除\\hostname\ 不去除:.replace(/[^\\]+$/,'')
|
||||
p = p.substr(i + 1);
|
||||
else if (i !== -1)
|
||||
// \\\zzzz的情形:不合法的路徑
|
||||
throw new Error(1, 'illegal path:' + p);
|
||||
// !isWeb()&&~
|
||||
if (typeof isFile === 'function' && isFile(p))
|
||||
p = p.replace(new RegExp(
|
||||
library_namespace.env.path_separator_pattern + '[^'
|
||||
+ library_namespace.env.path_separator_pattern
|
||||
+ ']+$'), library_namespace.env.path_separator);
|
||||
return p;
|
||||
}
|
||||
|
||||
var path_separator_candidates = [ '/', '\\' ], path_separator_candidates_length = path_separator_candidates.length,
|
||||
// path_separator_candidates_Regex
|
||||
// =new RegExp(path_separator_candidates.join(''), 'g'),
|
||||
path_separator_RegExp;
|
||||
|
||||
_// JSDT:_module_
|
||||
.guess_path_separator = function(path) {
|
||||
if (typeof path !== 'string' || !path)
|
||||
return;
|
||||
|
||||
var count = 0, candidate, i, m;
|
||||
|
||||
if (!path_separator_RegExp)
|
||||
// 初始設定
|
||||
for (path_separator_RegExp = [], i = 0; i < path_separator_candidates_length; i++)
|
||||
path_separator_RegExp[i] = new RegExp('\\'
|
||||
+ path_separator_candidates[i], 'g');
|
||||
|
||||
// 偵測最符合的
|
||||
for (i = 0; i < path_separator_candidates_length; i++) {
|
||||
m = path.match(path_separator_RegExp[i]);
|
||||
if (m && m.length > count)
|
||||
count = m.length, candidate = path_separator_candidates[i];
|
||||
}
|
||||
|
||||
return candidate || library_namespace.env.path_separator;
|
||||
};
|
||||
|
||||
_// JSDT:_module_
|
||||
.
|
||||
/**
|
||||
* 取得 base_path 相對於 working_path 的路徑。
|
||||
* <p>
|
||||
* 當前處於 working_path,欲取得 base_path 下所指到的 resource_file_path,可使用: <code>
|
||||
* get_relative_path(base_path, working_path) + resource_file_path
|
||||
* </code>
|
||||
* </p>
|
||||
* TODO: 找出最大連續相同路徑。
|
||||
*
|
||||
* @example <code>
|
||||
|
||||
CeL.run('application.storage.file',function(){CeL.set_debug(2);CeL.log(CeL.get_relative_path('a/b/same/d/file','same/e/'));});
|
||||
|
||||
CeL.set_debug(2);CeL.get_relative_path('a/b/same/d/f/file','e/r/t/same/e/',1);
|
||||
|
||||
base_path = CeL.get_relative_path('kanashimi/www/cgi-bin/game/');
|
||||
|
||||
// 想要保持 Protocol,但卻是不同機器時。 <a href="http://nedbatchelder.com/blog/200710.html#e20071017T215538" accessdate="2011/8/28 0:18" title="Ned Batchelder: October 2007">Http-https transitions and relative URLs</a>
|
||||
CeL.get_relative_path('cgi-bin/game/photo/','//lyrics.meicho.com.tw/game/game.pl?seg=diary21',1);
|
||||
|
||||
* </code>
|
||||
*
|
||||
* @param {String}
|
||||
* base_path 給定 base path 的範本結構, base_path_structure.
|
||||
* @param {String}
|
||||
* working_path 當前處於 working_path.
|
||||
* @param {Boolean}
|
||||
* get_full_path 藉由 working_path 推測 base path 的 full path.
|
||||
* 否則回傳相對路徑(relative path),會增加 ../ 等。
|
||||
* @returns {String} 推測的 base path 相對於 working_path 的 path.
|
||||
*
|
||||
* @since 2003/10/1 15:57
|
||||
* @since 2011/8/28 00:16:40
|
||||
* @requres getPathOnly,library_namespace.env.path_separator,library_namespace.env.path_separator_pattern
|
||||
* @_memberOf _module_
|
||||
*/
|
||||
get_relative_path = function(base_path, working_path, get_full_path) {
|
||||
|
||||
library_namespace.debug('phase 1: 簡化並審查 path<br />base_path ['
|
||||
+ base_path + ']<br />working_path [' + working_path + ']', 2,
|
||||
'get_relative_path');
|
||||
|
||||
if (!working_path)
|
||||
working_path = library_namespace.get_script_base_path();
|
||||
else
|
||||
working_path = library_namespace.simplify_path(working_path);
|
||||
|
||||
if (!working_path)
|
||||
return;
|
||||
|
||||
if (!base_path)
|
||||
base_path = (library_namespace.is_WWW() ? location.href
|
||||
: typeof WshShell === 'object' ? WshShell.CurrentDirectory
|
||||
: typeof WScript === 'object' ? WScript.ScriptFullName
|
||||
// TODO: path_separator_candidates
|
||||
: '').replace(/[^\/\\]+$/, '');
|
||||
else
|
||||
base_path = library_namespace.simplify_path(base_path);
|
||||
|
||||
if (!base_path
|
||||
// base_path 需要是絕對路徑
|
||||
// || !is_absolute_path(base_path)
|
||||
)
|
||||
return working_path;
|
||||
|
||||
library_namespace
|
||||
.debug(
|
||||
'phase 2: 將 path 分解成 Array,從尾至頭比對,以 base_path 為基準,找尋 working_path 是否有相同的目錄名。<br />base_path ['
|
||||
+ base_path
|
||||
+ ']<br />working_path ['
|
||||
+ working_path + ']', 2, 'get_relative_path');
|
||||
|
||||
// 在 IE 或 HTA 中,path_separator === '\\' 但輸入的 path 為 '/';
|
||||
// 甚至於 working_path, base_path 兩者可能不同。
|
||||
var path_separator =
|
||||
// library_namespace.env.path_separator
|
||||
_.guess_path_separator(working_path);
|
||||
|
||||
working_path = working_path.split(path_separator);
|
||||
if (!working_path.at(-1))
|
||||
// 防止輸入 a/b/c/ 而非 a/b/c 的情況。
|
||||
working_path.pop();
|
||||
base_path = base_path.split(_.guess_path_separator(base_path));
|
||||
// alert(working_path + '\n' + base_path);
|
||||
|
||||
var file_name = base_path.pop();
|
||||
|
||||
var index_base_path = base_path.length, index_working_path, working_path_length = working_path.length, directory, not_found = true;
|
||||
for (; index_base_path && not_found;)
|
||||
// 取得第 index_base_path 識別用目錄名
|
||||
if (directory = base_path[--index_base_path]) {
|
||||
for (index_working_path = working_path_length; index_working_path;)
|
||||
if (directory === working_path[--index_working_path]) {
|
||||
not_found = false;
|
||||
// 第一個找到就 break 了。
|
||||
// TODO: 找出最大連續相同路徑。
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
library_namespace.debug('phase 3: '
|
||||
+ (not_found ? +'找不到' : '找到 index: base_path['
|
||||
+ index_base_path + '], working_path['
|
||||
+ index_working_path + ']'), 2, 'get_relative_path');
|
||||
if (not_found)
|
||||
library_namespace.debug("Can't find base directory of this file!\n"
|
||||
+ working_path + '\n\nTreat base directory as:\n'
|
||||
+ base_path, 2, 'get_relative_path'),
|
||||
directory = get_full_path ? working_path.concat(base_path)
|
||||
: base_path;
|
||||
else {
|
||||
if (get_full_path)
|
||||
directory = working_path.slice(0, index_working_path + 1);
|
||||
else {
|
||||
directory = [];
|
||||
for (var i = index_working_path + 1; i < working_path_length; i++)
|
||||
directory.push('..');
|
||||
}
|
||||
|
||||
// directory.append(base_path, index_base_path + 1);
|
||||
directory = directory.concat(base_path.slice(index_base_path + 1));
|
||||
}
|
||||
|
||||
directory.push(file_name);
|
||||
return directory.join(path_separator);
|
||||
};
|
||||
|
||||
_// JSDT:_module_
|
||||
.
|
||||
/**
|
||||
* cf: get_file_name(), parse_URL
|
||||
*
|
||||
* @param {String}
|
||||
* path path name
|
||||
* @return
|
||||
* @_memberOf _module_
|
||||
*/
|
||||
parse_path = function(path) {
|
||||
if (typeof path !== 'string' || !path)
|
||||
return;
|
||||
|
||||
var path_data = {
|
||||
input_data : path
|
||||
}, m;
|
||||
|
||||
if (m = path.match(/^(([A-Za-z]):\\)?(([^\\]+\\)*)([^\\]*)?$/)) {
|
||||
path_data.is_absolute = !!(path_data.drive = m[2]);
|
||||
path_data.path_name = m[3];
|
||||
path_data.file_name = m[5];
|
||||
library_namespace.debug('type: Windows/MS-DOS file path', 2);
|
||||
} else if (m = path
|
||||
.match(/^file:\/\/\/([A-Za-z]):\/(([^\/]+\/)*)([^\/]*)?$/)) {
|
||||
path_data.is_absolute = true;
|
||||
path_data.drive = m[1];
|
||||
path_data.path_name = m[2];
|
||||
path_data.file_name = m[4];
|
||||
library_namespace.debug(
|
||||
'type: URL of Windows/MS-DOS local file path', 2);
|
||||
} else if (m = path.match(/^((\/)?([^\/]+\/)*)([^\/]*)?$/)) {
|
||||
path_data.is_absolute = !!m[2];
|
||||
path_data.path_name = m[1];
|
||||
path_data.file_name = m[4];
|
||||
library_namespace.debug('type: UNIX file path', 2);
|
||||
} else {
|
||||
library_namespace.debug('Failure to parse [' + path + ']');
|
||||
}
|
||||
|
||||
// 正規化
|
||||
path_data.path_name = path_data.path_name.replace(/[\/\\]/g,
|
||||
library_namespace.env.path_separator);
|
||||
|
||||
m = path_data.file_name.match(/^(.*?)(\.([^.]*))?$/);
|
||||
path_data.name = m[1];
|
||||
path_data.extension = m[3];
|
||||
|
||||
path_data.path = path_data.path_name + path_data.file_name;
|
||||
path_data.location = path_data.drive + ':\\' + path_data.path;
|
||||
path_data.directory = path_data.drive + ':\\' + path_data.path_name;
|
||||
|
||||
return path_data;
|
||||
};
|
||||
|
||||
_// JSDT:_module_
|
||||
.
|
||||
/**
|
||||
* Test if local path is absolute or relative path, not very good solution.
|
||||
* TODO: test FULL path.
|
||||
*
|
||||
* @param {String}
|
||||
* local path
|
||||
* @return
|
||||
* @requires library_namespace.env.path_separator,library_namespace.env.path_separator_pattern
|
||||
* @_memberOf _module_
|
||||
*/
|
||||
is_absolute_path = function(path) {
|
||||
// alert(typeof path + '\n' + path);
|
||||
return /^(\/|[A-Z]+:([\\\/]|$)|\\\\[^\\])/i.test(path);
|
||||
|
||||
return path
|
||||
&& (library_namespace.env.path_separator === '/'
|
||||
&& path.charAt(0) === library_namespace.env.path_separator || new RegExp(
|
||||
'^(\\\\|[A-Za-z]+:)'
|
||||
+ library_namespace.env.path_separator_pattern)
|
||||
.test(path))
|
||||
// ?true:false
|
||||
;
|
||||
};
|
||||
|
||||
// 轉成path(加'\')
|
||||
function turnToPath(p) {
|
||||
return p ? p + (p.slice(-1) == '\\' ? '' : '\\') : '';
|
||||
}
|
||||
// 僅取得path部分(包括 library_namespace.env.path_separator),不包括檔名。
|
||||
// getFilePath[generateCode.dLK]='library_namespace.env.path_separator';
|
||||
function getFilePath(p) {
|
||||
var i = p.lastIndexOf(library_namespace.env.path_separator);
|
||||
if (i == -1)
|
||||
p += library_namespace.env.path_separator; // 相對路徑?
|
||||
else if (i < p.length - 1)
|
||||
p = p.slice(0, i + 1); // 取得path部分
|
||||
return p;
|
||||
}
|
||||
|
||||
// get_file_path[generateCode.dLK]='is_absolute_path,getPathOnly,get_relative_path';
|
||||
/**
|
||||
* 傳回包括檔名之絕對/相對路徑,假如是資料夾,也會回傳資料夾路徑。可包含'.','..'等 the return value include ? #
|
||||
* of URI<br />
|
||||
* 在Win/DOS下輸入'\'..會加上base driver。<br />
|
||||
* 若只要相對路徑,可用 library_namespace.simplify_path()。取得如'..\out'的絕對路徑可用
|
||||
* get_file_path('../out',1)
|
||||
*
|
||||
* @param {String}path
|
||||
* 路徑
|
||||
* @param {Number}[mode]
|
||||
* 0:傳回auto(維持原狀), 1:傳回絕對路徑, 2:傳回相對路徑。
|
||||
* @param {String}[base_path]
|
||||
* base path
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function get_file_path(path, mode, base_path) {
|
||||
if (!path)
|
||||
return '';
|
||||
|
||||
// old, deprecated:
|
||||
if (false)
|
||||
return (path.lastIndexOf('\\') === -1
|
||||
&& path.lastIndexOf('/') === -1 ?
|
||||
// get_file_object
|
||||
getFolder(getScriptFullName()) : '')
|
||||
+ path;
|
||||
|
||||
var matched;
|
||||
if (path.charAt(0) === '\\'
|
||||
&& (matched = get_relative_path(base_path).match(
|
||||
/^(\\\\|[A-Z]:)/i)))
|
||||
path = matched[1] + path;
|
||||
|
||||
path = library_namespace.simplify_path(path);
|
||||
if (mode === 1) {
|
||||
// 當為相對路徑時前置 base path。
|
||||
if (!is_absolute_path(path))
|
||||
path = library_namespace
|
||||
.simplify_path((base_path ? getPathOnly(base_path)
|
||||
: get_relative_path())
|
||||
+ path);
|
||||
} else if (mode === 2 && is_absolute_path(path))
|
||||
path = get_relative_path(base_path, path, 1);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
_.get_file_path = get_file_path;
|
||||
|
||||
// get_file_name[generateCode.dLK]='get_file_path,library_namespace.env.path_separator';
|
||||
/**
|
||||
* 傳回檔名部分,the return value include ? # of URI<br />
|
||||
*
|
||||
* @param {String}path
|
||||
* 路徑
|
||||
* @param {String}[base_path]
|
||||
* base path
|
||||
* @param {Number}[mode]
|
||||
* 0:檔名,1:(當輸入為不可信賴的字串時)去除檔名中不允許的字元,割掉? #等
|
||||
*
|
||||
* @returns 檔名部分
|
||||
*/
|
||||
function get_file_name(path, base_path, mode) {
|
||||
path = get_file_path(path, 0, base_path);
|
||||
|
||||
// 比起(mode=path.lastIndexOf(library_namespace.env.path_separator))==-1?path:path.substr(mode+1);此法比較直接,不過感覺多一道手續…
|
||||
path = path
|
||||
// 不能用.substr(path.lastIndexOf(library_namespace.env.path_separator))+library_namespace.env.path_separator,因為path.lastIndexOf(library_namespace.env.path_separator)可能==-1
|
||||
.slice(path.lastIndexOf(library_namespace.env.path_separator) + 1);
|
||||
|
||||
if (mode) {
|
||||
if (path.match(/[#?]/))
|
||||
path = path.substr(0, RegExp.lastIndex - 1);
|
||||
// 處理 illegal file name. 去除檔名中不被允許的字元。cf.
|
||||
// application.net.to_file_name()
|
||||
// [ \.]
|
||||
path = path.replace(/[\\\/:*?"<>|]/g, '_');
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
_.get_file_name = get_file_name;
|
||||
|
||||
// 傳回檔案/資料夾物件
|
||||
// FileSystemObjectのバグ(制限)で、環境によっては2G以上の領域を認識できません。WSH5.6ではこのバグが修正されています。
|
||||
// get_file_object[generateCode.dLK]='isFile,parse_shortcut,get_file_path,library_namespace.env.path_separator,getFolder,initialization_WScript_Objects';
|
||||
// path,mode=0:auto(維持原狀),1:絕對路徑,2:相對路徑,base
|
||||
function get_file_object(p, m, bp) {
|
||||
// path
|
||||
try {
|
||||
return isFile(p = parse_shortcut(get_file_path(p, m, bp), 1)) ? fso
|
||||
.GetFile(p) : fso.GetFolder(p);
|
||||
} catch (e) {
|
||||
return p.indexOf(library_namespace.env.path_separator) === -1 ? get_file_object(
|
||||
getFolder(WScript.ScriptFullName) + p, m, bp)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
// alert(get_file_path('\program files\\xxx\\xxx.exe',2));
|
||||
|
||||
_// JSDT:_module_
|
||||
.
|
||||
/**
|
||||
* 取得 file 之 file name extension(副檔名).
|
||||
*
|
||||
* @example <code>
|
||||
* // get 'htm'.
|
||||
* get_file_extension('test.htm');
|
||||
* </code>
|
||||
* @param {String}file_name
|
||||
* 檔案名稱
|
||||
* @returns {String} file name extension(副檔名)
|
||||
*/
|
||||
get_file_extension = function(file_name) {
|
||||
var m = ('' + file_name).match(/\.([^.]*)$/);
|
||||
return m ? m[1] : '';
|
||||
};
|
||||
|
||||
_// JSDT:_module_
|
||||
.
|
||||
/**
|
||||
* 設定/更改 file 之 extension(副檔名).
|
||||
*
|
||||
* @example <code>
|
||||
* // get 'test.html'.
|
||||
* set_file_extension('test.htm','html');
|
||||
* </code>
|
||||
* @param {String}file_name
|
||||
* 檔案名稱
|
||||
* @param {String}change_to
|
||||
* 更改成 change_to
|
||||
* @returns {String} 更改 extension 後之 file name.
|
||||
*/
|
||||
set_file_extension = function(file_name, change_to) {
|
||||
if (change_to)
|
||||
file_name = ('' + file_name).replace(/\.[^.]*$/, '') + '.'
|
||||
+ change_to;
|
||||
return file_name;
|
||||
};
|
||||
|
||||
// http://stackoverflow.com/questions/1547899/which-characters-make-a-url-invalid
|
||||
// URL_encoded('http://authority.ddbc.edu.tw/time/search.php?chk=nextLevel&julianSwitch=off&dpk=新羅')
|
||||
// === false;
|
||||
function URL_encoded(URL) {
|
||||
return /^(?:https?|ftp):\/\/(?:[a-zA-Z0-9\-._~\/?#\[\]@!$&'()*+,;=]|%[a-fA-Z0-9]{2})+$/
|
||||
.test(URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* cache 相關函數:
|
||||
*
|
||||
* @see application.storage.file.get_cache_file
|
||||
* application.OS.Windows.file.cacher
|
||||
* application.net.Ajax.get_URL_cache application.net.wiki
|
||||
* wiki_API.cache() CeL.wiki.cache()
|
||||
*/
|
||||
|
||||
var get_file = library_namespace.get_file,
|
||||
// @see https://nodejs.org/api/fs.html
|
||||
write_file = library_namespace.platform.nodejs
|
||||
&& require('fs').writeFileSync;
|
||||
|
||||
/**
|
||||
* 檔案 cache 作業操作之輔助套裝函數。
|
||||
*
|
||||
* @param {String|Object}URL
|
||||
* 請求目的URL or options
|
||||
* @param {Object}[options]
|
||||
* 附加參數/設定特殊功能與選項
|
||||
*
|
||||
* @returns cache data
|
||||
*/
|
||||
function cache_file(URL, options) {
|
||||
|
||||
// 前置處理。
|
||||
if (!library_namespace.is_Object(options))
|
||||
options = Object.create(null);
|
||||
|
||||
// 決定將 URL 存放至何處(存成哪個檔案)。
|
||||
var file_path = options.file_name || get_file_name;
|
||||
if (typeof file_path === 'function')
|
||||
file_path = file_path(URL);
|
||||
|
||||
if (options.base_path)
|
||||
file_path = options.base_path + file_path;
|
||||
|
||||
if (!URL_encoded(URL))
|
||||
URL = encodeURI(URL);
|
||||
|
||||
var file_encoding = options.file_encoding || options.encoding
|
||||
|| cache_file.encoding, data;
|
||||
|
||||
if (!options.force) {
|
||||
try {
|
||||
// get cache file
|
||||
data = get_file(file_path, file_encoding);
|
||||
// data = read_file(file_name, encoding);
|
||||
} catch (e) {
|
||||
library_namespace.debug('嘗試讀取 cache file [' + file_path
|
||||
+ '] 失敗。', 1, 'cache_file');
|
||||
}
|
||||
}
|
||||
|
||||
if (data === undefined) {
|
||||
library_namespace.debug('重新取得 [' + URL + ']。', 1, 'cache_file');
|
||||
if ((data = get_file(URL, options.encoding))
|
||||
// 預防此時尚未 loaded.
|
||||
&& (write_file || (write_file = library_namespace.write_file))) {
|
||||
if (/\.s?html?$/i.test(file_path)) {
|
||||
// 插入網域識別標記之網頁註解 MOTW (Mark of the Web)。
|
||||
// e.g., about:internet
|
||||
// http://msdn.microsoft.com/en-us/library/ms537628(v=vs.85).aspx
|
||||
var MOTW = String(URL.length), line_separator = data
|
||||
.match(/\r?\n/);
|
||||
MOTW = '<!-- saved from url=('
|
||||
+ '0000'.slice(MOTW.length)
|
||||
+ MOTW
|
||||
+ ')'
|
||||
+ URL
|
||||
+ ' -->'
|
||||
+ (line_separator ? line_separator[0]
|
||||
: library_namespace.env.line_separator);
|
||||
data = MOTW + data;
|
||||
}
|
||||
library_namespace.debug('write to [' + file_path + ']');
|
||||
write_file(file_path, data, file_encoding);
|
||||
}
|
||||
}
|
||||
|
||||
if (/\.json$/i.test(file_path) && JSON.parse)
|
||||
data = JSON.parse(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
_.cache_file = cache_file;
|
||||
|
||||
/** {String}預設 file encoding for fs of write_file。 */
|
||||
cache_file.encoding = library_namespace.platform.nodejs ? 'utf8' : 'UTF-8';
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// 可以參考 CeL.application.net.MIME
|
||||
// https://github.com/sindresorhus/file-type/blob/master/index.js
|
||||
|
||||
function to_magic_array(header) {
|
||||
return header.split('').map(function(char) {
|
||||
return char.charCodeAt(0).toString(16);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function uint32_from_buffer(buffer, byteOffset) {
|
||||
// NG: (new Uint32Array(buffer, 4, 4))[0]
|
||||
byteOffset |= 0;
|
||||
return (((buffer[byteOffset + 3] * 256) + buffer[byteOffset + 2]) * 256 + buffer[byteOffset + 1])
|
||||
* 256 + buffer[byteOffset];
|
||||
}
|
||||
|
||||
// Magic_number[type]={Object}data
|
||||
var Magic_number = {
|
||||
// text
|
||||
html : {
|
||||
// other file extensions
|
||||
extensions : [ 'htm', 'shtml' ],
|
||||
min_size : 52
|
||||
},
|
||||
pdf : {
|
||||
magic : to_magic_array('%PDF'),
|
||||
min_size : 800
|
||||
},
|
||||
|
||||
// image
|
||||
gif : {
|
||||
// Header: GIF89a
|
||||
magic : to_magic_array('GIF89a'),
|
||||
// end of image data + GIF file terminator
|
||||
eof : '00 3B',
|
||||
min_size : 800
|
||||
},
|
||||
gif87a : {
|
||||
// Header: GIF87a
|
||||
magic : to_magic_array('GIF87a'),
|
||||
// end of image data + GIF file terminator
|
||||
eof : '00 3B',
|
||||
extensions : [ 'gif' ],
|
||||
extensions_without_type : true,
|
||||
min_size : 800
|
||||
},
|
||||
// PNG圖像
|
||||
// https://www.w3.org/TR/PNG/#11IEND
|
||||
// https://en.wikipedia.org/wiki/PNG
|
||||
// https://en.wikipedia.org/wiki/APNG
|
||||
png : {
|
||||
// IHDR數據塊: ‰PNG....
|
||||
magic : '89 50 4E 47 0D 0A 1A 0A',
|
||||
// http://blog.xuite.net/tzeng015/twblog/113272013-5.2.3+分析PNG圖像文件結構(6)
|
||||
// IEND數據塊: IEND®B`‚...
|
||||
eof : '00 00 00 00 49 45 4E 44 AE 42 60 82',
|
||||
min_size : 100
|
||||
},
|
||||
jpg : {
|
||||
// ÿØ
|
||||
magic : 'FF D8 FF',
|
||||
// http://stackoverflow.com/questions/4585527/detect-eof-for-jpg-images
|
||||
// check EOI, End Of Image mark of .jpeg: ÿÙ
|
||||
eof : 'FF D9',
|
||||
// other file extensions
|
||||
extensions : [ 'jpeg' ],
|
||||
min_size : 3e3
|
||||
},
|
||||
tif : {
|
||||
// II*.
|
||||
magic : '49 49 2A 00',
|
||||
// other file extensions
|
||||
extensions : [ 'tiff' ],
|
||||
min_size : 3e3
|
||||
},
|
||||
ico : {
|
||||
magic : '00 00 01 00',
|
||||
min_size : 50
|
||||
},
|
||||
|
||||
// https://www.garykessler.net/library/file_sigs.html
|
||||
// archives
|
||||
zip : {
|
||||
// PK.. PKZIP壓縮軟體的發明者 Phil Katz,ZIP原名Deflate
|
||||
magic : '50 4B 03 04',
|
||||
min_size : 100
|
||||
},
|
||||
'7z' : {
|
||||
// 7z¼¯'.
|
||||
magic : '37 7A BC AF 27 1C',
|
||||
min_size : 100
|
||||
},
|
||||
rar : {
|
||||
// Rar!...
|
||||
magic : '52 61 72 21 1A 07 00',
|
||||
min_size : 100
|
||||
},
|
||||
rar5 : {
|
||||
// Rar!....
|
||||
magic : '52 61 72 21 1A 07 01 00',
|
||||
min_size : 100
|
||||
},
|
||||
|
||||
// sound
|
||||
mp3 : {
|
||||
// 49 44 33 04 00
|
||||
magic : to_magic_array('ID3'),
|
||||
min_size : 100
|
||||
},
|
||||
|
||||
// video
|
||||
mpg : {
|
||||
// 00 00 01 Bx
|
||||
magic : '00 00 01',
|
||||
eof : '00 00 01 B7',
|
||||
extensions : [ 'mpeg' ],
|
||||
min_size : 1e3
|
||||
},
|
||||
|
||||
// RIFF types: 會自動判別RIFF標頭,不用特別指定。
|
||||
wav : {
|
||||
min_size : 100,
|
||||
verify : function(file_contents) {
|
||||
// TODO: file_contents.slice(4, 8): File Size (little endian)
|
||||
|
||||
return file_contents.slice(8, 15).toString() === 'WAVEfmt';
|
||||
}
|
||||
},
|
||||
avi : {
|
||||
min_size : 100,
|
||||
verify : function(file_contents) {
|
||||
// TODO: file_contents.slice(4, 8): File Size (little endian)
|
||||
|
||||
return file_contents.slice(8, 16).toString() === 'AVI LIST';
|
||||
}
|
||||
},
|
||||
webp : {
|
||||
min_size : 100,
|
||||
// https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
|
||||
// https://en.wikipedia.org/wiki/WebP
|
||||
verify : function(file_contents) {
|
||||
// TODO: file_contents.slice(4, 8): File Size (little endian)
|
||||
|
||||
// "WEBPVP8 " for lossy images,
|
||||
// "WEBPVP8L" for lossless images.
|
||||
return file_contents.slice(8, 15).toString() === 'WEBPVP8';
|
||||
}
|
||||
}
|
||||
},
|
||||
// Magic_number_data[byte count]=[{Natural}Magic_number:{Object}data]
|
||||
Magic_number_data = [], MAX_magic_byte_count = Math
|
||||
.log2(Number.MAX_SAFE_INTEGER) / 8 | 0;
|
||||
|
||||
Object.entries(Magic_number).forEach(function(type) {
|
||||
var magic_data = type[1];
|
||||
if (typeof magic_data === 'string') {
|
||||
// e.g., jpg:'FF D8 FF'
|
||||
magic_data = {
|
||||
magic : magic_data
|
||||
};
|
||||
}
|
||||
// 檔案格式。
|
||||
magic_data.type = type = type[0];
|
||||
// 副檔名。
|
||||
// TODO: 大小寫。
|
||||
if (magic_data.extensions) {
|
||||
if (!Array.isArray(magic_data.extensions)) {
|
||||
magic_data.extensions = [ magic_data.extensions ];
|
||||
}
|
||||
if (!magic_data.extensions_without_type
|
||||
//
|
||||
&& !magic_data.extensions.includes(type)) {
|
||||
// 以 type name 為主
|
||||
magic_data.extensions.unshift(type);
|
||||
}
|
||||
} else {
|
||||
magic_data.extensions = [ type ];
|
||||
}
|
||||
|
||||
if (!magic_data.magic) {
|
||||
// 不採用 Magic number 測試
|
||||
return;
|
||||
}
|
||||
|
||||
magic_data.magic = magic_data.magic.replace(/[ ,]+/g, '');
|
||||
var magic_byte_count = magic_data.magic_byte_count
|
||||
//
|
||||
= magic_data.magic.length / 2 | 0, magic;
|
||||
if (magic_byte_count > MAX_magic_byte_count) {
|
||||
magic_byte_count = MAX_magic_byte_count;
|
||||
magic = magic_data.magic.slice(0, magic_byte_count * 2);
|
||||
} else {
|
||||
magic = magic_data.magic;
|
||||
}
|
||||
if (!Magic_number_data[magic_byte_count]) {
|
||||
Magic_number_data[magic_byte_count] = [];
|
||||
}
|
||||
Magic_number_data[magic_byte_count][parseInt(magic, 0x10)]
|
||||
//
|
||||
= magic_data;
|
||||
if (magic_data.eof) {
|
||||
magic_data.eof = magic_data.eof.replace(/[ ,]+/g, '');
|
||||
magic_data.reversed_eof_bytes
|
||||
//
|
||||
= magic_data.eof.chunk(2).map(function(hex) {
|
||||
return parseInt(hex, 0x10);
|
||||
}).reverse();
|
||||
if (false) {
|
||||
console.log(magic_data.type + ': eof: ' + magic_data.eof);
|
||||
console.log(magic_data.reversed_eof_bytes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* detect / 驗證檔案格式。
|
||||
*
|
||||
* @param {Buffer}file_contents
|
||||
* file contents
|
||||
* @param {Object|String}options
|
||||
* 附加參數/設定選擇性/特殊功能與選項
|
||||
*
|
||||
* @returns
|
||||
*
|
||||
* @since 2017/4/10
|
||||
*/
|
||||
function verify_file_type(file_contents, options) {
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
type : options
|
||||
};
|
||||
} else {
|
||||
// 前置作業。
|
||||
options = library_namespace.setup_options(options);
|
||||
}
|
||||
|
||||
var magic_data, damaged;
|
||||
// console.log(Magic_number_data);
|
||||
for (var i = 0, magic_number = 0; i < Math.min(
|
||||
Magic_number_data.length, MAX_magic_byte_count);) {
|
||||
magic_number = magic_number * 0x100 + file_contents[i];
|
||||
// console.log(magic_number);
|
||||
if (Magic_number_data[++i]
|
||||
&& (magic_data = Magic_number_data[i][magic_number])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!magic_data && file_contents.slice(0, 4).toString() === 'RIFF') {
|
||||
// https://en.wikipedia.org/wiki/Resource_Interchange_File_Format
|
||||
// https://en.wikipedia.org/wiki/WebP
|
||||
var RIFF_type = file_contents.slice(8, 12).toString(),
|
||||
// an unsigned, little-endian 32-bit integer with the length of
|
||||
// this chunk (except this field itself and the chunk
|
||||
// identifier).
|
||||
chunk_size = uint32_from_buffer(file_contents, 4);
|
||||
library_namespace.debug('verify_file_type: RIFF type: ' + RIFF_type
|
||||
+ ', ' + chunk_size + ' bytes, stream length: '
|
||||
+ file_contents.length);
|
||||
// console.log(file_contents.slice(0, 24));
|
||||
magic_data = Magic_number[RIFF_type.toLowerCase()];
|
||||
if (file_contents.length - chunk_size !== 8) {
|
||||
// file damaged
|
||||
damaged = true;
|
||||
} else if (magic_data && (typeof magic_data.verify === 'function')) {
|
||||
damaged = !magic_data.verify(file_contents);
|
||||
}
|
||||
}
|
||||
|
||||
if (!magic_data) {
|
||||
var contents_String = file_contents.toString();
|
||||
// e.g., "<!DOCTYPE html>", "<!DOCTYPE html PUBLIC "...
|
||||
if (contents_String.trimStart().startsWith('<!DOCTYPE html')
|
||||
// TODO: 此處為太過簡陋的測試
|
||||
|| /<html[ a-z\d-="']*>/i.test(contents_String)) {
|
||||
magic_data = Magic_number.html;
|
||||
}
|
||||
}
|
||||
|
||||
if (!magic_data) {
|
||||
// 無法判別。
|
||||
if (options.type in Magic_number) {
|
||||
return {
|
||||
verified : false
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
var result = {
|
||||
type : magic_data.type,
|
||||
// 副檔名。
|
||||
extension : magic_data.extensions[0],
|
||||
extensions : magic_data.extensions
|
||||
};
|
||||
|
||||
if (magic_data.min_size > 0) {
|
||||
result.too_small = file_contents.length < magic_data.min_size;
|
||||
}
|
||||
|
||||
if (damaged) {
|
||||
// file damaged
|
||||
result.damaged = true;
|
||||
|
||||
} else if (magic_data.reversed_eof_bytes) {
|
||||
// verify 檔案損毀
|
||||
var file_index = file_contents.length;
|
||||
if (magic_data.reversed_eof_bytes.some(function(byte, index) {
|
||||
if (false) {
|
||||
console.log('magic: ' + byte + ' vs. '
|
||||
+ file_contents[file_index - 1]);
|
||||
}
|
||||
return byte !== file_contents[--file_index];
|
||||
})) {
|
||||
// file damaged
|
||||
result.damaged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.type) {
|
||||
// TODO: check 副檔名
|
||||
result.verified = options.type === result.type;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_.file_type = verify_file_type;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
return (_// JSDT:_module_
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user