mirror of
				https://scm.univ-tours.fr/22107988t/rappaurio-sae501_502.git
				synced 2025-11-04 05:15:23 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			2035 lines
		
	
	
		
			64 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			2035 lines
		
	
	
		
			64 KiB
		
	
	
	
		
			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 + ']');
 | 
						||
		}
 | 
						||
 | 
						||
		// 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')))
 | 
						||
					tmp = URI_accessor.target_exist.move(tmp[0] || save_to,
 | 
						||
							tmp[1], FSO);
 | 
						||
				else if (typeof tmp === 'string' && tmp.charAt(0) === '*')
 | 
						||
					tmp = URI_accessor.target_exist[tmp.slice(1)];
 | 
						||
 | 
						||
				if (typeof tmp === 'function')
 | 
						||
					tmp = tmp(save_to, FSO);
 | 
						||
 | 
						||
				if (typeof tmp === 'string' && tmp)
 | 
						||
					save_to = tmp;
 | 
						||
				else {
 | 
						||
					library_namespace
 | 
						||
							.debug(
 | 
						||
									'Skip ['
 | 
						||
											+ URI
 | 
						||
											+ ']: target file ['
 | 
						||
											+ save_to
 | 
						||
											+ '] exists and target_exist of setting refused rename or overwrite.',
 | 
						||
									2, 'URI_accessor.default_getter.getter');
 | 
						||
					result = TARGET_FILE_EXISTS;
 | 
						||
					if (tmp = setting('callback'))
 | 
						||
						tmp(save_to, URI, result);
 | 
						||
					return result;
 | 
						||
				}
 | 
						||
			}
 | 
						||
 | 
						||
			// 只有非常用字母才需要 temporary file。
 | 
						||
			if (temporary_file && !/^[\x20-\x7e]+$/.test(save_to)) {
 | 
						||
				temporary_file_used = typeof temporary_file === 'function' ? temporary_file(
 | 
						||
						URI, save_to, FSO)
 | 
						||
						: temporary_file;
 | 
						||
				library_namespace.debug('temporary file: ['
 | 
						||
						+ temporary_file_used + ']←[' + temporary_file + ']',
 | 
						||
						2, 'URI_accessor.default_getter.getter');
 | 
						||
			}
 | 
						||
 | 
						||
			library_namespace.debug('Downloading [<a href="'
 | 
						||
					+ URI
 | 
						||
					+ '" target="_blank">'
 | 
						||
					+ URI
 | 
						||
					+ '</a>]'
 | 
						||
					+ (temporary_file_used ? '→[' + temporary_file_used + ']'
 | 
						||
							: '') + '→[' + save_to + ']..', 1,
 | 
						||
					'URI_accessor.default_getter.getter');
 | 
						||
 | 
						||
			apply_command(setting, command_array, URI, save_to,
 | 
						||
					temporary_file_used);
 | 
						||
			library_namespace.debug(
 | 
						||
					'Execute: [' + command_array.join('') + ']', 2,
 | 
						||
					'URI_accessor.default_getter.getter');
 | 
						||
			library_namespace.debug('WshShell: [' + (typeof WshShell) + ']'
 | 
						||
					+ WshShell, 3, 'URI_accessor.default_getter.getter');
 | 
						||
 | 
						||
			try {
 | 
						||
				// WshShell.Run("cmd.exe /c set > env.txt", 1, true);
 | 
						||
				result = WshShell.Run(command_array.join(''),
 | 
						||
				// Window Style
 | 
						||
				1,
 | 
						||
				// typeof window_style === 'function' ? window_style() :
 | 
						||
				// window_style,
 | 
						||
				// true: 等調用的程序退出後再執行。
 | 
						||
				true);
 | 
						||
				if (result) {
 | 
						||
					// result = EXIT CODE
 | 
						||
					this.lastest_errorno = result;
 | 
						||
					save_to = '[error] ' + save_to;
 | 
						||
				}
 | 
						||
 | 
						||
				if (temporary_file_used)
 | 
						||
					if (FSO.FileExists(temporary_file_used))
 | 
						||
						// 出問題還是照搬。
 | 
						||
						// 需注意出問題過,原先就存在的情況。
 | 
						||
						FSO.MoveFile(temporary_file_used, save_to);
 | 
						||
					else
 | 
						||
						library_namespace
 | 
						||
								.warn('temporary file does not exists: ['
 | 
						||
										+ temporary_file_used + ']');
 | 
						||
 | 
						||
				library_namespace.debug('['
 | 
						||
						+ URI
 | 
						||
						+ ']→[<a href="'
 | 
						||
						+ save_to
 | 
						||
						+ '" target="_blank">'
 | 
						||
						+ save_to
 | 
						||
						+ '</a>] @ '
 | 
						||
						+ Math.round((new Date - start_time) / 1000)
 | 
						||
						+ ' sec '
 | 
						||
						+ (result ? ', <em>error code ' + result + '</em>.'
 | 
						||
								: ''));
 | 
						||
 | 
						||
			} catch (e) {
 | 
						||
				// library_namespace.error(e);
 | 
						||
				if ((e.number & 0xFFFF) === 2)
 | 
						||
					// 若不存在此執行檔案,將 throw。
 | 
						||
					// '找不到執行檔: wget。您可能需要安裝此程式後再執行。'
 | 
						||
					// http://users.ugent.be/~bpuype/wget/
 | 
						||
					result = NO_EXECUTABLE_FILE;
 | 
						||
				else {
 | 
						||
					library_namespace.error(e);
 | 
						||
					result = e;
 | 
						||
				}
 | 
						||
			}
 | 
						||
 | 
						||
			if (tmp = setting('callback'))
 | 
						||
				tmp(save_to, URI, result, setting);
 | 
						||
			return result;
 | 
						||
		};
 | 
						||
 | 
						||
		if (false)
 | 
						||
			library_namespace.debug('WshShell: [' + (typeof WshShell) + ']'
 | 
						||
					+ WshShell, 2, 'URI_accessor.default_getter');
 | 
						||
 | 
						||
		// binding prototype
 | 
						||
		if (false)
 | 
						||
			library_namespace.set_method(URI_accessor.prototype,
 | 
						||
					getter.prototype);
 | 
						||
		else
 | 
						||
			getter.prototype = URI_accessor.prototype;
 | 
						||
 | 
						||
		normalize_directory('directory');
 | 
						||
		normalize_function('callback');
 | 
						||
 | 
						||
		return getter;
 | 
						||
	};
 | 
						||
 | 
						||
	library_namespace.set_method(URI_accessor.prototype, {
 | 
						||
		// TODO
 | 
						||
		list : function(URI_array, index_URI, index_save_to) {
 | 
						||
			throw NOT_YET_IMPLEMENTED;
 | 
						||
		},
 | 
						||
		process : function(index) {
 | 
						||
			throw NOT_YET_IMPLEMENTED;
 | 
						||
		}
 | 
						||
	});
 | 
						||
 | 
						||
	_// JSDT:_module_
 | 
						||
	.URI_accessor = URI_accessor;
 | 
						||
 | 
						||
	/**
 | 
						||
	 * get URI / URI 取得器.
 | 
						||
	 * 
 | 
						||
	 * @example <code>
 | 
						||
	 * get_URI('http://lyrics.meicho.com.tw/game/index.htm');
 | 
						||
	 * </code>
 | 
						||
	 * 
 | 
						||
	 * @param {String}URI
 | 
						||
	 *            URI to get
 | 
						||
	 * @param {String}[save_to]
 | 
						||
	 *            path save to
 | 
						||
	 * 
 | 
						||
	 * @returns error
 | 
						||
	 */
 | 
						||
	function get_URI(URI, save_to, setting) {
 | 
						||
		if (get_URI.getter && (!setting
 | 
						||
		// 有可能使用相同的 setting object,但僅改變了部分內容,如 temporary_file。
 | 
						||
		// || get_URI.setting === setting
 | 
						||
		))
 | 
						||
			return get_URI.getter(URI, save_to);
 | 
						||
 | 
						||
		var i, getter, result;
 | 
						||
		for (i in URI_accessor.module) {
 | 
						||
			result = (getter = new URI_accessor(i, setting))(URI, save_to);
 | 
						||
			if (result !== NO_EXECUTABLE_FILE) {
 | 
						||
				// cache default setting
 | 
						||
				get_URI.getter = getter;
 | 
						||
				get_URI.setting = setting;
 | 
						||
				break;
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		return result;
 | 
						||
	}
 | 
						||
 | 
						||
	_// JSDT:_module_
 | 
						||
	.get_URI = get_URI;
 | 
						||
 | 
						||
	// @since 2021/2/27 6:29:0 remove get_video() for 下載 Youtube 影片檔案與播放清單:
 | 
						||
	// 年久失修且網站改版,無法使用且沒想要維護了。
 | 
						||
 | 
						||
	/**
 | 
						||
	 * 自動組態設定檔/自動設定網址
 | 
						||
	 * 
 | 
						||
	 * url: 完整的URL字串, host: 在 URL字串中遠端伺服器的網域名稱。該參數祇是為了 方便而設定的,是與URL在 :// 和 /
 | 
						||
	 * 中的文字是一模 一樣。但是傳輸阜(The port number)並不包含其中 。當需要的時候可以從URL字串解讀出來。
 | 
						||
	 * 
 | 
						||
	 * <code>
 | 
						||
	http://contest.ks.edu.tw/syshtml/proxy-pac.html
 | 
						||
	Proxy Auto-Config File Format	http://lyrics.meicho.com.tw/proxy.pac
 | 
						||
	http://openattitude.irixs.org/%E7%BC%96%E5%86%99-pac-proxy-auto-config-%E6%96%87%E4%BB%B6/
 | 
						||
	http://www.atmarkit.co.jp/fwin2k/experiments/ieproxy/ieproxy_01.html
 | 
						||
	http://www.cses.tcc.edu.tw/~chihwu/proxy-pac.htm
 | 
						||
	you should configure your server to map the .pac filename extension to the MIME type:
 | 
						||
		application/x-ns-proxy-autoconfig
 | 
						||
 | 
						||
	網域名稱之長度,經punycode轉碼後,不得超過63字元,大約二十個中文字以內。
 | 
						||
 | 
						||
	FindProxyForURL 將會傳回一個描寫Proxy組態設定的單一字串。假如該字串為空字串,則表示瀏覽器不使用 Proxy 伺服器。
 | 
						||
	假如有多個代理伺服器設定同時存在,則最左邊的設定將第一個使用,直 到瀏覽器無法建立連線才會更換到第二個設定。而瀏覽器將會在30分鐘後 自動對於先前無回應的 PROXY 伺服器重新連線。而瀏覽器將會於一個小時 後自動再連線一次(每一次的重新連線都會增加30分鐘)。
 | 
						||
	如果說所有的 PROXY 伺服器都當掉了,也沒有將 DIRECT 設定在 .pac 檔 案,那麼瀏覽器在嘗試建立連線 20 分鐘後將會詢問是否要暫時忽略 Proxy 服器直接存取網路,下一次詢問的時間則是在 40 分鐘後(注意!每一次 詢問都會增加20分鐘)
 | 
						||
 | 
						||
	http://www.microsoft.com/technet/prodtechnol/ie/ieak/techinfo/deploy/60/en/corpexjs.mspx?mfr=true
 | 
						||
	The isInNet, isResolvable, and dnsResolve functions query a DNS server.
 | 
						||
	The isPlainHostName function checks to see if there are any dots in the hostname. If so, it returns false; otherwise, the function returns true.
 | 
						||
	The localHostOrDomainIs function is executed only for URLs in the local domain.
 | 
						||
	The dnsDomainIs function returns true if the domain of the hostname matches the domain given.
 | 
						||
 | 
						||
	DIRECT - 不調用代理,直接連接
 | 
						||
	PROXY host:port - 調用指定代理(host:port)
 | 
						||
	SOCKS host:port - 調用指定SOCKS代理(host:port)
 | 
						||
	如果是選用由分號分割的多塊設置,按照從左向右,最左邊的代理會被最優先調用,除非瀏覽器無法成功和proxy建立連接,那麼下一個配置就會被調 用。如果瀏覽器遇到不可用的代理服務器,瀏覽器將在30分鐘後自動重試先前無響應的代理服務器,一個小時後會再次進行嘗試,依此類推,每次間隔時間為 30 分鐘。
 | 
						||
	</code>
 | 
						||
	 */
 | 
						||
	function FindProxyForURL(url, host) {
 | 
						||
		var lch = host.toLowerCase();
 | 
						||
 | 
						||
		// isPlainHostName(lch) || isInNet(lch,"192.168.0.0","255.255.0.0") ||
 | 
						||
		// isInNet(lch,"127.0.0.0","255.255.0.0") || dnsDomainIs(lch,".tw")
 | 
						||
		// ?"DIRECT";
 | 
						||
		return (
 | 
						||
		/**
 | 
						||
		 * <code>
 | 
						||
		//dnsDomainIs(lch,"holyseal.net") || dnsDomainIs(lch,".fuzzy2.com") ? "PROXY 211.22.213.114:8000; DIRECT":	//	可再插入第二、三順位的proxy
 | 
						||
		http://www.cybersyndrome.net/
 | 
						||
 | 
						||
		http://www.publicproxyservers.com/page1.html
 | 
						||
		curl --connect-timeout 5 -x 219.163.8.163:3128 http://www.getchu.com/ | grep Getchu.com
 | 
						||
		curl --connect-timeout 5 -x 64.34.113.100:80 http://www.getchu.com/ | grep Getchu.com
 | 
						||
		curl --connect-timeout 5 -x 66.98.238.8:3128 http://www.getchu.com/ | grep Getchu.com
 | 
						||
 | 
						||
		dnsDomainIs(lch, ".cn") || dnsDomainIs(lch, "pkucn.com") ? "PROXY proxy.hinet.net:80; DIRECT" :	//	2009/8/16 14:20:32	用 HiNet 網際網路 Proxy Server 上大陸網速度還滿快的	http://www.ltivs.ilc.edu.tw/proxy/proxy/hinet.htm
 | 
						||
		dnsDomainIs(lch, ".getchu.com") ? "PROXY 219.163.8.163:3128; PROXY 64.34.113.100:80; PROXY 66.98.238.8:3128; DIRECT" :
 | 
						||
		dnsDomainIs(lch, ".minori.ph") ? "PROXY 219.94.198.110:3128; PROXY 221.186.108.237:80; DIRECT" :	//	Japan Distorting Open Proxy List	http://www.xroxy.com/proxy--Distorting-JP-nossl.htm
 | 
						||
		//	slow:	http://www.cybersyndrome.net/country.html
 | 
						||
		dnsDomainIs(lch, ".tactics.ne.jp") ? "PROXY 202.175.95.171:8080; PROXY 203.138.90.141:80; DIRECT" :
 | 
						||
		dnsDomainIs(lch,".ys168.com")		? "PROXY 76.29.160.230:8000; DIRECT":	//	永硕E盘专业网络硬盘服务
 | 
						||
		</code>
 | 
						||
		 */
 | 
						||
		dnsDomainIs(lch, "erogamescape.dyndns.org")
 | 
						||
		//
 | 
						||
		? "PROXY 211.22.213.114:8000; DIRECT"
 | 
						||
		// http://www.twnic.net.tw/proxy.pac 將中文網域名稱轉成英文網域名稱
 | 
						||
		// :/^[a-z\.\d_\-]+$/.test(lch)?"DIRECT":"PROXY
 | 
						||
		// dnsrelay.twnic.net.tw:3127"
 | 
						||
		: "DIRECT");
 | 
						||
	}
 | 
						||
 | 
						||
	// http://help.globalscape.com/help/cuteftppro8/
 | 
						||
	// setupCuteFTPSite[generateCode.dLK]='parse_URI';
 | 
						||
	function setupCuteFTPSite(targetS, site) {
 | 
						||
		if (typeof targetS === 'string')
 | 
						||
			targetS = new URI(targetS, {
 | 
						||
				protocol : 'ftp:'
 | 
						||
			});
 | 
						||
		if (!targetS)
 | 
						||
			return;
 | 
						||
 | 
						||
		if (site) {
 | 
						||
			try {
 | 
						||
				site.Disconnect();
 | 
						||
			} catch (e) {
 | 
						||
			}
 | 
						||
			try {
 | 
						||
				site.Close();
 | 
						||
			} catch (e) {
 | 
						||
			}
 | 
						||
		}
 | 
						||
		try {
 | 
						||
			site = null;
 | 
						||
			site = WScript.CreateObject("CuteFTPPro.TEConnection");
 | 
						||
			site.Host = targetS.host;
 | 
						||
			// http://help.globalscape.com/help/cuteftppro8/setting_protocols.htm
 | 
						||
			// The default Protocol is FTP, however SFTP (SSH2), FTPS (SSL),
 | 
						||
			// HTTP, and HTTPS can also be used.
 | 
						||
			site.Protocol = targetS.protocol.replace(/:$/, '').toUpperCase();
 | 
						||
			if (targetS.username)
 | 
						||
				site.Login = targetS.username;
 | 
						||
			if (targetS.password)
 | 
						||
				site.Password = targetS.password;
 | 
						||
 | 
						||
			site.useProxy = "off";
 | 
						||
			site.TransferType = 'binary';
 | 
						||
 | 
						||
			site.Connect();
 | 
						||
 | 
						||
			// site.TransferURL("http://lyrics.meicho.com.tw/run.js");
 | 
						||
		} catch (e) {
 | 
						||
			return;
 | 
						||
		}
 | 
						||
		return site;
 | 
						||
	}
 | 
						||
 | 
						||
	/*
 | 
						||
	 * TODO: transferURL(remote URI,remote URI)
 | 
						||
	 */
 | 
						||
	// transferURL[generateCode.dLK]='parsePath,parse_URI,setupCuteFTPSite';
 | 
						||
	function transferURL(from_URI, to_URI) {
 | 
						||
		// var connectTo = from_URI.includes('://') ? from_URI : to_URI,
 | 
						||
		// CuteFTPSite = setupCuteFTPSite(connectTo);
 | 
						||
		var
 | 
						||
		// isD: use download (else upload)
 | 
						||
		isD, CuteFTPSite,
 | 
						||
		// lF: local file
 | 
						||
		lF,
 | 
						||
		// rP: remote path
 | 
						||
		rP;
 | 
						||
		if (from_URI.includes('://'))
 | 
						||
			isD = 0;
 | 
						||
		else if (to_URI.includes('://'))
 | 
						||
			isD = 1;
 | 
						||
		else
 | 
						||
			// local to local?
 | 
						||
			return;
 | 
						||
		lF = parsePath(isD ? to_URI : from_URI);
 | 
						||
		CuteFTPSite = setupCuteFTPSite(rP = new URI(isD ? from_URI : to_URI, {
 | 
						||
			protocol : 'ftp:'
 | 
						||
		}));
 | 
						||
		if (!CuteFTPSite || !CuteFTPSite.IsConnected)
 | 
						||
			return;
 | 
						||
 | 
						||
		// 到這裡之後,就認定 CuteFTPPro.TEConnection 的 initial 沒有問題,接下來若出問題,會嘗試重新
 | 
						||
		// initial CuteFTPPro.TEConnection.
 | 
						||
 | 
						||
		// initial local folder
 | 
						||
		try {
 | 
						||
			if (!site.LocalExists(site.LocalFolder = lF.directory))
 | 
						||
				site.CreateLocalFolder(lF.directory);
 | 
						||
		} catch (e) {
 | 
						||
			return;
 | 
						||
		}
 | 
						||
		site.RemoteFolder = rP.pathname;
 | 
						||
 | 
						||
		if (isD) {
 | 
						||
			site.Download(rP.fileName, lF.fileName || rP.fileName);
 | 
						||
			if (!site.LocalExists(lF.path))
 | 
						||
				return;
 | 
						||
		} else {
 | 
						||
			site.Upload(lF.fileName, rP.fileName || lF.fileName);
 | 
						||
			if (!site.LocalExists(rP.path))
 | 
						||
				return;
 | 
						||
		}
 | 
						||
 | 
						||
		// get list
 | 
						||
		// site.GetList('/OK', '', '%NAME');
 | 
						||
		// var l = site.GetResult().replace(/\r\n?/g, '\n').split('\n');
 | 
						||
 | 
						||
		// close
 | 
						||
		try {
 | 
						||
			site.Disconnect();
 | 
						||
		} catch (e) {
 | 
						||
		}
 | 
						||
		site.Close();
 | 
						||
 | 
						||
		return 1;
 | 
						||
	}
 | 
						||
 | 
						||
	// ---------------------------------------------------------------
 | 
						||
 | 
						||
	// var globalThis = library_namespace.env.global;
 | 
						||
	if (library_namespace.is_WWW(true) || library_namespace.platform.nodejs) {
 | 
						||
		library_namespace.set_method(library_namespace.env.global, {
 | 
						||
			// defective polyfill for W3C URL API, URLSearchParams()
 | 
						||
			URL : defective_URL,
 | 
						||
			URLSearchParams : defective_URLSearchParams
 | 
						||
		});
 | 
						||
 | 
						||
		// https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
 | 
						||
		// URLSearchParams_set_parameters(parameters)
 | 
						||
		URLSearchParams.prototype.set_parameters = function set_parameters(
 | 
						||
				parameters, options) {
 | 
						||
			if (Array.isArray(parameters))
 | 
						||
				parameters = parameters.join('&');
 | 
						||
			// assert: typeof parameters === 'object'
 | 
						||
			// || typeof parameters === 'string'
 | 
						||
			parameters = new URLSearchParams(parameters);
 | 
						||
 | 
						||
			var search = this;
 | 
						||
			parameters.forEach(function(value, key) {
 | 
						||
				search.append(key, value);
 | 
						||
			});
 | 
						||
			return this;
 | 
						||
		};
 | 
						||
	}
 | 
						||
 | 
						||
	return (_// JSDT:_module_
 | 
						||
	);
 | 
						||
}
 |