cejs
Version:
A JavaScript module framework that is simple to use.
1,657 lines (1,491 loc) • 65.6 kB
JavaScript
/**
* @name CeL function for net
* @fileoverview 本檔案包含了處理網路傳輸相關功能的 functions。
* @since
*/
// --------------------------------------------------------------------------------------------
// 不採用 if 陳述式,可以避免 Eclipse JSDoc 與 format 多縮排一層。
typeof CeL === 'function' && CeL.run({
// module name
name : 'application.net',
// includes() @ data.code.compatibility.
require : 'data.code.compatibility.' + '|data.native.'
//
+ '|application.OS.Windows.get_WScript_object'
//
+ '|interact.DOM.HTML_to_Unicode',
// 設定不匯出的子函式。
// no_extend : '*',
// 為了方便格式化程式碼,因此將 module 函式主體另外抽出。
code : module_code
});
function module_code(library_namespace) {
'use strict';
var module_name = this.id;
// @see PATTERN_has_URI_invalid_character @ library_namespace.character
var PATTERN_has_URI_invalid_character = /[^a-zA-Z0-9;,/?:@&=+$\-_.!~*'()#]/;
var check_encoding = function(encoding) {
// console.trace(encoding);
if (encoding && !/^UTF-?8$/i.test(encoding)) {
library_namespace.warn('您必須先載入 CeL.! 這訊息只會顯示一次!');
check_encoding = null;
}
},
// 本函數亦使用於 CeL.application.net.work_crawler
// 本函式將使用之 encodeURIComponent(),包含對 charset 之處理。
// @see function_placeholder() @ module.js
encode_URI_component = function(string, encoding) {
if (library_namespace.character) {
library_namespace.debug('採用 ' + library_namespace.Class
// 有則用之。 use CeL.data.character.encode_URI_component()
+ '.character.encode_URI_component 編碼 ' + encoding, 1, module_name);
encode_URI_component = library_namespace.character.encode_URI_component;
check_encoding = null;
return encode_URI_component(string, encoding);
}
check_encoding(encoding);
return encodeURIComponent(string);
};
var encode_URI = function(string, encoding) {
if (library_namespace.character) {
library_namespace.debug('採用 ' + library_namespace.Class
// 有則用之。 use CeL.data.character.encode_URI()
+ '.character.encode_URI 編碼 ' + encoding, 1, module_name);
encode_URI = library_namespace.character.encode_URI;
check_encoding = null;
return encode_URI(string, encoding);
}
check_encoding(encoding);
return encodeURI(string);
};
var decode_URI_component = function(string, encoding) {
if (library_namespace.character) {
library_namespace.debug('採用 ' + library_namespace.Class
// 有則用之。 use CeL.data.character.decode_URI_component()
+ '.character.decode_URI_component 解碼 ' + encoding, 1, module_name);
decode_URI = library_namespace.character.decode_URI;
decode_URI_component = library_namespace.character.decode_URI_component;
check_encoding = null;
return decode_URI_component(string, encoding);
}
check_encoding(encoding);
return decodeURIComponent(string);
};
var decode_URI = decode_URI_component;
// requiring
var KEY_not_native = library_namespace.env.not_native_keyword;
var get_WScript_object = this.r('get_WScript_object'), HTML_to_Unicode = this
.r('HTML_to_Unicode');
/**
* null module constructor
*
* @class net 的 functions
*/
var _// JSDT:_module_
= function() {
// null module constructor
};
/**
* for JSDT: 有 prototype 才會將之當作 Class
*/
_// JSDT:_module_
.prototype = {};
/** {Number}未發現之index。 const: 基本上與程式碼設計合一,僅表示名義,不可更改。(=== -1) */
var NOT_FOUND = ''.indexOf('_');
// ------------------------------------------------------------------------
function is_IP(host, IPv6_only) {
return !IPv6_only
// for IPv4 addresses
&& /^[12]?\d{1,2}(?:\.[12]?\d{1,2}){3}$/.test(host) && 4
// for IPv6 addresses
|| /^[\dA-F]{1,4}(?::[\dA-F]{1,4}){7}$/i.test(host) && 6;
}
_.is_IP = is_IP;
/**
* get full path.
*/
function get_full_URL(relative_path, base_URL) {
if (/([a-z\d]+:)\/\//.test(relative_path)) {
// e.g., "https://host.name/"
return relative_path;
}
if (relative_path.startsWith('/')) {
// e.g., "/path/to/file"
var matched = base_URL.match(/([a-z\d]+:)\/\/[^\/]+/);
if (matched) {
return matched[0] + relative_path;
}
}
// e.g., "relative/path/to/file"
return base_URL.replace(/[^\/]+$/, '') + relative_path;
}
_.get_full_URL = get_full_URL;
// gethost[generateCode.dLK]='Sleep';
/**
* get host name & IP 2005/3/1 22:32 只能用於WinXP, Win2000
* server(換個版本指令以及輸出可能就不同!),而且非常可能出狀況! Win98 不能反查,只能 check local IP
*
* @deprecated 改用 getNetInfo()
*/
function gethost(host) {
var IP, p, c, t, i, f, cmd;
// 決定shell cmd 對於 ".. > ""path+filename"" " 似乎不能對應的很好,
// 所以還是使用 "cd /D path;.. > ""filename"" "
try {
c = '%COMSPEC% /U /c "', WshShell.Run(c + '"');
p = WScript.ScriptFullName.replace(/[^\\]+$/, '');
c += 'cd /D ""' + p + '"" && ';
cmd = 1;
} catch (e) {
try {
c = '%COMSPEC% /c ';
WshShell.Run(c);
p = 'C:\\';
} catch (e) {
return;
}
}
if (host) {
if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host))
IP = host, host = 0;
} else {
f = 'ipconfig.tmp.txt';
// winipcfg
WshShell.Run(c + 'ipconfig > ' + (cmd ? '""' + f + '"" "' : p + f),
0, true);
if (t = simpleRead(f = p + f)) {
// TODO: use t.between()
if ((i = t.indexOf('PPP adapter')) !== NOT_FOUND)
t = t.slice(i);
else if ((i = t.indexOf('Ethernet adapter')) !== NOT_FOUND)
t = t.slice(i);
if ((i = t.indexOf('IP Address')) !== NOT_FOUND)
t = t.slice(i);
if (t.match(/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/))
IP = RegExp.$1;
}
try {
fso.DeleteFile(f);
} catch (e) {
}
if (!IP)
return [ 0, 0 ];
}
if (!cmd)
// Win98沒有nslookup
return [ host, IP ];
f = 'qDNS.tmp.txt';
WshShell.Run(c
+ 'nslookup '
+ (cmd ? '""' + (IP || host) + '"" > ""' + f + '"" "'
: (IP || host) + '>' + p + f), 0, true);
// /C:執行字串中所描述的指令然後結束指令視窗 (x)因為用/c,怕尚未執行完。
// try { WScript.Sleep(200); } catch (e) { }
if ((t = simpleRead(f = p + f)) && t.match(/Server:/)
&& t.match(/Address:\s*\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)) {
t = t.slice(RegExp.lastIndex);
host = t.match(/Name:\s*(\S+)/) ? RegExp.$1 : 0;
IP = t.match(/Address:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) ? RegExp.$1
: 0;
// library_namespace.debug(host + '\n' + IP);
} else
host = IP = 0;
try {
fso.DeleteFile(f);
} catch (e) {
}
return [ host, IP ];
}
// for element.dataset
if (false)
if (!library_namespace.global.DOMStringMap)
library_namespace.global.DOMStringMap = library_namespace.setting_pair;
// ------------------------------------------------------------------------
var port_of_protocol = {
// https://tools.ietf.org/html/rfc1928#section-3
// The SOCKS service is conventionally located on TCP port 1080.
// https://github.com/TooTallNate/node-socks-proxy-agent/blob/master/src/agent.ts
socks4 : 1080,
socks4a : 1080,
socks5 : 1080,
socks : 1080,
socks5h : 1080,
ftp : 21,
http : 80,
https : 443
};
_.port_of_protocol = port_of_protocol;
var PATTERN_URI =
// [ all, 1: `protocol:`, 2: '//', 3: host, 4: path ]
/^([\w\-]{2,}:)?(\/\/)?(\/[A-Z]:|(?:[^@]*@)?[^\/#?&:.][^\/#?&:]+(?::\d{1,5})?)?(.*)$/i
// /^(?:(https?:)\/\/)?(?:([^:@]+)(?::([^@]*))?@)?([^:@]+)(?::(\d{1,5}))?$/
;
/**
* URI class.
*
* 本組函數之目的:<br />
* 1. polyfill for W3C URL API.<br />
* 2. CeL.Search_parameters() 採用{Object}操作 hash 更方便重複利用,且可支援 charset。
*
* new URLSearchParams() 會將數值轉成字串。 想二次利用 {Object}, {Array},得採用 new CeL.URI()
* 而非 new URL()。
*
* @example <code>
// 警告: 這不能保證 a 和 fg 的順序!! 僅保證 fg=23 → fg=24。欲保持不同名稱 parameters 間的順序,請採用 {String}parameter+parameter。
var url = new CeL.URI('ftp://user:cgh@dr.fxgv.sfdg:4231/3452/dgh.rar?fg=23&a=2&fg=24#hhh');
alert(url.hostname);
// to URL()
new URL(url).toString() === url.toString()
// parameters to URLSearchParams()
new URLSearchParams(url.search_params.toString()).toString() === url.search_params.toString();
</code>
*
* <code>
test:
/fsghj.sdf
a.htm
http://www.whatwg.org/specs/web-apps/current-work/#attr-input-pattern
file:///D:/USB/cgi-bin/lib/JS/_test_suit/test.htm
//www.whatwg.org/specs/web-apps/current-work/#attr-input-pattern
TODO:
file:///D:/USB/cgi-bin/lib/JS/_test_suit/test.htm
→ .file_path:
D:\USB\cgi-bin\lib\JS\_test_suit\test.htm
eURI : /^((file|telnet|ftp|https?)\:\/\/|~?\/)?(\w+(:\w+)?@)?(([-\w]+\.)+([a-z]{2}|com|org|net))?(:\d{1,5})?(\/([-\w~!$+|.,=]|%[\dA-F]{2})*)?(\?(([-\w~!$+|.,*:]|%[\dA-F]{2})+(=([-\w~!$+|.,*:=]|%[\dA-F]{2})*)?&?)*)?(#([-\w~!$+|.,*:=]|%[\dA-F]{2})*)?$/i,
TODO:
input [ host + path, search, hash ]
URI, IRI, XRI
WHATWG URL parser
* </code>
*
* @param {String}uri
* URI to parse
* @param {String}[base_uri]
* 當做基底的 URL。 see
* CeL.application.storage.file.get_relative_path()
* @param {Object}[options]
* 附加參數/設定選擇性/特殊功能與選項
*
* @return parsed object
*
* @since 2010/4/13 23:53:14 from parseURI+parseURL
* @since 2021/2/27 6:10:25 Parses URI, function parse_URI(uri) → new
* URI(uri)
*
* @_memberOf _module_
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/URL_API
* @see RFC 1738, RFC 2396, RFC 3986, Uniform Resource Identifier (URI):
* Generic Syntax, http://tools.ietf.org/html/rfc3987,
* http://flanders.co.nz/2009/11/08/a-good-url-regular-expression-repost/,
* http://www.mattfarina.com/2009/01/08/rfc-3986-url-validation,
* https://developer.mozilla.org/en/DOM/window.location, also see
* batURL.htm
*/
function URI(uri, base_uri, options) {
if (!is_URI(this)) {
// Call URI(value), like String(value)
if (is_URI(uri))
return uri;
return new URI(uri, base_uri, options);
}
options = library_namespace.new_options(options);
if (options.charset === 'buffer') {
// Although the content is buffer, the URI itself should be not.
delete options.charset;
}
if ((uri instanceof URL) || is_URI(uri)) {
// uri.href
uri = uri.toString();
}
if (!uri
// 不能用 instanceof String!
|| typeof uri !== 'string') {
throw new Error('Invalid URI type: (' + (typeof uri) + ') ' + uri);
}
var href = library_namespace.simplify_path(uri);
if (/^\/\//.test(uri)) {
// CeL.simplify_path('//hostname') === '/hostname'
href = '/' + href;
}
var matched = href.match(PATTERN_URI), path;
if (!matched) {
throw new Error('Invalid URI: (' + (typeof uri) + ') ' + uri);
}
// console.log(href);
library_namespace.debug('parse [' + uri + ']: '
+ matched.join('<br />\n'), 8, 'URI');
// console.trace([ matched, base_uri, options ]);
uri = base_uri && URI(base_uri) || options.as_URL
//
|| library_namespace.is_WWW() && {
// protocol包含最後的':',search包含'?',hash包含'#'.
// file|telnet|ftp|https
protocol : location.protocol,
hostname : location.hostname,
port : location.port,
host : location.host,
// local file @ IE: C:\xx\xx\ff, others: /C:/xx/xx/ff
pathname : location.pathname
};
if (library_namespace.need_avoid_assign_to_setter) {
for ( var key in uri) {
if (key !== 'search'
// &&key !== 'hash'
) {
this[key] = uri[key];
}
}
uri = this;
} else {
uri = Object.assign(this, uri);
}
// uri.uri = href;
/**
* ** filename 可能歸至m[4]!<br />
* 判斷準則:<br />
* gsh.sdf.df#dhfjk filename|hostname<br />
* gsh.sdf.df/dhfjk hostname<br />
* gsh.sdf.df?dhfjk filename<br />
* gsh.sdf.df filename<br />
*/
href = matched[3] && matched[3].toLowerCase() || '';
path = matched[4] || '';
// 可辨識出為 domain 的這個 hostname. e.g., gTLD
// https://en.wikipedia.org/wiki/Generic_top-level_domain
if (/(?:\w+\.)+(?:com|org|net|info)$/i.test(href)) {
// e.g., URI("www.example.com")
path = path || '/';
if (uri.protocol === 'file:')
uri.protocol = 'https:';
}
if (matched[1])
uri.protocol = matched[1].toLowerCase();
// uri._protocol = uri.protocol.slice(0, -1).toLowerCase();
// library_namespace.debug('protocol [' + uri._protocol + ']', 2);
if (href && !/^\/[A-Z]:$/i.test(href)
&& (path.charAt(0) === '/' || /[@:]/.test(href))) {
// 處理 username:password
if (matched = href.match(/^([^@]*)@(.+)$/)) {
matched.user_passwords = matched[1].match(/^([^:]+)(:(.*))?$/);
if (!matched.user_passwords)
return;
uri.username = matched.user_passwords[1];
if (matched.user_passwords[3])
uri.password = matched.user_passwords[3];
href = matched[2];
} else {
// W3C URL API 不論有沒有帳號密碼皆會設定這兩個值
uri.password = '';
uri.username = '';
}
// [ all, host, (integer)port ]
matched = href.match(/^([^\/#?&\s:]+)(?::(\d{1,5}))?$/);
if (!matched) {
throw new Error('Invalid host: ' + href);
}
// 處理 host
// host=hostname:port
uri.hostname = uri.host = matched[1];
if (matched[2]
&& matched[2] != port_of_protocol[uri.protocol.slice(0, -1)
.toLowerCase()]) {
// uri[KEY_port] = parseInt(matched[2], 10);
uri.port = String(parseInt(matched[2], 10));
uri.host += ':' + uri.port;
} else if (false) {
uri[KEY_port] = parseInt(matched[2]
|| port_of_protocol[uri.protocol.slice(0, -1)
.toLowerCase()]);
}
} else {
// test uri.protocol === 'file:'
path = href + path;
href = '';
// uri.protocol === 'file:'
uri.port = uri.port || '';
uri.host = uri.host || '';
uri.hostname = uri.hostname || '';
uri.username = uri.username || '';
uri.password = uri.password || '';
}
uri.origin = uri.protocol + '//' + uri.host;
// Normalize Windows path
// "d:\\p\\" → "d:/p/"
path = path.replace(/\\/g, '/');
if (/^[A-Z]:/i.test(path)) {
// "d:/p/" → "/d:/p/"
path = '/' + path;
}
if (!href) {
// test /C:/path
if (!/^\/[A-Z]:/i.test(path)) {
if (!base_uri) {
library_namespace.debug(
// 將 [' + path + '] 當作 pathname! not hostname!
'Treat [' + path + '] as pathname!', 1, 'URI');
}
if (uri.pathname) {
if (/^\//.test(path)) {
// path 為 absolute path
matched = !/^\/[A-Z]:/i.test(path)
&& uri.pathname.match(/^\/[A-Z]:/i);
if (matched)
path = matched[0] + path;
} else {
// 僅取 uri.pathname 之 directory path
path = uri.pathname.replace(/[^\\\/]+$/, '') + path;
}
path = library_namespace.simplify_path(path);
}
}
// console.trace(path);
}
// upper-cased driver letter: "/d:/p/" → "/D:/p/"
path = path.replace(/^\/[a-z]:/g, function($0) {
return $0.toUpperCase();
});
if (library_namespace.is_WWW()) {
library_namespace.debug('local file: [' + location.pathname + ']',
9, 'URI');
}
// NG: /^([^%]+|%[\dA-F]{2})+$/
// prevent catastrophic backtracking. e.g., '.'.repeat(300)+'%'
// Thanks for James Davis.
if (false && path && !/^(?:[^%]|%[\dA-F]{2})+$/i.test(path)) {
library_namespace.warn('URI: encoding error: [' + path + ']');
}
if (path && /&#\d{2,5};/.test(path)) {
library_namespace
.warn('URI: You may need to decode "&#...;" first (e.g., via '
// CeL.HTML_to_Unicode()
+ library_namespace.Class
+ '.HTML_to_Unicode()): [' + path + ']');
console.trace(path);
}
// console.trace([ href, path, uri ]);
library_namespace.debug('parse path: [' + path + ']', 9);
if (path && (matched = path
// https://cdn.dongmanmanhua.cn/16189006774011603165.jpg?x-oss-process=image/quality,q_90
.match(/^(([^#?]*\/)?([^\/#?]*))?(\?([^#]*))?(#.*)?$/))) {
library_namespace.debug('pathname: [' + matched + ']', 9);
// pathname={path}filename
uri.pathname = matched[1] || '';
if (/%[\dA-F]{2}/i.test(uri.pathname)) {
try {
// console.trace([ uri.pathname, decodeURI(uri.pathname) ]);
// Try to get decoded path.
uri.pathname = decodeURI(uri.pathname);
} catch (e) {
// uri.pathname = decode_URI(uri.pathname, charset);
}
}
if (PATTERN_has_URI_invalid_character.test(uri.pathname)) {
// console.trace([ uri.pathname, encode_URI(uri.pathname,
// options.charset) ]);
uri.pathname = encode_URI(uri.pathname, options.charset);
}
// .directory_path 會隨不同 OS 之 local file 表示法作變動!
uri.directory_path = /^\/[A-Z]:/i.test(uri.pathname) ? matched[2]
.slice(1).replace(/\//g, '\\')
// e.g., 'file:///D:/directory/file.name'
// → D:\directory\
: /^[A-Z]:(?:\/([^\/]|$)|$)/i.test(uri.pathname) ? matched[2]
.replace(/\//g, '\\') : matched[2];
uri.filename = matched[3];
// request path used @ node.js http.request(options)
// uri.path = uri.pathname + uri.search
// uri.path = uri.pathname + (matched[5] ? '?' + matched[5] : '');
var _options;
if (Object.defineProperty[KEY_not_native]) {
// hash without '#': using uri.hash.slice(1)
uri.hash = matched[6];
uri.search = matched[4];
_options = Object.assign({
// @see (typeof options.URI === 'object')
URI : uri
}, options);
} else {
Object.defineProperty(uri, KEY_hash, {
value : matched[6] ? matched[6].slice(1) : '',
writable : true
});
_options = options;
}
matched = matched[5];
// console.trace([ matched, _options ]);
} else {
if (!href) {
throw new Error('Invalid URI: ' + uri);
}
if (uri.pathname) {
uri.directory_path = uri.pathname.replace(/[^\/]+$/, '');
// uri.path = uri.pathname;
}
matched = '';
}
if (options.as_URL) {
// 盡可能模擬 W3C URL()
// library_namespace.debug('search: [' + matched[5] + ']', 2);
// https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
uri.searchParams = new URLSearchParams(matched, _options);
} else {
// do not set uri.search_params directly.
_options = Object.assign({
URI : uri
}, _options);
// console.trace(_options);
uri.search_params = new Search_parameters(matched, _options);
}
if (options.charset)
uri.charset = options.charset;
library_namespace.debug('path: [' + uri.path + ']', 9);
if (Object.defineProperty[KEY_not_native]) {
library_namespace.debug('Generate .href of URI by URI_toString()',
10);
uri.toString();
}
// console.trace(uri);
library_namespace.debug('href: [' + uri.href + ']', 8);
// return uri;
}
Object.defineProperties(URI.prototype, {
hash : {
enumerable : true,
get : function get() {
if (!this[KEY_hash])
return '';
return '#' + this[KEY_hash];
},
set : function set(value) {
value = String(value);
if (value.startsWith('#')) {
value = value.slice(1);
}
this[KEY_hash] = value;
}
},
// URI.prototype.search
search : {
enumerable : true,
get : search_getter,
set : function set(value) {
var search_params = this.search_params || this.searchParams;
if (false && this.search_params) {
this.search_params[KEY_URL] = this;
}
// search_params.clean_parameters();
search_clean_parameters(search_params);
// node.js v0.10.48 有 bug? 需要取得 search_params 一次才不會造成
// ReferenceError: CeL is not defined
// @ URI.prototype.href.set
// @ site_name #17 @ _test suite/test.js
URL[KEY_not_native] && search_params && Math.abs(0);
value = String(value);
if (value.startsWith('?')) {
value = value.slice(1);
}
if (value) {
// search_params.set_parameters(value);
search_set_parameters.call(search_params, value);
}
}
},
// URI.prototype.href
href : {
enumerable : true,
get : Object.defineProperty[KEY_not_native] ? URI_toString
: URI_href,
set : function set(href) {
URI.call(this, href);
}
},
toString : {
value : Object.defineProperty[KEY_not_native] ? URI_toString
: URI_href
}
});
function search_getter(options) {
// library_namespace.debug('normalize properties by search_getter');
// library_namespace.debug(this.search_params);
if (false && this.search_params) {
this.search_params[KEY_URL] = this;
}
var uri = this;
// console.trace([ uri, uri.searchParams ]);
var search = 'search_params' in uri
// function parameters_toString(options)
? uri.search_params.toString(options)
// options.as_URL?
: uri.searchParams.toString();
return search ? '?' + search : '';
}
function URI_href() {
var uri = this;
// console.trace([ uri, uri.search ]);
// href=protocol:(//)?username:password@hostname:port/path/filename?search#hash
var href = (uri.protocol ? uri.protocol + '//' : '')
+ (uri.username || uri.password ? uri.username
+ (uri.password ? ':' + uri.password : '') + '@' : '')
+ uri.host
// assert: uri.pathname is encodeURI()-ed.
+ uri.pathname + uri.search + uri.hash;
return href;
}
// options: 'charset'
function URI_toString(options) {
var uri = this;
// assert: !!Object.defineProperty[KEY_not_native] === true
uri.search = search_getter.call(uri, options);
if ((uri.hash = String(uri.hash)) && !uri.hash.startsWith('#')) {
uri.hash = '#' + uri.hash;
}
// console.trace(uri.search);
return uri.href = URI_href.call(uri);
}
_// JSDT:_module_
.URI = URI;
function is_URI(value) {
return value instanceof URI;
}
_.is_URI = is_URI;
// ------------------------------------------------------------------------
var NO_EQUAL_SIGN = typeof Symbol === 'function' ? Symbol('NO_EQUAL_SIGN')
//
: {
NO_EQUAL_SIGN : true
};
function decode_URI_component_no_throw(value, charset) {
try {
return decode_URI_component(value, charset);
} catch (e) {
}
// decode_URI_component() should be decodeURIComponent()
return value.replace(/%([\dA-F]{2})/g, function(encoded, code) {
return String.fromCharCode(parseInt(code, 16));
});
}
/**
* parse_parameters({String}parameter) to hash
*
* CeL.net.Search_parameters()
*
* 新版本與 charset 編碼無關的話,應該使用 new URLSearchParams(parameters).toString()。
*
* @param {String}search_string
* @param {Object}[options]
* 附加參數/設定選擇性/特殊功能與選項
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
*/
function Search_parameters(search_string, options) {
// Similar to:
// return new URLSearchParams(search_string);
// but with charset and forward compatibility
// and re-usable {Object} data structure.
if (!is_Search_parameters(this)) {
// `CeL.Search_parameters(search_string)`
if (is_Search_parameters(search_string))
return search_string;
return new Search_parameters(search_string, options);
}
options = library_namespace.setup_options(options);
var parameters = this;
var data, name, value, matched;
if (typeof search_string === 'string') {
// http://stackoverflow.com/questions/14551194/how-are-parameters-sent-in-an-http-post-request
data = search_string.replace(/\+/g, '%20').split(/&/);
} else if (Array.isArray(search_string)) {
data = search_string;
} else if (typeof search_string === 'object') {
// https://github.com/whatwg/url/issues/27
// Creation of URLSearchParams from Object/Map
if (library_namespace.is_Map(search_string)) {
// input {Map}.
Array.from(search_string.entries()).forEach(function(entry) {
parameters[entry[0]] = entry[1];
});
} else if (search_string instanceof URLSearchParams) {
Array.from(search_string.keys()).unique().forEach(
function(key) {
var values = search_string.getAll(key);
parameters[key] = values.length > 1 ? values
: values[0];
});
} else {
// {Object}search_string.
// assert: library_namespace.is_Object(search_string)
Object.assign(parameters, search_string);
}
} else {
if (search_string) {
// Invalid search 無法處理之 parameters
library_namespace.debug({
// gettext_config:{"id":"enter-a-non-string-parameter-$1"}
T : [ '輸入了非字串之參數:[%1]', search_string ]
}, 1, 'Search_parameters');
}
}
// 不可設置 parameters.charset,會加在 request URL 裡面。
var charset = options.charset;
for (var i = 0, l = data && data.length || 0; i < l; i++) {
if (!data[i])
continue;
if (library_namespace.is_Object(data[i])) {
this.set_parameters(data[i], options);
continue;
}
if (typeof data[i] !== 'string') {
library_namespace
.error('Must input {String} as search parameter!');
console.error(data[i]);
return;
}
// Warning: Search_parameters() 僅接受 UTF-8。
// 欲設定 charset,必須自行先處理 .search!
// var index = parameter.indexOf('=');
if (matched = data[i].match(/^([^=]+)=(.*)$/)) {
name = matched[1];
value = decode_URI_component_no_throw(matched[2], charset);
} else {
name = data[i];
value = 'default_value' in options ? options.default_value
: /* name */NO_EQUAL_SIGN;
}
try {
name = decode_URI_component_no_throw(name, charset);
} catch (e) {
// TODO: handle exception
}
if (ignore_search_properties
// Warning: for old environment, may need ignore some keys
&& (name in ignore_search_properties)) {
continue;
}
if (library_namespace.is_debug(2)) {
try {
library_namespace.debug('[' + (i + 1) + '/' + l + '] '
//
+ (parameters[name] ? '<span style="color:#888;">('
//
+ parameters[name].length + ')</span> [' + name
//
+ '] += [' + value + ']' : '[' + name + '] = ['
//
+ value + ']'));
} catch (e) {
}
}
if (options.split_pattern && typeof value === 'string'
//
&& (matched = value.split(options.split_pattern)).length > 1) {
if (name in parameters) {
if (Array.isArray(parameters[name])) {
Array.prototype.push.apply(parameters[name], matched);
} else {
matched.unshift(parameters[name]);
parameters[name] = matched;
}
} else
parameters[name] = matched;
} else {
search_add_1_parameter.call(parameters, name, value);
}
}
if (options.Array_only) {
Object.keys(parameters).forEach(function(key) {
if (!ignore_search_properties
// Warning: for old environment, may need ignore some keys
|| !(key in ignore_search_properties)) {
if (!Array.isArray(parameters[name]))
parameters[name] = [ parameters[name] ];
}
});
}
if (typeof options.URI === 'object') {
Object.defineProperty(parameters, KEY_URL, {
value : options.URI
});
}
}
function search_add_1_parameter(key, value, options) {
if (key in this) {
var original_value = this[key];
if (Array.isArray(original_value))
original_value.push(value);
else
this[key] = [ original_value, value ];
} else {
// Warning: if Array.isArray(value),
// next value will push to the value!
this[key] = value;
}
}
/**
* set / append these parameters
*
* @inner
*/
function search_set_parameters(parameters, options) {
// console.trace([ this, parameters, options ]);
options = Object.assign({
charset : this.charset || this[KEY_URL] && this[KEY_URL].charset
}, options);
if (!library_namespace.is_Object(parameters))
parameters = Search_parameters(parameters, options);
// console.trace([ this, parameters, options ]);
// Object.keys() 不會取得 Search_parameters.prototype 的屬性。
Object.keys(parameters).forEach(function(key) {
if (!ignore_search_properties
// Warning: for old environment, may need ignore some keys
|| !(key in ignore_search_properties)) {
var value = parameters[key];
if (options.append) {
search_add_1_parameter.call(this,
//
key, value, options);
} else {
this[key] = value;
}
}
}, this);
return this;
}
// @inner
function search_clean_parameters(object) {
// if (!object)
object = this;
if (!object) {
// @ node.js v0.10.48
// https://github.com/kanasimi/CeJS/runs/2105831296?check_suite_focus=true
return this;
}
Object.keys(object).forEach(function(key) {
if (!ignore_search_properties
// Warning: for old environment, may need ignore some keys
|| !(key in ignore_search_properties)) {
delete object[key];
}
});
return this;
}
// {Object}this parameter hash to String
// https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/toString
function parameters_toString(options) {
var charset;
if (typeof options === 'string') {
charset = options;
options = Object.create(null);
} else {
options = library_namespace.setup_options(options);
charset = options.charset;
}
if (charset === undefined) {
// console.trace([ this, this[KEY_URL] ]);
charset = this.charset || this[KEY_URL] && this[KEY_URL].charset;
}
var search = [], key;
function append(value) {
if (library_namespace.is_debug(9) && typeof value !== 'string'
&& typeof value !== 'number' && value !== NO_EQUAL_SIGN) {
try {
library_namespace.debug({
T : [
// gettext_config:{"id":"set-$1-to-a-non-string-$2"}
'設定 %1 成非字串之參數:%2',
typeof JSON === 'object' ? JSON.stringify(key)
: String(key),
typeof JSON === 'object' ? JSON
.stringify(value) : String(value) ]
}, 1, 'parameters_toString.append');
} catch (e) {
// TypeError: Converting circular structure to JSON
}
}
// console.trace([ key, value ]);
try {
search.push(value === NO_EQUAL_SIGN ? key : key + '='
+ encode_URI_component(String(value), charset));
// console.trace(search);
} catch (e) {
library_namespace.error(e);
console.error(e);
console.trace([ key, value ]);
}
}
// console.trace([ this, charset ]);
for (var index = 0, key_list = Object.keys(this); index < key_list.length; index++) {
key = key_list[index];
if (ignore_search_properties && (key in ignore_search_properties)) {
// Warning: for old environment, may need ignore some keys
continue;
}
var value = this[key];
key = encode_URI_component(key, charset);
// console.trace(key + ' = ' + value);
if (!Array.isArray(value)) {
append(value);
} else if (Object.getOwnPropertyDescriptor(value, 'toString')) {
// assert: 自行定義 {Function}.toString()
append(value.toString());
} else {
value.forEach(append);
}
}
library_namespace.debug([ {
// gettext_config:{"id":"a-total-of-$1-parameters"}
T : [ '共%1個參數:', search.length ]
}, '<br />\n', search.map(function(parameter) {
return parameter.length > 400 ? parameter.slice(0,
//
library_namespace.is_debug(6) ? 2000 : 400) + '...' : parameter;
}).join('<br />\n') ], 9, 'parameters_toString');
search = search.join('&');
if (this[KEY_URL]) {
// @see URI.prototype.search
this[KEY_URL].search = search;
}
return search;
}
// @private
var KEY_hash = typeof Symbol === 'function' ? Symbol('hash') : '\0hash';
var KEY_URL = !Object.defineProperty[KEY_not_native]
&& typeof Symbol === 'function' ? Symbol('URL') : '\0URL';
// search_properties
Object.assign(Search_parameters.prototype, {
clean_parameters : search_clean_parameters,
set_parameters : search_set_parameters,
// valueOf
toString : parameters_toString
});
var ignore_search_properties;
if (Object.defineProperty[KEY_not_native]) {
// 皆已採用 Object.keys(), Object.entries()
// Object.keys() 不會取得 Search_parameters.prototype 的屬性。
// ignore_search_properties = Object.clone(Search_parameters.prototype);
ignore_search_properties = Object.create(null);
// @ WScript.exe 會採用 (key in ignore_search_properties) 的方法,
// 因此 KEY_URL 必須是 {String}。
if (typeof KEY_URL !== 'string')
KEY_URL = String(KEY_URL);
ignore_search_properties[KEY_URL] = true;
// alert(Object.keys(ignore_search_properties));
}
_.Search_parameters = Search_parameters;
function is_Search_parameters(value) {
return value instanceof Search_parameters;
}
_.is_Search_parameters = is_Search_parameters;
// --------------------------------
// 有缺陷的 URL()
function defective_URL(url) {
// Object.assign() will not copy toString:URI_toString()
// Object.assign(this, URI(url));
return new URI(url, null, {
// 盡可能模擬 W3C URL()
as_URL : true
});
}
// 有缺陷的 URLSearchParams()
function defective_URLSearchParams(search_string, options) {
// library_namespace.debug(search_string);
// Warning: new Map() 少了許多必要的功能! 不能完全替代!
var search = Object.entries(
//
new Search_parameters(search_string, options));
if (ignore_search_properties) {
search = search.filter(function(entry) {
return !(entry[0] in ignore_search_properties);
});
}
// library_namespace.info(search.length);
// alert(Array.isArray(search));
try {
Map.call(this, search);
if (!this.forEach)
throw 1;
return;
} catch (e) {
// node.js 0.11: Constructor Map requires 'new'
}
search = new Map(search);
// Copy all methods
Object.assign(search, defective_URLSearchParams.prototype);
return search;
}
// https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Objects/Inheritance
Object.assign(defective_URLSearchParams.prototype = Object
.create(Map.prototype), {
constructor : defective_URLSearchParams,
clean : function clean() {
var search = this;
var keys = Array.from(this.keys());
keys.forEach(function(key) {
search['delete'](key);
});
return this;
},
// URLSearchParams() 會存成字串,不會保留原先的資料結構。
set : function set(key, value) {
key = String(key);
value = String(value);
Map.prototype.set.call(this, key, value);
},
append : function append(key, value) {
key = String(key);
value = String(value);
// defective_URLSearchParams.prototype.toString
if (this.has(key)) {
var original_value = Map.prototype.get.call(this, key);
if (Array.isArray(original_value)) {
original_value.push(value);
} else {
Map.prototype.set
.call(this, key, [ original_value, value ]);
}
} else {
Map.prototype.set.call(this, key, value);
}
},
// Return the first one
get : function get(key) {
key = String(key);
var original_value = Map.prototype.get.call(this, key);
if (Array.isArray(original_value))
return original_value[0];
return original_value;
},
getAll : function getAll(key) {
key = String(key);
if (!this.has(key))
return [];
var original_value = Map.prototype.get.call(this, key);
if (Array.isArray(original_value))
return original_value;
return [ original_value ];
},
// 注意: 本 library 模擬之 URLSearchParams.prototype.toString 只能得到等價
// href,不完全相同。
toString : function toString() {
// defective_URLSearchParams.prototype.toString
var list = [];
this.forEach(function(value, key) {
// console.trace([ value, key ]);
key = encodeURIComponent(key) + '=';
if (Array.isArray(value)) {
value.forEach(function(v) {
list.push(key + encodeURIComponent(String(v)));
});
} else {
list.push(key + encodeURIComponent(String(value)));
}
});
return list.join('&');
}
});
// ------------------------------------------------------------------------
/**
* <code>
https://pubs.opengroup.org/onlinepubs/007908799/xbd/notation.html
The following table lists escape sequences and associated actions on display devices capable of the action.
https://pubs.opengroup.org/onlinepubs/007908799/xcu/printf.html
the escape sequences listed in the XBD specification, File Format Notation (\\, \a, \b, \f, \n, \r, \t, \v), which will be converted to the characters they represent
</code>
*/
var to_file_name_escape_sequences = {
'\n' : '\n',
'\r' : '\r',
'\t' : '\t'
};
/**
* 正規化 file name,排除會導致 error 的字元。 normalize file name
*
* @param {String}file_name
* file name
* @param {Boolean}do_escape
* 是否作 escape
*
* @returns {String}正規化 file name
*
* @see data.is_matched.string_pre_handler(),
* application.storage.file.get_file_name()
* @since 2012/10/13 13:31:21
*/
function to_file_name(file_name, do_escape) {
file_name = file_name.trim();
// 處理 illegal file name. 去除檔名中不被允許的字元。
// http://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
if (do_escape)
file_name = file_name
// 若本來就含有這些 functional 字元的情況,須作 escape。
.replace(/([\/|?*])/g, '\$1');
// else: make result readable.
file_name = file_name.replace(/[\0-\x1f]/g, function($0) {
if ($0 in to_file_name_escape_sequences)
return to_file_name_escape_sequences[$0];
var c = $0.charCodeAt(0).toString(16), l = c.length;
if (l === 1 || l === 3)
c = '0' + c;
else if (4 < l && l < 8)
c = '000'.slice(l - 5) + c;
return '\' + (c.length === 2 ? 'x' : 'u') + c;
});
file_name = file_name
// functional characters in RegExp.
.replace(/[\\\/|?*]/g, function($0) {
return {
'\\' : '\',
// Fraction slash '⁄'
// Division slash '∕'
'/' : '/',
'|' : '|',
'?' : '?',
'*' : '*'
}[$0];
});
file_name = file_name
// normalize string.
// 全寬引號(fullwidth quotation mark)["]
.replace(/"([^"'“”"]+)"/g, '“$1”').replace(/"/g, '”')
.replace(/:/g, ':').replace(/</g, '<').replace(/>/g, '>');
if (library_namespace.platform.is_Windows()) {
file_name = file_name
// 若是以 "." 結尾,在 Windows 7 中會出現問題,無法移動或刪除。
.replace(/(.)\.$/, '$1._');
}
// 限制長度.
// http://en.wikipedia.org/wiki/Filename#Length_restrictions
// http://msdn.microsoft.com/en-us/library/aa365247.aspx#maxpath
// https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
if (file_name.length > 255) {
library_namespace
.warn('to_file_name: The file name will be cutted! ['
+ file_name.length + '] [' + file_name + ']');
file_name = file_name.slice(0, 255);
}
return file_name;
}
_// JSDT:_module_
.to_file_name = to_file_name;
var
/**
* 取得副檔名。
*
* @type {RegExp}
*/
PATTERN_extension = /\.([a-z\d\-]+)$/i,
/**
* 一般字元,非特殊字元之 folder 名。<br />
* [...]{1,512}<br />
*
* @type {RegExp}
*/
PATTERN_ordinary_folder_name = /^[a-z\d ~!@#$%^&()-_+={}[],.]+[\\\/]$/i,
TARGET_FILE_EXISTS = new Error, NO_EXECUTABLE_FILE = new Error, NOT_YET_IMPLEMENTED = new Error;
TARGET_FILE_EXISTS.name = 'TARGET_FILE_EXISTS';
NO_EXECUTABLE_FILE.name = 'NO_EXECUTABLE_FILE';
NOT_YET_IMPLEMENTED.name = 'NOT_YET_IMPLEMENTED';
/**
* 取得 URI/取得器
*
* @param {Function}[module]
* use what module/command to get.
* @returns getter
* @throws No
* module to use.
*/
function URI_accessor(module, setting) {
if (!module)
if (URI_accessor.default_module)
module = URI_accessor.default_module;
else {
// detect what module/command to use.
for (module in URI_accessor.module)
if (!URI_accessor.test_module(module)) {
URI_accessor.default_module = module;
break;
}
if (!URI_accessor.default_module)
module = undefined;
}
if ((module in URI_accessor.module)
&& library_namespace
.is_Function(module = URI_accessor.module[module]
(setting)))
return module;
throw new Error('No module' + (module ? ' [' + module + ']' : '')
+ ' to use!');
}
// return undefined: OK, others: error.
URI_accessor.test_module = function(module_name) {
library_namespace.debug('test module: [' + module_name + ']', 1,
'URI_accessor.test_module');
try {
get_WScript_object().WshShell.Run(module_name, 0, true);
} catch (e) {
// 若不存在此執行檔案,將 throw。
library_namespace.error(e);
return (e.number & 0xFFFF) === 2 ? NO_EXECUTABLE_FILE : e;
}
library_namespace.debug('test module: [' + module_name + ']: OK.', 1,
'URI_accessor.test_module');
};
/**
* 從 URI 抽取 file name
*
* @param URI
* URI
* @returns file name
* @throws decodeURIComponent
* error
*/
URI_accessor.extract_file_name = function(URI) {
// 須處理非標準之符號,可能會有 ' 之類的東西。因此對 #hash 之處理得放在 HTML_to_Unicode() 後面。
var m = URI.replace(/([^&])#.*/, '$1')
//
.match(/(([^\/\\]+)[\/\\]+)?([^\/\\]*)$/);
if (m) {
return URI_accessor.regularize_file_name(
// 因為 escape 會多出不必要符號,因此不 escape。
HTML_to_Unicode(m[3] || m[1]), false);
}
};
// 正規化 file name
URI_accessor.regularize_file_name = to_file_name;
URI_accessor.setting = {
// referer : '',
window_style : function() {
// 0: hidden, 1: show, 2: Activate & minimize,
// 7: Minimize. The active window remains active.
return library_namespace.is_debug() ? 1 : 0;
},
// 指定當檔名具有特殊字元時之暫存檔。
// temporary_file : 'URI_accessor.tmp',
// temporary_file : 'C:\\URI_accessor.tmp',
// temporary_file : function(URI, save_to, FSO) { return
// temporary_file_path; },
// temporary_file : function(URI, save_to, FSO) { return save_to +
// '.unfinished'; },
temporary_file : function(URI, save_to) {
var extension = save_to.match(PATTERN_extension),
// 應該用 save_to 的 md5 值。
hash_id = Math.ceil(Math.random() * 1e9);
return 'URI_accessor.'
+ (extension ? 'temp.' + hash_id + extension[0] : hash_id
+ '.temp');
},
// do not overwrite:
// target_exist : false
// when target file exists, save to ..
// target_exist : function(target, FSO) { return save_to || skip; },
// when target file exists, rename old to ..
// target_exist : [ save new to, rename old to ],
target_exist : [],
user_agent : 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.29 Safari/537.22'
};
URI_accessor.target_exist = {
rename : function(target, FSO) {
var proto = target + '.old', move_to = proto, i = 0;
// TODO: when error occurred..
while (FSO.FileExists(move_to))
move_to = proto + ++i;
try {
FSO.MoveFile(target, move_to);
} catch (e) {
}
return target;
},
// save new to, rename old to
move : function(save_to, move_to, FSO) {
if (!move_to)
move_to = save_to + '.old';
if (FSO.FileExists(move_to))
try {
FSO.DeleteFile(move_to);
} catch (e) {
}
try {
FSO.MoveFile(save_to, move_to);
} catch (e) {
}
return save_to;
}
};
/**
* <code>
default command modules.
取得方法:
wget
curl
lftp
prozilla
puf
CuteFTPPro.TEConnection
XMLHttp
Msxml2.DOMDocument
InternetExplorer.Application
WinHttp.WinHttpRequest.5.1
深入挖掘Windows腳本技術(5) - 網頁特效代碼 - IT學習者 http://www.itlearner.com/Article/2008/4024_5.shtml
獲取軟件下載的真實地址!再談獲取Response.redirect重定向的URL-asp教程-asp學習網 http://www.aspxuexi.com/xmlhttp/example/2006-8-8/852.htm
http://www.360doc.com/content/11/0108/11/597197_84935972.shtml
從msdn得知,WinHttp.WinHttpRequest.5.1 是 msxml 4.0 的底層對象,也就是說 XMLHTTP/ServerXMLHTTP 也是在它的基礎上封裝而來。
XMLHTTP組件在處理包含Location頭的302消息時太智能了,直接跳轉到最後的頁面
TODO:
先知道 file size
use $PATH
</code>
*/
URI_accessor.module = {
curl : function(user_setting) {
// http://curl.haxx.se/docs/httpscripting.html
// The ORDINAL 2821 could not be located in the dynamic link library
// LIBEAY32.dll
// This is caused by a conflict in the version of LIBEAY32.DLL
// Solution: install the latest version of Win32 OpenSSL
// http://www.slproweb.com/products/Win32OpenSSL.html
if (false) {
library_namespace.debug('URI_accessor.setting.temporary_file:'
+ URI_accessor.setting.temporary_file, 2,
'URI_accessor.module.curl');
library_namespace.debug('user_setting.temporary_file:'
+ user_setting.temporary_file, 2,
'URI_accessor.module.curl');
}
var setting = new library_namespace.setting_pair(Object
.create(null), URI_accessor.setting, user_setting),
//
value = setting('user_agent'),
//
tmp = setting('cookie') || setting('cookie_file'),
//
command_array = [
'curl --remote-time --insecure --compressed '
+ (library_namespace.is_debug(2) ? '-v ' : '')
+ (setting('additional_options') ? setting('additional_options')
+ ' '
: '')
// --cookie STRING/FILE String or file to read
// cookies from (H)
+ (tmp ? '--cookie "' + tmp + '" ' : '')
+ ((tmp = setting('cookie_file')
|| setting('cookie')) ? '--cookie-jar "'
+ tmp + '" ' : '') + '--output "', '',
(value ? '" --user-agent "' + value : '') + '"' ];
if (setting('POST')) {
setting('POST_index', command_array.length + 1);
command_array.push(' --data "', '', '"');
}
command_array[command_array.length - 1] += ' --referer "';
tmp = '" "';
if (value = setting('referer')) {
library_namespace.debug([ 'referer: ', {
a : value,
href : value
} ], 2, 'URI_accessor.module.curl');
command_array[command_array.length - 1] += value + tmp;
} else
setting('referer_index', command_array.length), command_array
.push('', tmp);
command_array.push('', '"');
library_namespace.debug('command_array: ' + command_array, 2,
'URI_accessor.module.curl');
if (false)
library_namespace.debug('temporary_file: ['
+ (typeof setting('temporary_file')) + ']'
+ setting('temporary_file'), 2,
'URI_accessor.module.curl');
return URI_accessor.default_getter(setting, command_array,
URI_accessor.default_apply_command);
},
wget : function(user_setting) {
var setting = new library_namespace.setting_pair(Object
.create(null), URI_accessor.setting, user_setting), value = setting('user_agent'), tmp = '" "', command_array = [
'wget --timestamping --keep-session-cookies --no-check-certificate '
+ (library_namespace.is_debug(2) ? '-d ' : '')
+ (setting('additional_options') ? setting('additional_options')
+ ' '
: '') + '--output-document="', '',
(value ? '" --user-agent="' + value : '') + '"' ];
if (setting('POST')) {
setting('POST_index', command_array.length + 1);
command_array.push(' --post-data="', '', '"');
}
command_array[command_array.length - 1] += ' --referer="';
if (value = setting('referer')) {
library_namespace.debug([ 'referer: ', {
a : value,
href : value
} ], 2, 'URI_accessor.module.wget');
command_array[command_array.length - 1] += value + tmp;
} else
setting('referer_index', command_array.length), command_array
.push('', tmp);
command_array.push('', '"');
library_namespace.debug('command_array: ' + command_array, 2,
'URI_accessor.module.wget');
if (false)
library_namespace.debug('temporary_file: ['
+ (typeof setting('temporary_file')) + ']'
+ setting('temporary_file'), 2,
'URI_accessor.module.wget');
return URI_accessor.default_getter(setting, command_array,
URI_accessor.default_apply_command);
}
};
URI_accessor.default_apply_command = function(setting, command_array, URI,
save_to, temporary_file_used) {
command_array[1] = temporary_file_used || save_to;
command_array[command_array.length - 2] = URI;
var i;
if (i = setting('referer_index'))
command_array[i] = URI;
if (i = setting('POST_index'))
command_array[i] = setting('POST') || '';
};
URI_accessor.default_getter = function(setting, command_array,
apply_command) {
if (false)
library_namespace.debug('get_WScript_object: ['
+ (typeof get_WScript_object) + ']' + get_WScript_object,
2, 'URI_accessor.default_getter');
var WSO = get_WScript_object();
if (false)
library_namespace.debug('WSO: [' + (typeof WSO) + ']' + WSO, 2,
'URI_accessor.default_getter');
if (!WSO) {
library_namespace.warn('No WScript objects got!');
return;
}
var WshShell = WSO.WshShell, FSO = WSO.FSO,
//
normalize_directory = function(id) {
var directory = setting(id);
if (directory && !/[\\\/]$/.test(directory))
setting(id, directory + library_namespace.env.path_separator);
}, normalize_function = function(id) {
if (typeof setting(id) !== 'function')
setting(id, undefined);
},
//
window_style = setting('window_style'), temporary_file = setting('temporary_file');
library_namespace.debug('temporary_file: [' + (typeof temporary_file)
+ ']' + temporary_file, 2, 'URI_accessor.default_getter');
WSO = null;
var getter = function(URI, save_to) {
var start_time = new Date, result, temporary_file_used, tmp;
if (library_namespace.is_Object(save_to)) {
setting(save_to);
normalize_directory('directory');
normalize_function('callback');
save_to = setting('save_to');
}
// 若沒有輸入 save_to,從 URI 取得。
if (!save_to)
save_to = URI_accessor.extract_file_name(URI);
// 得放在偵測 temporary file 之前,預防 directory
// 包含非普通的(unordinary)字符。
if (tmp = setting('directory'))
save_to = tmp + save_to;
if (FSO.FileExists(save_to) && ('target_exist' in setting())) {
if (Array.isArray(tmp = setting('target_exist')))
t