UNPKG

cejs

Version:

A JavaScript module framework that is simple to use.

397 lines (351 loc) 10.3 kB
/** * @name CeL function for archive file. * @fileoverview 本檔案包含了壓縮 compress / archive file 的 functions。 * * @see CeL.application.storage.archive * * @since */ 'use strict'; // 'use asm'; // -------------------------------------------------------------------------------------------- if (typeof CeL === 'function') { CeL.run({ // module name name : 'application.OS.Windows.archive', require : 'data.code.compatibility.' // + '|application.OS.Windows.execute.run_command', code : module_code }); } function module_code(library_namespace) { // requiring var run_command = this.r('run_command'); /** * null module constructor * * @class executing program 的 functions */ var _// JSDT:_module_ = function() { // null module constructor }; /** * for JSDT: 有 prototype 才會將之當作 Class */ _// JSDT:_module_ .prototype = {}; // 2007/5/31 21:5:16 // default configuration var compress_tool_set = { WinRAR : { // rar.exe path : '"%ProgramFiles%\\WinRAR\\WinRAR.exe"', extension : 'rar', // compress switch c : { // cL:command line, c:compress, s:switch cL : '$path $cmd $s $archive -- $files', cmd : 'a', // l:'-ilog logFN', // -rr1p -s<N> -ap -as -ep1 -tl -x<f> -x@<lf> -z<f> -p[p] -hp[p] // rar等 // -v690m s : '-m5 -u -dh -os -r -ts -scuc -ep1 -ilog' }, // uncompress switch u : { // command line cL : '$path $cmd $archive $eF $eTo', cmd : 'e' }, // test switch t : { cL : '$path $cmd $archive', cmd : 't' }, // command line command : '%path %command %switch %archive %files' }, '7-Zip' : { // The path of p7z executable file. // TODO: use library_namespace.nodejs.executable_file_path('7z') // 7zG.exe path : '"%ProgramFiles%\\7-Zip\\7z.exe"', extension : '7z', // compress switch c : { cL : '$path $cmd $s $archive $files', cmd : 'u', s : '-mx9 -ms -mhe -mmt -uy2' }, // uncompress switch u : { cL : '$path $cmd $s $archive $eF', // cmd : 'e', cmd : 'x', s : function(fO) { var s = ' -ssc -y'; if (fO.eTo) s += ' -o"' + fO.eTo + '"'; return s; } }, // test switch t : { cL : '$path $cmd $archive', cmd : 't' } } }; /** * <code> test: var base='C:\\kanashimi\\www\\cgi-bin\\program\\misc\\'; compress(base+'jit','_jit.htm',{tool:'7-Zip',s:''}); uncompress(base+'jit',base,{tool:'7-Zip'}); fO={ tool:'WinRAR' // or'7-Zip' ,m:'c' // method ,s:'' // switch ,archive:'' // archivefile ,files='' // whattocompress ,eTo='' // wheretouncompress ,eF='' // whattouncompress ,rcL=1 // rebuildcommandline } </code> */ // solid, overwrite, compressLevel, password /** * compress FSO * * @param {Object}fO * flags object * @returns */ function compressF(fO) { // 參數檢查: 未完全 if (!fO) fO = {}; if (typeof fO !== 'object') return; if (!fO.tool) fO.tool = 'WinRAR'; // method if (false && !fO.m) fO.m = 'c'; if (!fO.m || !fO.archive && (fO.m !== 'c' || fO.m === 'c' && !fO.files)) return; if (fO.m === 'c') { if (typeof fO.files !== 'object') fO.files = fO.files ? [ fO.files ] : fO.archive.replace( /\...+$/, ''); if (!fO.archive) fO.archive = fO.files[0].replace(/[\\\/]$/, '') + _t.extension; fO.files = '"' + fO.files.join('" "') + '"'; } var i, _t = compress_tool_set[fO.tool], _m, _c; if (!_t || !(_m = _t[fO.m])) return; else if (!/\.[a-z]+$/.test(fO.archive)) fO.archive += '.' + _t.extension; if (false && fO.bD) // base directory, work directory, base folder fO.archive = fO.bD + (/[\\\/]$/.test(fO.bD) ? '' : '\\') + fO.archive; fO.archive = '"' + fO.archive.replace(/"/g, '""') + '"'; library_namespace.debug('compressF(): check OK.'); // 構築 command line arguments。 if (_m._cL && !fO.rcL) { _c = _m._cL; } else { // rebuild command line arguments _c = _m.cL.replace(/\$path/, _t.path); for (i in _m) if (typeof fO[i] === 'undefined') _c = _c.replace(new RegExp('\\$' + i), typeof _m[i] === 'function' ? _m[i](fO) : _m[i] || ''); _m._cL = _c; library_namespace.debug(_c, 2, 'compressF'); } for (i in fO) _c = _c.replace(new RegExp('\\$' + i), fO[i] || ''); if (_c.indexOf('$') !== -1) { library_namespace.debug('compressF() error:\n' + _c); return; } library_namespace.debug('compressF() ' + (_c.indexOf('$') === -1 ? 'run' : 'error') + ':\n' + _c); // run return WshShell.Run(_c, 0, true); // run_command.Unicode(_c); } // compress[generateCode.dLK]='compressF'; /** * compress files. * * @param {String}archive * compress file path. * @param {Array}files * what to compress * @param {Object}options * flags object * @returns */ function compress(archive, files, options) { // 前置處理。 options = library_namespace.setup_options(options); if (!options.m) options.m = 'c'; if (archive) options.archive = archive; if (files) options.files = files; return compressF(options); } _.compress = compress; // uncompress[generateCode.dLK]='uncompressF'; /** * uncompress archive file * * @param archive * compressed archive file path * @param eTo * where to uncompress/target * @param {Object} * flag flags * @returns */ function uncompress(archive, eTo, flag) { if (!flag) flag = {}; else if (typeof flag !== 'object') return; if (!flag.m) flag.m = 'u'; if (!flag.eF) flag.eF = ''; if (archive) flag.archive = archive; if (eTo) flag.eTo = eTo; return compressF(flag); } function parse_7z_data(status, log, error) { if (error && library_namespace.is_debug()) library_namespace.error(error); var message = log.match(/\nError:\s+(?:[A-Za-z]:)?[^:\n]+: ([^\n]+)/); if (message) { if (library_namespace.is_debug()) library_namespace.error(message[1]); this.callback.call(this['this'], this.path, new Error(message[1])); return; } library_namespace.debug(log.replace(/\n/g, '<br/>'), 4); message = log .match(/\r?\n([^\r\n]+)\r?\n([ \-]+)\r?\n((?:.+|\n)+?)\r?\n[ \-]+\r?\n/); library_namespace.debug(message, 3); if (!message) { if (library_namespace.is_debug()) library_namespace.warn('無法 parse header!'); this.callback(this.path, new Error('無法 parse header!')); return; } // TODO: 系統化讀入固定欄位長度之 data。 var header = [], i = 0, length, match, file_list, file_array = [], pattern = [], // start = [], end = []; message[1].replace(/\s*(\S+)/g, function($0, $1) { library_namespace.debug('header: +[' + $1 + '] / [' + $0 + ']', 2); header.push($1); end.push(i += $0.length); start.push(i - $1.length); return ''; }); start[0] = 0; file_list = message[3].replace(/\r/g, '').split(/\n/); library_namespace.debug(file_list.join('<br />'), 3); var no_calculate_count = 0, calculate_done = true; for (i = 0, length = file_list.length; i < length; i++) { calculate_done = true; var no_calculate = true; library_namespace.debug('一個個猜測邊界: ' + i + '/' + length + '<br />start: ' + start + '<br />end: ' + end, 2); for (var j = 1, fragment; j < header.length; j++) { if (end[j - 1] + 1 < start[j]) { calculate_done = false; fragment = file_list[i].slice(end[j - 1], start[j]); if (match = fragment.match(/^\S+/)) if (match[0].length < fragment.length) { library_namespace.debug('end: [' + (j - 1) + '] += ' + match[0].length, 2); end[j - 1] += match[0].length; no_calculate = false; } else { library_namespace.warn('無法判別 ' + header[j - 1] + ' 與 ' + header[j] + ' 之邊界。fragment: [' + fragment + ']'); continue; } if (match = fragment.match(/\S+$/)) { library_namespace.debug('start: [' + j + '] -= ' + match[0].length, 2); start[j] -= match[0].length; no_calculate = false; } } } if (no_calculate) ++no_calculate_count; else no_calculate_count = 0; if (calculate_done || no_calculate_count > 20) { library_namespace.debug('於 ' + i + '/' + length + ' 跳出邊界判別作業: ' + (calculate_done ? '已' : '未') + '完成。'); break; } } for (i = 0; i < header.length - 1; i++) pattern.push('(.{' + (start[i + 1] - start[i]) + '})'); pattern.push('(.+)'); pattern = new RegExp(pattern.join('')); library_namespace.debug('header: [' + header.join('<b style="color:#e44;">|</b>') + '], using pattern ' + pattern); for (i = 0, length = file_list.length; i < length; i++) { if (match = file_list[i].match(pattern)) { var j = 1, data = []; for (; j < match.length; j++) data.push(match[j].trim()); library_namespace.debug(data .join('<b style="color:#e44;">|</b>'), 3); file_array.push(data); } else { library_namespace.warn('無法 parse [' + file_list[i] + ']'); } } this.callback(this.path, file_array, header); } // List archive file. // read file list of .7z archive // callback(status, log, error) function archive_data(path, callback, options) { if (path && typeof callback === 'function') { // 前置處理。 options = Object.assign(Object.create(null), options, { path : path, callback : callback }); run_command.Unicode(compress_tool_set['7-Zip'].path + ' l "' + path + '"', parse_7z_data.bind(options)); } } _.archive_data = archive_data; // -------------------------------------------------------------------------------------------- // export 導出. return (_// JSDT:_module_ ); }