PageSourceSearch

https://sbisb.co.kr/sw/raon/cmn/TouchEnNx_exproto.js

js sbisb.co.kr collected 2026-09-24 09:30:04 UTC 74,942 bytes, 2,170 lines download raw bytes

1/**
2****************************************************
3TouchEnNx_exproto.js
4****************************************************
5| Version    ÀÛ¼ºÀÚ     ¼öÁ¤ÀÏ     º¯°æ»çÇ× 
6 ---------  -------  -----------  ----------
7| v1.0.0.17   °­³²ÁØ  2023.02.01 
8| v1.0.0.16   ÀÓ µ¿	  2021.03.25  
9| v1.0.0.15   °­³²ÁØ  2021.01.29
10| v1.0.0.14   °­³²ÁØ  2021.01.29
11| v1.0.0.13   ±è¹ÎÁ¤  2020.12.21 
12| v1.0.0.12   ÀÓ µ¿	  2020.11.30 
13| v1.0.0.11   ÀÓ µ¿	  2020.05.14     
14| v1.0.0.10   °­³²ÁØ  2019.06.11
15| v1.0.0.9    °­³²ÁØ  2019.04.01
16| v1.0.0.8    ¹é¼­¸°  2018.11.12
17| v1.0.0.7    °­³²ÁØ  2018.02.09
18| v1.0.0.6    ÇãÇý¸²  2018.01.10
19| v1.0.0.5    ÇãÇý¸²  2018.01.09 
20| v1.0.0.4    ÇãÇý¸²  2017.12.26   
21| v1.0.0.3    °­ÀÎ±Ô  2017.10.20    
22| v1.0.0.2    ¹é¼­¸°  2017.06.01   
23| v1.0.0.1    ¹é¼­¸°  2017.01.20      ÃÖÃÊ
24
25****************************************************
26 Copyright ©Ï RaonSecure Co., Ltd. 
27****************************************************
28**/
29
30var TOUCHENEX_CONST = {
31	"debug"			: TouchEnNxConfig.isDebug,	// console.log Ãâ·Â ¿©ºÎ
32	"debugAlert"	: TouchEnNxConfig.isDebug,	// exproto¿¡¼­ ¹ß»ýÇÏ´Â ¾Ë¸² ¿©ºÎ
33	"exEXObjName"	: "TOUCHENEX",	// _EX¸í
34	"frameName"		: "",
35	"browserInfo"	: "",
36	"OSInfo"		: "",
37	"pluginInfo"	: [],
38	"extabid"		: "",
39	"pluginCount"	: 0,
40	"isInstalled"	: false,
41	"tmpExtArr"		: [],
42	"json2Path"		: TouchEnNxConfig.path.cmn+"/json2.js",
43	"exDivName"		: "touchenexScrDiv",
44	"scrLength"		: 1000,
45	"cbTimeout"		: 5
46};
47
48/* 
49 * TOUCHENEX Loading
50 */
51var TOUCHENEX_LOADING = function( callback ){
52	
53	if(TOUCHENEX_CONST.pluginInfo.length <= 0){
54		alert("Ç÷¯±×ÀΠüũ¸¦ ½ÇÇàÇϽʽÿÀ.");
55		return;
56	} else {
57		if(TOUCHENEX_CHECK.chkInfoStatus.status){
58			var chk = true;
59			for(var i = 0; i < TOUCHENEX_CONST.pluginInfo.length; i++){
60				var pluginInfo = TOUCHENEX_CONST.pluginInfo[i];
61				try {
62					window[pluginInfo.exPluginName] = new window[TOUCHENEX_CONST.exEXObjName + "_EX"](pluginInfo);
63					exlog("_LOADING", pluginInfo.exPluginName + " = new " + TOUCHENEX_CONST.exEXObjName + "_EX(" + pluginInfo.exPluginInfo + ");");
64					exlog("_LOADING." + pluginInfo.exPluginName, window[pluginInfo.exPluginName]);
65				} catch (e) {
66					exlog("_LOADING [exception]", e);
67					//exalert("_LOADING [exception]", pluginInfo.exPluginName + "ÃʱâÈ­¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù.");
68					exalert("_LOADING [exception]", e);
69					chk = false;
70					break;
71				}
72			}
73			TOUCHENEX_CONST.isInstalled = chk;
74			if(callback){
75				setTimeout(function(){
76					// TODO
77					TOUCHENEX_UTIL.runCallback(callback, chk);
78				}, TOUCHENEX_CONST.cbTimeout);
79			}
80		} else {
81			alert("Ç÷¯±×ÀÎÀÌ ¸ðµÎ ¼³Ä¡µÇÁö ¾Ê¾Ò½À´Ï´Ù.");
82			if(callback) TOUCHENEX_UTIL.runCallback(callback, false);
83		}
84	}
85};
86
87/* 
88 * CrossEX InstallCheck
89 */
90var TOUCHENEX_CHECK = {
91	
92	chkCallback : "",
93	chkInfoStatus : {"status":false, info:[]},
94	chkCurrPluginCnt : 0,
95	chkStatus : 'stop',
96
97	check : function( pluginInfoArr, callback ){
98		
99		if(this.chkStatus == 'stop') {
100			this.chkStatus = 'run';
101		} else {
102			setTimeout(function(){TOUCHENEX_CHECK.check(pluginInfoArr, callback);}, 50);
103			return;
104		}
105		// TOUCHENEX_CONST Initialize
106		TOUCHENEX_CONST.frameName = TOUCHENEX_UTIL.findPath(self);
107		TOUCHENEX_CONST.OSInfo = TOUCHENEX_UTIL.getOSInfo();
108		TOUCHENEX_CONST.browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
109		exlog("_CONST.frameName", TOUCHENEX_CONST.frameName);
110		exlog("_CONST.OSInfo", TOUCHENEX_CONST.OSInfo);
111		exlog("_CONST.browserInfo", TOUCHENEX_CONST.browserInfo);
112
113		// generate IE tab id
114		if(!TOUCHENEX_CONST.extabid && (TOUCHENEX_UTIL.typeEX() || TOUCHENEX_UTIL.typePlugin())){
115			TOUCHENEX_CONST.extabid = TOUCHENEX_UTIL.createId();
116		}
117		
118		exlog("_CHECK.check", pluginInfoArr);
119		this.chkInfoStatus = {"status":false, info:[]};
120		this.chkCurrPluginCnt = 0;
121		
122		if(pluginInfoArr && pluginInfoArr.length > 0){
123			var infoCnt = pluginInfoArr.length;
124			TOUCHENEX_CONST.pluginInfo = [];
125			
126			for(var i = 0; i < infoCnt; i++){
127				if(TOUCHENEX_UTIL.isFirefox() && (Number(TOUCHENEX_UTIL.getBrowserVer()) < 55)){
128					pluginInfoArr[i].exExtensionInfo.exFirefoxExtVer = pluginInfoArr[i].exExtensionInfo.exFirefoxJpmExtVer;
129					pluginInfoArr[i].exExtensionInfo.exFirefoxExtDownURL = pluginInfoArr[i].exExtensionInfo.exFirefoxJpmExtDownURL;
130      	}
131
132				TOUCHENEX_CONST.pluginInfo.push(pluginInfoArr[i]);
133				var tmpInfo = {"name":pluginInfoArr[i].exPluginName};
134				if(TOUCHENEX_UTIL.typeExtension()){
135					tmpInfo.extension = false;
136				}
137				tmpInfo.EX = false;
138				tmpInfo.client = false;
139				tmpInfo.daemonVer = "";
140				tmpInfo.daemon = "";
141				this.chkInfoStatus.info.push(tmpInfo);
142				
143				// check spec
144				if(pluginInfoArr[i].checkSpec){
145					// check OS
146					if(!TOUCHENEX_UTIL.chkOS(TOUCHENEX_CONST.OSInfo, pluginInfoArr[i].reqSpec.OS)){
147						exlog("_CHECK.check", "not support OS");
148						if(pluginInfoArr[i].exErrSpec) TOUCHENEX_UTIL.runCallback(pluginInfoArr[i].exErrSpec, ['OS', pluginInfoArr[i].reqSpec.OS]);
149						this.chkStatus = "stop"; // chkStatus init
150						setTimeout(function(){callback(TOUCHENEX_CHECK.chkInfoStatus);}, 10);
151						return;
152					}
153					// check Browser
154					if(!TOUCHENEX_UTIL.chkBrowser(TOUCHENEX_CONST.browserInfo, pluginInfoArr[i].reqSpec.Browser)){
155						exlog("_CHECK.check", "not support Browser");
156						if(pluginInfoArr[i].exErrSpec) TOUCHENEX_UTIL.runCallback(pluginInfoArr[i].exErrSpec, ['BROW
156SER', pluginInfoArr[i].reqSpec.Browser]);
157						this.chkStatus = "stop"; // chkStatus init
158						setTimeout(function(){callback(TOUCHENEX_CHECK.chkInfoStatus);}, 10);
159						return;
160					}
161				}
162			}
163		} else {
164			if(TOUCHENEX_CONST.pluginInfo.length <= 0){
165				alert("Ç÷¯±×ÀÎ Á¤º¸°¡ ÇÊ¿äÇÕ´Ï´Ù.");
166				return;
167			}
168		}
169		
170		if(callback){
171			this.chkCallback = callback;
172		} else {
173			alert("ÄݹéÀÌ ÇÊ¿äÇÕ´Ï´Ù.");
174			return;
175		}
176		
177		TOUCHENEX_CONST.pluginCount = TOUCHENEX_CONST.pluginInfo.length;
178		exlog("_CONST.pluginInfo", TOUCHENEX_CONST.pluginInfo);
179		exlog("_CONST.pluginCount", TOUCHENEX_CONST.pluginCount);
180		
181		// generate exDiv
182		TOUCHENEX_UTIL.chkCrossEXDiv(TOUCHENEX_CONST);
183		
184		this.moduleCheck(0);
185	},
186	
187	moduleCheck : function( currPluginCnt ) {
188		
189		this.chkCurrPluginCnt = currPluginCnt;
190		
191		if(currPluginCnt >= TOUCHENEX_CONST.pluginCount){
192			var chk = true;
193			for(var i=0; i<TOUCHENEX_CONST.pluginCount; i++){
194				var currInstalled = true;
195				var currStatus = this.chkInfoStatus.info[i];
196				if(TOUCHENEX_UTIL.typeExtension()){
197					if(!currStatus.extension){
198						chk = false;
199						currInstalled = false;
200					}
201				}
202				if(!currStatus.EX){
203					chk = false;
204					currInstalled = false;
205				}
206				if(!currStatus.client){
207					chk = false;
208					currInstalled = false;
209				}
210				currStatus.isInstalled = currInstalled;
211			}
212			this.chkInfoStatus.status = chk;
213			exlog("_CHECK.moduleCheck.chkInfoStatus", this.chkInfoStatus);
214			TOUCHENEX_UTIL.runCallback(TOUCHENEX_CHECK.chkCallback, this.chkInfoStatus);
215			this.chkStatus = 'stop';
216			return;
217		}
218		
219		var pluginInfo = TOUCHENEX_CONST.pluginInfo[currPluginCnt];
220		//exlog("_CHECK.moduleCheck.currPluginCnt", currPluginCnt);
221		
222		
223		if(pluginInfo.exModuleName=="nxweb" && TOUCHENEX_UTIL.isLinux() ){
224			var checkCallback = "TOUCHENEX_CHECK.LXVersionCheck";
225			var bws = TOUCHENEX_UTIL.getBrowserInfo().browser.toUpperCase();
226			if(bws=='CHROME'){
227				bws = 0;
228			}else if(bws == 'FIREFOX'){
229				bws = 1;
230			}else if(bws == 'OPERA'){
231				bws = 2;
232			}else{
233				bws = 3;
234			}
235			url = "http://"+nxWebConfig.version.linux.url
236			url += ":"+nxWebConfig.version.linux.port;
237			url += "/"+checkCallback;
238			url += "&"+touchennxwebpolicy;
239			url += "&"+bws;
240			url += "&"+TOUCHENEX_UTIL.createId();
241			// getVersionÀ» Àç½ÇÇà½Ã¿¡ n°ªÀ» Àü¼Û
242			/*if(TOUCHENEX_CONST.isInstalled){
243				url += "&n=true";
244			}*/
245			exlog("_CHECK.moduleCheck.url", url);
246			this.loadScript(url);
247		} else if(TOUCHENEX_UTIL.typeEX()){
248			
249			var checkCallback = "TOUCHENEX_CHECK.EXVersionCheck";
250			var url = pluginInfo.exProtocolName + "://" + location.host + "/GetVersions";
251			url += "?callback=" + checkCallback;
252			url += "&m=" + pluginInfo.exModuleName;
253			url += "&tabid=" + TOUCHENEX_CONST.extabid;
254			url += "&hostid=" + encodeURIComponent(location.host);
255			url += "&lic=" + encodeURIComponent(pluginInfo.lic);
256			
257			// iframe ¼±¾ðÀÌ document.writeÀÎ °æ¿ì¿¡ ÇÑÇÏ¿© i=1 °ªÀ» Ãß°¡ÇÑ´Ù.
258			if(window.location.protocol == "https:") url += "&i=1&s=1";
259			
260			// getVersionÀ» Àç½ÇÇà½Ã¿¡ n°ªÀ» Àü¼Û
261			if(TOUCHENEX_CONST.isInstalled){
262				url += "&n=true";
263			}
264			exlog("_CHECK.moduleCheck.url", url);
265			this.loadScript(url);
266			
267		} else if(TOUCHENEX_UTIL.typeExtension()){
268			
269			var nativecall;
270			try {
271				nativecall = TOUCHENEX_UTIL.createFuncByName(pluginInfo.exExtHeader + "_nativecall");
272			} catch (e) {
273				exlog("_CHECK.moduleCheck.nativecall", "nativecall init");
274			}
275			
276			var url = {"cmd":"init", "exfunc":"get_extension_version", "callback":""};
277			exlog("_CHECK.moduleCheck.nativecall.param", url);
278			if(typeof nativecall == 'function') {
279				nativecall(url, function(version) {
280					TOUCHENEX_CHECK.extensionVersionCheck(version);
281				});
282			} else {
283				exlog("_CHECK.moduleCheck.nativecall","nativecall retry");
284				setTimeout(function(){
285					try {
286
287						nativecall = TOUCHENEX_UTIL.createFuncByName(pluginInfo.exExtHeader + "_nativecall");
288					} catch (e) {
289						exlog("_CHECK.moduleCheck.nativecall", "nativecall retry init");
290					}
291					if(typeof nativecall == 'function') {
292						nativecall(url, function(version) {
293							TOUCHENEX_CHECK.extensionVersionCheck(version);
294						});						
295					} else {
296						exlog("_CHECK.moduleCheck.nativecall [exception]","extension not load");
297						try{
298							TOUCHENEX_CHECK.extensionVersionCheck("-1");
299						}catch(e) {
300							exlog("_CHECK.moduleCheck.nativecall [exception]","extensionVersionCheck('-1')");
301						}
302					}
303				}, 300);
304			}
305			
306		} else if(TOUCHENEX_UTIL.typePlugin()) {
307			
308			navigator.plugins.refresh(false);
309			var EXNP = navigator.mimeTypes[pluginInfo.exNPMimeType];
310			
311			if (EXNP && EXNP.enabledPlugin){
312				// np plugin embed
313				if(!document.getElementById(pluginInfo.exNPPluginId)){
314					var exPlugin = document.createElement("embed");
315					exPlugin.setAttribute("id", pluginInfo.exNPPluginId);
316					exPlugin.setAttribute("type", pluginInfo.exNPMimeType);
317					exPlugin.setAttribute("tabid", TOUCHENEX_CONST.extabid);
318					exPlugin.setAttribute("width", "0");
319					exPlugin.setAttribute("height", "0");
320					document.body.appendChild(exPlugin);
321				}
322				
323				var verJSON = {"init" : "get_versions",
324					"m" : pluginInfo.exModuleName,
325					"origin" : location.origin,
326					"lic" : pluginInfo.lic
327				};
328				exlog("_CHECK.moduleCheck.nativecall.param", verJSON);
329				var npObj = document.getElementById(pluginInfo.exNPPluginId);
330				if(npObj) {
331					var npVersionInfo = {};
332					try {
333						if(typeof npObj.nativeCall == "function"){
334							npVersionInfo = npObj.nativeCall(JSON.stringify(verJSON));
335							TOUCHENEX_CHECK.npVersionCheck(npVersionInfo);
336						} else {
337							exlog("_CHECK.moduleCheck.nativeCall [exception]","nativeCall retry");
338							setTimeout(function(){
339								npObj = document.getElementById(pluginInfo.exNPPluginId); 
340								if(typeof npObj.nativeCall == "function"){
341									npVersionInfo = npObj.nativeCall(JSON.stringify(verJSON));
342									TOUCHENEX_CHECK.npVersionCheck(npVersionInfo);
343								} else {
344									if(TOUCHENEX_UTIL.isWin()){
345										location.reload();
346									} else {
347										exlog("_CHECK.moduleCheck.nativeCall [exception]","nativeCall cannot run retry");
348										setTimeout(function(){
349											npObj = document.getElementById(pluginInfo.exNPPluginId);
350											if(typeof npObj.nativeCall == "function"){
351												npVersionInfo = npObj.nativeCall(JSON.stringify(verJSON));
352												TOUCHENEX_CHECK.npVersionCheck(npVersionInfo);
353											} else {
354												exlog("_CHECK.moduleCheck.nativeCall [exception]","nativeCall cannot run fail");
355												if (parseInt(TOUCHENEX_UTIL.getBrowserVer())	>= 11) {
356													alert("TouchEn PCº¸¾È ÀÎÅÍ³Ý Ç÷¯±×ÀΠȰ¼ºÈ­ ¼³Á¤ÀÌ ÇÊ¿äÇÕ´Ï´Ù.");
357													top.location.href = "http://faq.touchen.co.kr/nxKey/page/plugin_set.htm";
358												}
359												//location.reload();
360											}
361										}, 3000);
362									}
363								}
364							}, 300);
365						}
366					} catch(e){
367						exalert("_CHECK.moduleCheck nativaCall getversion [exception]", e);
368						return;
369					}
370				} else {
371					exalert("_CHECK.moduleCheck [exception]", "embed ÅÂ±× »ý¼º ½ÇÆÐ");
372					return;
373				}
374			} else {
375				this.npVersionCheck("-1");
376			}
377		} else {
378			if(pluginInfo.exErrSpec) TOUCHENEX_UTIL.runCallback(pluginInfo.exErrSpec, ['BROW
378SER', pluginInfo.reqSpec.Browser]);
379			return;
380		}
381},
382
383	
384	EXVersionCheck : function( updateInfo ) {
385		
386		var pluginInfo = TOUCHENEX_CONST.pluginInfo[this.chkCurrPluginCnt];
387		
388		if(updateInfo) {
389			exlog("_CHECK.EXVersionCheck.updateInfo", updateInfo);
390			
391			// license check
392			if(typeof updateInfo.status !== "undefined" && updateInfo.status == false){
393				exlog("_CHECK.EXVersionCheck [license check]", pluginInfo.exPluginName + " license check FAIL");
394					TOUCHENEX_CHECK.setStatus("license", "", false, false, updateInfo.expire);
395			} else {
396				exlog("_CHECK.EXVersionCheck [license check]", pluginInfo.exPluginName + " license check SUCCESS");
397					TOUCHENEX_CHECK.setStatus("license", "", true, false, updateInfo.expire);
398			}
399			
400			// EX Version Diff
401			var exEXSvrVer;
402			exlog("_CHECK.EXVersionCheck", "EX version check");
403			exEXSvrVer = pluginInfo.exProtocolInfo.exWinProtocolVer;
404			
405			if(TOUCHENEX_UTIL.diffVersion(updateInfo.ex, exEXSvrVer)) {
406				
407				TOUCHENEX_CHECK.setStatus("EX", updateInfo.ex, true, false);
408				
409				// Client Version Diff
410				var currModuleInfoArr = updateInfo.m;
411				var currModuleVer;
412				for(var i = 0; i < currModuleInfoArr.length; i++){
413					var cm = currModuleInfoArr[i];
414					if(cm.name == pluginInfo.exModuleName){
415						currModuleVer = cm.version;
416						break;
417					}
418				}
419				var exModuleSvrVer;
420				if(TOUCHENEX_UTIL.isWin()){
421					if(TOUCHENEX_UTIL.getBrowserBit() == "64"){
422						exModuleSvrVer = pluginInfo.moduleInfo.exWin64Ver;
423					} else {
424						exModuleSvrVer = pluginInfo.moduleInfo.exWinVer;
425					}
426				} else if(TOUCHENEX_UTIL.isMac()){
427					exModuleSvrVer = pluginInfo.moduleInfo.exMacVer;
428				} else if(TOUCHENEX_UTIL.isLinux()){
429					exModuleSvrVer = pluginInfo.moduleInfo.exLinuxVer;
430				}
431				exlog("_CHECK.EXVersionCheck", "Client version check");
432				if(TOUCHENEX_UTIL.diffVersion(currModuleVer, exModuleSvrVer)) {
433					
434					// set installed
435					TOUCHENEX_CHECK.setStatus("client", currModuleVer, true, true);
436					
437				} else {
438					TOUCHENEX_CHECK.setStatus("client", currModuleVer, false, true);
439				}
440			} else {
441				TOUCHENEX_CHECK.setStatus("EX", updateInfo.ex, false, true);
442			}
443		} else {
444			exlog("_CHECK.EXVersionCheck", pluginInfo.exPluginName + " updateInfo Error");
445			TOUCHENEX_CHECK.setStatus("EX", "", false, true);
446		}
447	},
448	
449	extensionVersionCheck : function( updateInfo ) {
450		
451		var pluginInfo = TOUCHENEX_CONST.pluginInfo[this.chkCurrPluginCnt];
452		exlog("_CHECK.extensionVersionCheck.updateInfo", updateInfo);
453		
454		if(!window[pluginInfo.exProtocolName + "_extension_listener"]){
455			window[pluginInfo.exProtocolName + "_extension_listener"] = function(event){
456				alert(pluginInfo.exPluginName + " È®Àå ±â´É ¼³Ä¡¸¦ ¿Ï·á ÇÏ¿´½À´Ï´Ù.");
457			};
458		}
459		
460		if(updateInfo == "-1") {
461			window.addEventListener('__'+ pluginInfo.exProtocolName + '_extension_installed__', window[pluginInfo.exProtocolName + "_extension_listener"]);
462			exlog("_CHECK.extensionVersionCheck", pluginInfo.exPluginName + " EX Extension not install");
463			TOUCHENEX_CHECK.setStatus("extension", "", false, true);
464			return;
465		}
466		
467		var extensionVersion = "";
468		if(TOUCHENEX_UTIL.isChrome()) extensionVersion = pluginInfo.exExtensionInfo.exChromeExtVer;
469		else if(TOUCHENEX_UTIL.isFirefox()) extensionVersion = pluginInfo.exExtensionInfo.exFirefoxExtVer;
470		else if(TOUCHENEX_UTIL.isOpera()) extensionVersion = pluginInfo.exExtensionInfo.exOperaExtVer;
471		
472		// Extension Version Diff
473		exlog("_CHECK.extensionVersionCheck", "Extension version check");
474		if(TOUCHENEX_UTIL.diffVersion(updateInfo, extensionVersion)) {
475			TOUCHENEX_CHECK.setStatus("extension", updateInfo, true, false);
476			window.removeEventListener('__'+ pluginInfo.exProtocolName + '_extension_installed__', window[pluginInfo.exProtocolName + "_extension_listener"]);
477			this.extensionNativeVersionCheck();
478		} else {
479			// chromeÀº ÀÚµ¿¾÷µ¥ÀÌÆ® µÇ¹Ç·Î ¿¹¿Üó¸®
480			if(TOUCHENEX_UTIL.isChrome()){
481				TOUCHENEX_CHECK.setStatus("extension", updateInfo, false, false);
482				window.removeEventListener('__'+ pluginInfo.exProtocolName + '_extension_installed__', window[pluginInfo.exProtocolName + "_extension_listener"]);
483				this.extensionNativeVersionCheck();
484			} else {
485				window.addEventListener('__'+ pluginInfo.exProtocolName + '_extension_installed__', window[pluginInfo.exProtocolName + "_extension_listener"]);
486				TOUCHENEX_CHECK.setStatus("extension", updateInfo, false, true);
487			}
488		}
489	},
490	
491	extensionNativeVersionCheck : function() {
492		
493		var pluginInfo = TOUCHENEX_CONST.pluginInfo[this.chkCurrPluginCnt];
494		var nativecall = TOUCHENEX_UTIL.createFuncByName(pluginInfo.exExtHeader + "_nativecall");
495		
496		var pv = "";
497		if(TOUCHENEX_UTIL.isWin()){
498			pv = pluginInfo.exProtocolInfo.exWinProtocolVer;
499		} else if(TOUCHENEX_UTIL.isMac()){
500			pv = pluginInfo.exProtocolInfo.exMacProtocolVer;
501		} else if(TOUCHENEX_UTIL.isLinux()){
502			pv = pluginInfo.exProtocolInfo.exLinuxProtocolVer;
503		}
504		
505		var nativecallData = {"cmd":"init", "exfunc":"get_versions", 
506				"m" : pluginInfo.exModuleName,
507				"origin" : pluginInfo.hostid ? pluginInfo.hostid : location.origin,
508				"pv" : pv,
509				"lic" : pluginInfo.lic,
510				"callback":""};
511		if(TOUCHENEX_UTIL.isFirefox()) nativecallData.ffPatch = true;
512		exlog("_CHECK.extensionNativeVersionCheck.nativecall.param", nativecallData);
513		
514		var chkExtVerChkInterval;
515		var chkExtRetry = 0;
516		function chkVersionNativeCall(){
517			if(chkExtRetry > 1)
518				exlog("_CHECK.extensionNativeVersionCheck.retry", chkExtRetry);
519			chkExtRetry++;
520			
521			nativecall(nativecallData,
522				function (response) {
523					exlog("_CHECK.extensionNativeVersionCheck", "clearInterval");
524					clearInterval(chkExtVerChkInterval);
525					exlog("_CHECK.extensionNativeVersionCheck.response", response);
526					if(response) {
527						// type 0 - check version
528						// type 1 - need to install
529						// type 2 - native host error
530						if(response.status == "INTERNAL_ERROR") {
531							
532							exlog("_CHECK.extensionNativeVersionCheck", pluginInfo.exPluginName + " internal error :: " + response.reply);
533							TOUCHENEX_CHECK.setStatus("EX", "", false, true);
534							
535						} else if(response.status == "TRUE") {
536							
537							// license check
538							if(typeof response.reply.status !== "undefined" && response.reply.status == false){
539								exlog("_CHECK.extensionNativeVersionCheck [license check]", pluginInfo.exPluginName + " license check FAIL");
540								TOUCHENEX_CHECK.setStatus("license", "", false, false, response.reply.expire);
541							} else {
542								exlog("_CHECK.extensionNativeVersionCheck [license check]", pluginInfo.exPluginName + " license check SUCCESS");
543								TOUCHENEX_CHECK.setStatus("license", "", true, false, response.reply.expire);
544							}
545							
546							// EX Version Diff
547							var exEXSvrVer;
548							if(TOUCHENEX_UTIL.isWin()){
549								exEXSvrVer = pluginInfo.exProtocolInfo.exWinProtocolVer;
550							} else if(TOUCHENEX_UTIL.isMac()){
551								exEXSvrVer = pluginInfo.exProtocolInfo.exMacProtocolVer;
552							} else if(TOUCHENEX_UTIL.isLinux()){
553								exEXSvrVer = pluginInfo.exProtocolInfo.exLinuxProtocolVer;
554							}
555							exlog("_CHECK.extensionNativeVersionCheck", "EX version check");
556							if(TOUCHENEX_UTIL.diffVersion(response.reply.ex, exEXSvrVer)) {
557								
558								TOUCHENEX_CHECK.setStatus("EX", response.reply.ex, true, false);
559								
560								// TODO Linux üũ ¾îÄÉÇÒ±î ¼Ö·ç¼Ç¸¶´Ù ´Ù¸¦ÅÙµ¥....
561								// Client Version Diff
562								var currModuleInfoArr = response.reply.m;
563								var currModuleVer;
564								for(var i = 0; i < currModuleInfoArr.length; i++){
565									var cm = currModuleInfoArr[i];
566									if(cm.name == pluginInfo.exModuleName){
567										currModuleVer = cm.version;
568										break;
569									}
570								}
571								var exModuleSvrVer;
572								if(TOUCHENEX_UTIL.isWin()){
573									exModuleSvrVer = pluginInfo.moduleInfo.exWinVer;
574								} else if(TOUCHENEX_UTIL.isMac()){
575									exModuleSvrVer = pluginInfo.moduleInfo.exMacVer;
576								} else if(TOUCHENEX_UTIL.isLinux()){
577									exModuleSvrVer = pluginInfo.moduleInfo.exLinuxVer;
578								}
579								exlog("_CHECK.extensionNativeVersionCheck", "Client version check");
580								if(TOUCHENEX_UTIL.diffVersion(currModuleVer, exModuleSvrVer)) {
581									
582									// Set isInstalled
583									TOUCHENEX_CHECK.setStatus("client", currModuleVer, true, true);
584								} else {
585									exlog("_CHECK.extensionNativeVersionCheck", pluginInfo.exPluginName + " client not installed or need upgrade");
586									TOUCHENEX_CHECK.setStatus("client", currModuleVer, false, true);
587								}
588							} else {
589								exlog("_CHECK.extensionNativeVersionCheck", pluginInfo.exPluginName + " client not installed or need upgrade");
590								TOUCHENEX_CHECK.setStatus("EX", response.reply.ex, false, true);
591							}
592						} else {
593							exlog("_CHECK.extensionNativeVersionCheck", pluginInfo.exPluginName + " status not TRUE");
594							TOUCHENEX_CHECK.setStatus("EX", "", false, true);
595						}
596					} else {
597						exlog("_CHECK.extensionNativeVersionCheck", pluginInfo.exPluginName + "response not exist");
598						exalert("_CHECK.extensionNativeVersionCheck", "ExtensionÀÇ ¼³Ä¡¸¦ È®ÀÎÇØÁÖ¼¼¿ä.");
599						TOUCHENEX_CHECK.setStatus("extension", "", false, true);
600					}
601				}
602			);
603		}
604		chkVersionNativeCall();
605		chkExtVerChkInterval = setInterval(function(){
606			exlog("_CHECK.extensionNativeVersionCheck", "setIntervalCall");
607			if(chkExtRetry > 0){
608				exlog("_CHECK.extensionNativeVersionCheck", "retry!!!");
609				chkVersionNativeCall();
610			} else {
611				exlog("_CHECK.extensionNativeVersionCheck", "pass!!!");
612				clearInterval(chkExtVerChkInterval);
613			}
614		},3000);
615	},
616	
617	npVersionCheck : function( updateInfo ) {
618		
619		updateInfo = JSON.parse(updateInfo);
620		exlog("_CHECK.npVersionCheck.updateInfo", updateInfo);
621		
622		var pluginInfo = TOUCHENEX_CONST.pluginInfo[this.chkCurrPluginCnt];
623		if(updateInfo == "-1") {
624			exlog("_CHECK.npVersionCheck", pluginInfo.exPluginName + " not install");
625			TOUCHENEX_CHECK.setStatus("EX", "", false, true);
626			return;
627		}
628		
629		// license check
630		if(typeof updateInfo.status !== "undefined" && updateInfo.status == false){
631			exlog("_CHECK.extensionNativeVersionCheck [license check]", pluginInfo.exPluginName + " license check FAIL");
632				TOUCHENEX_CHECK.setStatus("license", "", false, false, updateInfo.expire);
633		} else {
634			exlog("_CHECK.extensionNativeVersionCheck [license check]", pluginInfo.exPluginName + " license check SUCCESS");
635				TOUCHENEX_CHECK.setStatus("license", "", true, false, updateInfo.expire);
636		}
637		
638		// TODO OS ±¸ºÐ
639		// EX Version Diff
640		var exEXSvrVer;
641		if(TOUCHENEX_UTIL.isWin()){
642			exEXSvrVer = pluginInfo.exProtocolInfo.exWinProtocolVer;
643		} else if(TOUCHENEX_UTIL.isMac()){
644			exEXSvrVer = pluginInfo.exProtocolInfo.exMacProtocolVer;
645		} else if(TOUCHENEX_UTIL.isLinux()){
646			exEXSvrVer = pluginInfo.exProtocolInfo.exLinuxProtocolVer;
647		}
648		exlog("_CHECK.npVersionCheck", "EX version check");
649		if(TOUCHENEX_UTIL.diffVersion(updateInfo.ex, exEXSvrVer)) {
650			
651			TOUCHENEX_CHECK.setStatus("EX", updateInfo.ex, true, false);
652			
653			// Client Version Diff
654			var currModuleInfoArr = updateInfo.m;
655			var currModuleVer;
656			for(var i = 0; i < currModuleInfoArr.length; i++){
657				var cm = currModuleInfoArr[i];
658				if(cm.name == pluginInfo.exModuleName){
659					currModuleVer = cm.version;
660					break;
661				}
662			}
663			var exModuleSvrVer;
664			if(TOUCHENEX_UTIL.isWin()){
665				exModuleSvrVer = pluginInfo.moduleInfo.exWinVer;
666			} else if(TOUCHENEX_UTIL.isMac()){
667				exModuleSvrVer = pluginInfo.moduleInfo.exMacVer;
668			} else if(TOUCHENEX_UTIL.isLinux()){
669				exModuleSvrVer = pluginInfo.moduleInfo.exLinuxVer;
670			}
671			exlog("_CHECK.npVersionCheck", "Client version check");
672			if(TOUCHENEX_UTIL.diffVersion(currModuleVer, exModuleSvrVer)) {
673				// Set isInstalled
674				TOUCHENEX_CHECK.setStatus("client", currModuleVer, true, true);
675			} else {
676				TOUCHENEX_CHECK.setStatus("client", currModuleVer, false, true);
677			}
678		} else {
679			TOUCHENEX_CHECK.setStatus("EX", updateInfo.ex, false, true);
680		}
681	},
682
683LXVersionCheck : function( updateInfo ) {
684		var pluginInfo = TOUCHENEX_CONST.pluginInfo[this.chkCurrPluginCnt];
685		if(updateInfo) {
686			exlog("_CHECK.LXVersionCheck.updateInfo", updateInfo);
687			
688			TOUCHENEX_CHECK.setStatus("EX", updateInfo.ex, true, false);
689			TOUCHENEX_CHECK.setStatus("extension", updateInfo.extension, true, false);
690				
691			// Client Version Diff
692			var currModuleVer = updateInfo;
693			var exModuleSvrVer = pluginInfo.moduleInfo.exLinuxVer;
694			
695			exlog("_CHECK.LXVersionCheck", "Client version check");
696			if(TOUCHENEX_UTIL.diffVersion(currModuleVer, exModuleSvrVer)) {
697				TOUCHENEX_CHECK.setStatus("client", currModuleVer, true, true);
698			} else {
699				TOUCHENEX_CHECK.setStatus("client", currModuleVer, false, true);
700			}
701		} else {
702			exlog("_CHECK.LXVersionCheck", pluginInfo.exPluginName + " updateInfo Error");
703			TOUCHENEX_CHECK.setStatus("EX", "", false, true);
704		}
705	},
706	
707	loadScript : function( url ){
708
709		var newScript = document.createElement("script");
710		newScript.type = "text/javascript";
711		
712		if(newScript.readyState) { // IE8 under
713			newScript.onreadystatechange = function() {
714				exlog("_UTIL.loadScript.readyState", newScript.readyState);
715				if (newScript.readyState == 'loading' || newScript.readyState == 'loaded') {
716					newScript.onreadystatechange = null;
717					exlog("_UTIL.loadScript", "loadScript load error");
718					TOUCHENEX_CHECK.setStatus("EX", "", false, true);
719				}
720			};
721		} else {
722			newScript.onerror = function() {
723				exlog("_UTIL.loadScript", "loadScript load error");
724				TOUCHENEX_CHECK.setStatus("EX", "", false, true);
725			};
726		}
727		
728		try {
729			newScript.src = url;
730		} catch (e) {
731			exlog("_UTIL.loadscript", "LoadScript not https load error");
732			TOUCHENEX_CHECK.setStatus("EX", "", false, true);
733		}
734		window[TOUCHENEX_CONST.exDivName].appendChild(newScript);
735	},
736	
737	setStatus : function (type, localVer, status, isNext, licExpire){
738		var currPlugin = TOUCHENEX_CONST.pluginInfo[this.chkCurrPluginCnt];
739		try{
740			if(type == "license"){
741				if(!licExpire) licExpire = "";
742				this.chkInfoStatus.info[this.chkCurrPluginCnt].license = status;
743				this.chkInfoStatus.info[this.chkCurrPluginCnt].licExpire = licExpire;
744			} else if(type == "extension"){
745				this.chkInfoStatus.info[this.chkCurrPluginCnt].extensionVer = localVer;
746				this.chkInfoStatus.info[this.chkCurrPluginCnt].extension = status;
747			} else if(type == "EX"){
748				this.chkInfoStatus.info[this.chkCurrPluginCnt].EXVer = localVer;
749				this.chkInfoStatus.info[this.chkCurrPluginCnt].EX = status;
750			} else if(type == "client"){
751				this.chkInfoStatus.info[this.chkCurrPluginCnt].clientVer = localVer;
752				this.chkInfoStatus.info[this.chkCurrPluginCnt].client = status;
753				if(status){
754					currPlugin.isInstalled = true;
755				}
756			}
757			
758			if(isNext){
759				//this.chkInfoStatus.info[this.chkCurrPluginCnt].check = true;
760				//exlog("_CHECK.setStatus", this.chkInfoStatus);
761				this.moduleCheck(this.chkCurrPluginCnt + 1);
762			} else {
763				//exlog("_CHECK.setStatus", this.chkInfoStatus);
764			}
765		}catch(e){
766			exlog("_CHECK.setStatus", "setStatus failed");
767		}
768		
769	}
770};
771
772
773/* 
774 * CrossEX Construct
775 * TOUCHENEX_EX
776 */
777var TOUCHENEX_EX = function( property ) {
778	
779	this.isInstalled	= property.isInstalled;
780	this.exPluginName	= property.exPluginName;
781	this.exModuleName	= property.exModuleName ? property.exModuleName : property.exProtocolName;
782	this.exProtocolName	= property.exProtocolName;
783	this.exExtHeader	= property.exExtHeader;
784	this.exNPPluginId	= property.exNPPluginId;
785	this.exErrFunc		= property.exErrFunc;
786	this.lic			= property.lic;
787	this.exDefaultCallbackName = property.exDefaultCallback ? property.exDefaultCallback : property.exPluginName + ".exDefaultCallback";
788	
789	this.exDivName		= TOUCHENEX_CONST.exDivName;
790	this.exFormName		= TOUCHENEX_CONST.exFormName;
791	this.exFormDataName	= TOUCHENEX_CONST.exFormDataName;
792	this.exIframeName	= TOUCHENEX_CONST.exIframeName;
793	this.exScriptName	= TOUCHENEX_CONST.exScriptName;
794	
795	dummyDomain	= property.dummyDomain?property.dummyDomain:location.host;
796	hostid		= property.hostid?property.hostid:location.host;
797	
798	this.initEXInfoArr	= [];
799	this.exInterfaceArr	= [];
800	this.exEcho			= false;
801	this.setEcho = function( status ){
802		this.exEcho =status;
803	};
804	this.alertInfo		= {"BLOCK":false, "EX":false, "CLIENT":false};
805	
806	// default callback
807
808		this.exDefaultCallback = function( response ){
809		exlog("exDefaultCallback", response);
810		
811		//¾Æ·¡´Â ¿¹Á¦·Î½á. 
812		// ¿¡·¯ÄÚµå´Â »çÀÌÆ®¿¡ ¸Â°Ô ¾Ë¾Æ¼­.. 
813		if(response){
814			var resPluginObj;
815			if(response.NAME){
816				resPluginObj = window[response.NAME];
817			}
818			if(response.NAME!="TOUCHENEX")
819			{
820				if(response.ERR == "BLOCK"){
821					if(!resPluginObj.alertInfo.BLOCK){
822						resPluginObj.alertInfo.BLOCK = true;
823						alert(response.NAME + " ¶óÀ̼¾½º¸¦ È®ÀÎÇϼ¼¿ä.");
824					}
825				} else if(response.ERR == "BLOCK:EX"){
826					if(!resPluginObj.alertInfo.EX){
827						resPluginObj.alertInfo.EX = true;
828						alert(response.NAME + " ÇÁ·Î±×·¥ÀÌ º¯Á¶µÇ¾ú½À´Ï´Ù.(EX)\nÀ缳ġ°¡ ÇÊ¿äÇÕ´Ï´Ù.");
829						return;
830					}
831				} else if(response.ERR == "BLOCK:CLIENT"){
832					if(!resPluginObj.alertInfo.CLIENT){
833						resPluginObj.alertInfo.CLIENT = true;
834						alert(response.NAME + " ÇÁ·Î±×·¥ÀÌ º¯Á¶µÇ¾ú½À´Ï´Ù.(client)\nÀ缳ġ°¡ ÇÊ¿äÇÕ´Ï´Ù.");
835						return;
836					}
837				} else if(response.ERR == "BLOCK:DISCONNECTED"){
838					exlog("exDefaultCallback.msg", response.MSG);
839					
840					if(!resPluginObj.alertInfo.BLOCK){
841						resPluginObj.alertInfo.BLOCK = true;
842						alert(response.NAME + " ÇÁ·Î±×·¥ÀÌ ÁߴܵǾú½À´Ï´Ù.(client)\nÆäÀÌÁö¸¦ »õ·Î°íħÇϼ¼¿ä.");
843						return;
844					}
845				} else if(response.ERR == "BLOCK:INTERNAL"){
846					exlog("exDefaultCallback.msg", response.MSG);
847					if(!resPluginObj.alertInfo.BLOCK){
848						resPluginObj.alertInfo.BLOCK = true;
849						alert(response.NAME + " ÇÁ·Î±×·¥ÀÌ ÁߴܵǾú½À´Ï´Ù.(client)\nÆäÀÌÁö¸¦ »õ·Î°íħÇϼ¼¿ä.");
850					}
851				} else {
852					exalert("½ÇÇàÁß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.(EX)", response);
853				}
854			}
855			try{
856				if(resPluginObj.exErrFunc){
857					TOUCHENEX_UTIL.runCallback(resPluginObj.exErrFunc, response);
858					return;
859				}
860			} catch (e){
861				exlog("_exCallbackCheck", "Callback not response");
862			}
863		} else {
864		exalert("½ÇÇàÁß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.(EX)", "InvokeCallback not response");
865		}
866	};
867	
868	/*
869	 * Invoke
870	 */
871	this.Invoke = function( fname, args, exCallback, pageCallback ){
872		
873		var id = TOUCHENEX_UTIL.createId();
874		var obj = {};
875		obj.id = id;
876		obj.EXCallback = exCallback ? exCallback:null;
877		obj.pageCallback = pageCallback ? pageCallback : null;
878		obj.pluginName = this.exPluginName;
879		this.exInterfaceArr.push(obj);
880		exlog(this.exPluginName + ".Invoke.exInterfaceArr.id", id);
881		//exlog(this.exPluginName + ".Invoke.exInterfaceArr.push", obj);
882		//exlog(this.exPluginName + ".Invoke.exInterfaceArr.length", this.exInterfaceArr.length);
883		
884		var cmd = "native";
885		if(TOUCHENEX_UTIL.typeEX()){
886			this.InvokeScriptEX(id, cmd, fname, args, exCallback);
887		} else if(TOUCHENEX_UTIL.typeExtension()){
888			this.InvokeExtension(id, cmd, fname, args, exCallback);
889		} else if(TOUCHENEX_UTIL.typePlugin()) {
890			this.InvokePlugin(id, cmd, fname, args, exCallback);
891		} else {
892			return;
893		}
894	};
895	
896	/*
897	 * SetPushCallback
898	 */
899	this.SetPushCallback = function( fname, args ) {
900		
901		var id = TOUCHENEX_UTIL.createId();
902		var obj = {};
903		obj.id = id;
904		this.exInterfaceArr.push(obj);
905		exlog(this.exPluginName + ".SetPushCallback.info", obj);
906		
907		var cmd = "setcallback";
908		if(TOUCHENEX_UTIL.typeEX()){
909			this.InvokeScriptEX(id, cmd, fname, args);
910		} else if(TOUCHENEX_UTIL.typeExtension()){
911			this.InvokeExtension(id, cmd, fname, args);
912		} else if(TOUCHENEX_UTIL.typePlugin()) {
913			this.InvokePlugin(id, cmd, fname, args);
914		} else {
915			return;
916		}
917	};
918	
919	this.InvokeScriptEX = function( id, cmd, fname, funcArgsArray, callback ) {
920		
921		var initUrl = this.createInitEXURL(id, this.exPluginName + ".InitEXCallback"); 
922		var reqJSON = {};
923		reqJSON.id = id;
924		reqJSON.tabid = TOUCHENEX_CONST.extabid;
925		reqJSON.module = this.exModuleName;
926		reqJSON.cmd = cmd;
927		reqJSON.origin = location.origin != undefined ? location.origin : (location.protocol + "//" + hostid);
928		reqJSON.exfunc = {};
929		reqJSON.exfunc.fname = fname;	
930		reqJSON.callback = callback;
931		
932		var exfunc = reqJSON.exfunc;
933		if(funcArgsArray) {
934			if(funcArgsArray instanceof Array) {
935				exfunc.args = funcArgsArray;
936			} else {
937				var arr = [funcArgsArray];
938				exfunc.args = arr;
939			}
940		} else {
941			exfunc.args = [];
942		}
943		exlog(this.exPluginName + ".InvokeScriptEX.reqJSON", reqJSON);
944
945			var strCutLength = TOUCHENEX_CONST.scrLength;
946			var reqStr = JSON.stringify(reqJSON);
947
948
949		
950
951
952
953		if(reqStr.length > 600000)
954		{
955			// ÃֽнºÅ©¸³Æ®¿¡¼­ ±æÀ̰¡ 60¸¸ ÀÌ»óÀÌ¸é ¹öÆÛ¿À¹öÇÃ·Î¿ì ¹ß»ýÇÏ¿© ÀÌ °æ¿ì ±¸¹öÀü ½ºÅ©¸³Æ®·Î µ¿ÀÛÇϵµ·Ï ÇÔ			
956			var initEXInfo = {"id":id,"json":reqJSON,"callback":callback};
957			this.initEXInfoArr.push(initEXInfo);
958		
959			exlog(this.exPluginName + ".InitEX.loadScript.url", initUrl);
960			TOUCHENEX_UTIL.loadScript(initUrl);
961		
962		}
963		else
964		{
965			reqStr = TOUCHENEX_UTIL.Base64.encode(reqStr);
966			var paging = Math.ceil(reqStr.length / strCutLength);
967			
968			exlog(this.exPluginName + ".InvokeScriptEX.reqStr", reqStr);
969			exlog(this.exPluginName + ".InvokeScriptEX.reqStr.length", reqStr.length);
970			exlog(this.exPluginName + ".InvokeScriptEX.paging", paging);
971			
972			if(paging > 1) {
973				for(var i=0; i < paging + 1; i++) {
974					var url = "";
975					var tmpReq = reqStr.substr(i * strCutLength, strCutLength);
976					exlog(this.exPluginName + ".InvokeScriptEX.params", tmpReq);
977
978					if(i < paging){
979						url = this.createScriptEXURL(id, "");
980						url += "&tseq=" + paging + "&seq=" + i;
981						url += "&params=" + encodeURIComponent(tmpReq);
982
983					} else {
984						url = this.createScriptEXURL(id, this.exPluginName + ".InvokeCallback");
985						url += "&tseq=" + paging + "&seq=" + i;
986					}
987					exlog(this.exPluginName + ".InvokeScriptEX.url", url);
988					TOUCHENEX_UTIL.loadScript(url);
989				}
990			} else {
991				var url = this.createScriptEXURL(id, this.exPluginName + ".InvokeCallback");
992				url += "&params=" + encodeURIComponent(reqStr);
993				exlog(this.exPluginName + ".InvokeScriptEX.url", url);
994				TOUCHENEX_UTIL.loadScript(url);
995			}
996
997
998
999
1000
1001		}
1002		
1003	};
1004	
1005	this.InvokeGarbageCallback = function(response){
1006		exlog(this.exPluginName + ".InvokeGarbageCallback.response", response);
1007	};
1008
1009	
1010	////////////////////////////////////////////////////////////////////////////////////
1011	// // ÃֽнºÅ©¸³Æ®¿¡¼­ ±æÀ̰¡ 60¸¸ ÀÌ»óÀÌ¸é ¹öÆÛ¿À¹öÇÃ·Î¿ì ¹ß»ýÇÏ¿© ÀÌ °æ¿ì ±¸¹öÀü ½ºÅ©¸³Æ®·Î µ¿ÀÛÇϵµ·Ï ÇÔ			 
1012	this.InitEXCallback = function( id ) {
1013				
1014		var
1015			callback,
1016			reqJSON;
1017		
1018		if(this.initEXInfoArr){
1019			for(var i=0; i < this.initEXInfoArr.length; i++){
1020				initExObj = this.initEXInfoArr[i];
1021				if(initExObj.id == id){
1022					reqJSON = initExObj.json;
1023					callback = initExObj.json.callback;
1024					this.initEXInfoArr.splice(i,1);
1025					break;
1026				}
1027			}
1028		} else {
1029			exlog(this.exPluginName + ".InitEXCallback [exception]", "initEXInfoArr´Â Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù.");
1030			exalert(this.exPluginName + ".InitEXCallback [exception]", "initEXInfoArr´Â Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù.");
1031			return;
1032		}
1033		
1034		this.InvokeEX(id, callback, reqJSON);
1035	};
1036	
1037	this.InvokeEX = function( id, callback, reqJSON){
1038		
1039		var frm = document.getElementById(TOUCHENEX_CONST.exFormName);
1040		frm.target = TOUCHENEX_CONST.exIframeName;
1041		frm.action = this.createEXURL(id, this.exPluginName + ".InvokeCallback");
1042		
1043		if(frm.elements.length > 1){
1044			for(var i=0; i<frm.elements.length;){
1045				var chkElement = frm.elements[i];
1046				var chkId = chkElement.id ? chkElement.id : "";
1047				var chkName = chkElement.name ? chkElement.name : ""; 
1048				
1049				if(chkId != TOUCHENEX_CONST.exFormDataName || chkName != TOUCHENEX_CONST.exFormDataName){
1050					exlog(this.exPluginName + ".InvokeEX.form remove garbage param",chkId + "::" + chkName);
1051					chkElement.parentElement.removeChild(chkElement);
1052				} else {
1053					i++;
1054				}
1055			}
1056		}
1057		
1058		var node = frm.elements[0];
1059		node.value = JSON.stringify(reqJSON);
1060		
1061		exlog(this.exPluginName + ".InvokeEX." + frm.id + ".action", frm.action);
1062		exlog(this.exPluginName + ".InvokeEX." + node.name + ".value", node.value);
1063		frm.submit();
1064	};
1065	////////////////////////////////////////////////////////////////////////////////////
1066	
1067	this.InvokeExtension = function( id, cmd, fname, args, callback ) {
1068		
1069		var request = {};
1070		request.id = id;
1071		request.module = this.exModuleName;
1072		request.cmd = cmd;
1073		request.origin = location.origin != undefined ? location.origin : (location.protocol + "//" + location.host);
1074		request.exfunc = {};
1075		request.exfunc.fname = fname;
1076		request.exfunc.args = args;
1077		request.callback = callback;
1078		if(this.exEcho) request.echo = true;
1079		exlog(this.exPluginName + ".InvokeExtension.request", request);
1080		
1081		TOUCHENEX_CONST.tmpExtArr.push({"id":id,"name":this.exPluginName});
1082		var invokeCallbackFn = window[this.exPluginName]["InvokeExtensionCallback"];
1083		if(typeof window[this.exExtHeader+"_nativecall"] == "function"){
1084			window[this.exExtHeader+"_nativecall"](request, invokeCallbackFn);
1085		} else {
1086			TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, "extension not installed");
1087		}
1088	};
1089	
1090	this.InvokeExtensionCallback = function( response ){
1091		var tmpPluginName;
1092		for(var i = 0; i < TOUCHENEX_CONST.tmpExtArr.length; i++){
1093			var tmpObj = TOUCHENEX_CONST.tmpExtArr[i];
1094			if(response.id == tmpObj.id){
1095				tmpPluginName = tmpObj.name;
1096				TOUCHENEX_CONST.tmpExtArr.splice(i,1);
1097				break;
1098			}
1099		}
1100		if(tmpPluginName)
1101			window[tmpPluginName]["InvokeCallback"](response);
1102	};
1103
1104	this.InvokePlugin = function( id, cmd, fname, args, callback ) {
1105		
1106		var request = {};
1107		request.id = id;
1108		request.tabid = TOUCHENEX_CONST.extabid;
1109		request.module = this.exModuleName;
1110		request.cmd = cmd;
1111		request.origin = location.origin != undefined ? location.origin : location.host;
1112		request.exfunc = {};
1113		request.exfunc.fname = fname;
1114		request.exfunc.args = args;
1115		request.callback = callback;
1116		if(this.exEcho) request.echo = true;
1117		
1118		exlog(this.exPluginName + ".InvokePlugin.request", JSON.stringify(request));
1119		var plugin = window[this.exNPPluginId];
1120		if(typeof plugin.nativeCall == "function"){
1121			var response = plugin.nativeCall(JSON.stringify(request));
1122			this.InvokeCallback(response);
1123		} else {
1124			TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, "plugin not installed");
1125			return;
1126		}
1127		
1128		// plugin client callback set
1129		if(TOUCHENEX_UTIL.typePlugin() && cmd == "setcallback"){
1130			try {
1131				var pluginNameStr = this.exNPPluginId;
1132				var exNameStr = this.exPluginName;
1133				var pluginPop = function(){
1134					try {
1135						//exlog("nppluginPop", TOUCHENEX_CONST.frameName + pluginNameStr);
1136						var popPlugin = document.getElementById(pluginNameStr);
1137						var popResp = popPlugin.pop();
1138						if(popResp){
1139							new Function(popResp)();
1140							//exlog("nppluginPop", "call");
1141						} else {
1142							//exlog("nppluginPop", "pass");
1143						}
1144					} catch (e){
1145						exlog(exNameStr + "nppluginPop [exception]", e);
1146						exlog(exNameStr + "nppluginPop", "plugin.popo function not exist");
1147					}
1148					clearInterval(g_intervalPop);
1149					g_intervalPop = setInterval(pluginPop,1);
1150				};
1151				//pluginPop();
1152				//setInterval(pluginPop,1);
1153				g_intervalPop = setInterval(pluginPop, 1);
1154			} catch (e) {
1155				exlog(this.exPluginName + ".InvokePlugin [exception]", e);
1156				exlog(this.exPluginName + ".InvokePlugin", "plugin.pop function not exist");
1157			}
1158		}
1159	};
1160	
1161	this.InvokeCallback = function( response ){
1162		if(response){
1163			try{
1164				exlog(this.exPluginName + ".InvokeCallback.response", response);
1165				if(typeof response == "object"){
1166					var strSerial = JSON.stringify(response);
1167				} else if(typeof response == "string"){
1168					response = JSON.parse(response);
1169				}
1170				
1171				if(TOUCHENEX_UTIL.typeEX() || TOUCHENEX_UTIL.typePlugin()) {
1172					response = response.response;
1173				} else {
1174					response = response;
1175				}
1176				
1177				var status = response.status;
1178				if(status == "TRUE") {	// success
1179					var id = response.id;
1180					var funcInfo = {};
1181					for(var i=0; i < this.exInterfaceArr.length; i++){
1182						if(this.exInterfaceArr[i]){
1183							var arrObj = this.exInterfaceArr[i];
1184							if(arrObj.id == id){
1185								//exlog(this.exPluginName + ".InvokeCallback remove exInterfaceArr info", arrObj);
1186								funcInfo = arrObj;
1187								this.exInterfaceArr.splice(i,1);
1188								break;
1189							}
1190						}
1191					}
1192					var callback = funcInfo.EXCallback;
1193					var reply = response.reply.reply;
1194					
1195					// run callback
1196					if(callback){
1197						if(reply instanceof Array) {
1198							var strReply = {};
1199							strReply.callback = funcInfo.pageCallback;
1200							var replyArr;
1201							replyArr = "[";
1202							for(var i in reply) {
1203								var str = reply[i];
1204								str = str.replace("\\r", "\r");
1205								str = str.replace("\\n", "\n");
1206								replyArr += "'" + str + "',";
1207							}
1208							replyArr += "]";
1209							strReply.reply = replyArr;
1210							callback = callback + "(" + JSON.stringify(strReply) + ");";
1211						} else if(typeof reply == 'string') {
1212							var strReply = {};
1213							strReply.callback = funcInfo.pageCallback;
1214							strReply.reply = reply.replace("\\r", "\r").replace("\\n", "\n");
1215							callback = callback + "(" + JSON.stringify(strReply) + ");";
1216						} else if(typeof reply == 'object') {
1217
1218							
1219							reply.callback = funcInfo.pageCallback;
1220							callback = callback + "(" + JSON.stringify(reply) + ");";
1221						} else {
1222							callback = callback + "()";
1223						}
1224						//exlog(this.exPluginName + ".InvokeCallback run EXCallback", callback);
1225						setTimeout(function(){
1226							new Function(callback)();
1227						},5);
1228					}
1229					
1230				} else if(status == "BLOCK") {
1231					exlog(this.exPluginName + ".InvokeCallback", "license not valid");
1232					TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, {"NAME":this.exPluginName, "ERR":"BLOCK"});
1233				} else if(status == "BLOCK:EX") {
1234					exlog(this.exPluginName + ".InvokeCallback", "CrossEX sig check fail");
1235					TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, {"NAME":this.exPluginName, "ERR":"BLOCK:EX"});
1236				} else if(status == "BLOCK:CLIENT") {
1237					exlog(this.exPluginName + ".InvokeCallback", "Client sig check fail");
1238					TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, {"NAME":this.exPluginName, "ERR":"BLOCK:CLIENT"});
1239				} else if(status == "INTERNAL_ERROR") {
1240					if(response.reply && response.reply.match(/disconnected/gi).length > 0){
1241						exlog(this.exPluginName + ".InvokeCallback", "CrossEXClient disconnect");
1242						TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, {"NAME":this.exPluginName, "ERR":"BLOCK:DISCONNECTED", "MSG":response.reply});
1243					} else {
1244						exlog(this.exPluginName + ".InvokeCallback", "CrossEXClient Internal Error");
1245						TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, {"NAME":this.exPluginName, "ERR":"BLOCK:INTERNAL", "MSG":response.reply});
1246					}
1247				} else {
1248					exlog(this.exPluginName + ".InvokeCallback", "native response status not TRUE");
1249					TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, response);
1250				}
1251			} catch (e) {
1252				exlog(this.exPluginName + ".InvokeCallback [exception]", e);
1253				exlog(this.exPluginName + ".InvokeCallback [exception]", "native response process exception");
1254				TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName, response);
1255			}
1256		} else {
1257			exlog(this.exPluginName + ".InvokeCallback", "native call not response");
1258			TOUCHENEX_UTIL.runCallback(this.exDefaultCallbackName);
1259		}
1260	};
1261	
1262	/*
1263	 * ScriptInvoke
1264	 */
1265	this.ScriptInvoke = function( args, callback ){
1266		var jsonStr;
1267		try {
1268			if(!(args instanceof Array)) {
1269				args = [args];
1270			}
1271			jsonStr = JSON.stringify(args);
1272		} catch(e) {
1273			exalert(this.exPluginName + ".ScriptInvoke", "ÀԷ°ªÀÌ ¿Ã¹Ù¸£Áö ¾Ê½À´Ï´Ù.");
1274			return;
1275		}
1276		var url = this.createScriptInvokeURL(jsonStr, callback);
1277		exlog(this.exPluginName + ".ScriptInvoke.url", url);
1278		
1279		if(TOUCHENEX_UTIL.typeEX()){
1280			TOUCHENEX_UTIL.loadScript(url);
1281		} else {
1282			exlog(this.exPluginName + ".ScriptInvoke", "not IE");
1283			exalert(this.exPluginName + ".ScriptInvoke", "IE ºê¶ó¿ìÀú¿¡¼­´Â µ¿ÀÛÇÏÁö ¾Ê´Â Æã¼ÇÀÔ´Ï´Ù.");
1284			return;
1285		}
1286	};
1287	
1288	this.createScriptEXURL = function( id, callback ) {
1289		var cmd = "CallScript";
1290		var params = "hostid=" + encodeURIComponent(hostid)
1291			+ "&id=" + encodeURIComponent(id);
1292		if(callback)
1293			params += "&callback=" + encodeURIComponent(TOUCHENEX_CONST.frameName + callback);
1294		if(window.location.protocol == "https:") params += "&s=1";
1295		var url = this.exProtocolName + "://" + dummyDomain + "/" + cmd + "?" + params;
1296		
1297		return url;
1298	};
1299	
1300	this.createScriptInvokeURL = function( args, callback ) {
1301		var id = TOUCHENEX_UTIL.createId();
1302		var url = this.exProtocolName + "://" + dummyDomain + "/Call2?hostid=" + hostid + "&id=" + id;
1303		if(callback) {
1304			url += "&callback=" + callback;
1305			url += "&__CROSSEX_DATA__=" + encodeURIComponent(args);
1306		}
1307		if(window.location.protocol == "https:") url += "&s=1";
1308		//exlog(this.exPluginName + ".createScriptInvokeURL", url);
1309		return url;
1310	};
1311	
1312	//////////////////////////////////////////////////////////////////////////////////////
1313	/// // ÃֽнºÅ©¸³Æ®¿¡¼­ ±æÀ̰¡ 60¸¸ ÀÌ»óÀÌ¸é ¹öÆÛ¿À¹öÇÃ·Î¿ì ¹ß»ýÇÏ¿© ÀÌ °æ¿ì ±¸¹öÀü ½ºÅ©¸³Æ®·Î µ¿ÀÛÇϵµ·Ï ÇÔ			
1314	this.createEXURL = function( id, callback ) {
1315		var param = "hostid=" + encodeURIComponent(hostid)
1316			+ "&id=" + encodeURIComponent(id)
1317			+ "&callback=" + encodeURIComponent(TOUCHENEX_CONST.frameName + callback);
1318		url = this.createProtocolURL("Call", param);
1319		
1320		return url;
1321	};
1322	
1323	this.createProtocolURL = function( cmd, param ) {
1324		var url = this.exProtocolName + "://" + dummyDomain + "/" + cmd + "?";
1325		if(param) {
1326			url += param;
1327			if(window.location.protocol == "https:") url += "&i=1&s=1";
1328		} else {
1329			if(window.location.protocol == "https:") url += "i=1&s=1";
1330		}
1331		
1332		return url;
1333	};
1334
1335	this.createInitEXURL = function( id, callback ) {
1336		var param = "hostid=" + encodeURIComponent(hostid) 
1337			+ "&id=" + encodeURIComponent(id)
1338			+ "&callback=" + encodeURIComponent(TOUCHENEX_CONST.frameName + callback);
1339		url = this.createProtocolURL("Init", param);
1340	
1341		return url;
1342	};
1343	////////////////////////////////////////////////////////////////////////////////////
1344};
1345
1346
1347/* 
1348 * CrossEX Util
1349 * TOUCHENEX_UTIL
1350 */
1351var TOUCHENEX_UTIL = {
1352
1353	exlog : function( func, value ){
1354		
1355		if(TOUCHENEX_CONST.debug) {
1356			//if(!window.console) console = {log:function(msg){alert(msg);}};
1357			if(!window.console) console = {log:function(msg){}};
1358			
1359			var strlog;
1360			try {
1361				if(typeof value == "undefined") {
1362					strlog = "[undefined]";
1363				} else {
1364					if(typeof value == "function") {
1365						strlog = "[function] " + value;
1366					} else if(typeof value == "object") {
1367						try{
1368							strlog = "[json] " + JSON.stringify(value);
1369						} catch (e){
1370							strlog = "[object] " + value;
1371						}
1372					} else if(typeof value == "number") {
1373						strlog = "[number] " + value;
1374					} else if(typeof value == "string") {
1375						strlog = "[string] " + value;
1376					} else if(typeof value == "boolean") {
1377						strlog = "[boolean] " + value;
1378					} else{
1379						strlog = "[other] " + value.toString();
1380					}
1381				}
1382			} catch (e) {
1383				strlog = " [exlog exception] " + typeof value;
1384			}
1385			
1386			try{
1387				//console.log("[exlog] " + TOUCHENEX_CONST.frameName + func + " : " + strlog);
1388			} catch (e) {
1389				exlog("[exlog] ", "console log failed");
1390			}
1391			
1392			return;
1393		}
1394	},
1395	exalert : function( func, value ){
1396		
1397		if(TOUCHENEX_CONST.debugAlert) {
1398			var msg;
1399			try {
1400				if(value){
1401					if(typeof value == "object") {
1402						msg = JSON.stringify(value);
1403					} else if(typeof value == "function") {
1404						msg = value;
1405					} else if(typeof value == "number") {
1406						msg = value;
1407					} else if(typeof value == "string") {
1408						msg = value;
1409					} else if(typeof value == "boolean") {
1410						msg = value;
1411					} else {
1412						msg = value.toString();
1413					}
1414				}
1415			} catch (e) {
1416				msg = "[exception] " + value;
1417			}
1418			
1419			if(func) {
1420				alert(func + " : " + msg);
1421			} else {
1422				alert(msg);
1423			}
1424			return;
1425		}
1426	},
1427	findPath : function(currentFrame, tmpPath) {
1428		
1429		if(currentFrame == top) return "";
1430		
1431		var path, pathObj;
1432		if(!tmpPath) {
1433			pathObj = top;
1434			path = "top";
1435		} else {
1436			var pathArr = tmpPath.split(".");
1437			for (var i=0; i < pathArr.length; i++){
1438				if(pathArr[i] == "top"){
1439					pathObj = top;
1440				} else {
1441					var framesStr = pathArr[i];
1442					framesStr = framesStr.replace("frames[", "");
1443					framesStr = framesStr.replace("]", "");
1444					pathObj = pathObj.frames[framesStr];
1445				}
1446			}
1447			path = tmpPath;
1448		}
1449		
1450		var frameCnt = pathObj.frames.length;
1451		for(var i = 0 ; i < frameCnt; i++){
1452			var fr = pathObj.frames[i];
1453			if(currentFrame == fr){
1454				return path + ".frames[" + i + "].";
1455			}
1456			try {
1457				if(fr.frames && fr.frames.length > 0){
1458					var resultPath = TOUCHENEX_UTIL.findPath(currentFrame, path + ".frames[" + i + "]");
1459					if(resultPath){
1460						return resultPath;
1461					}
1462				}
1463			} catch(e) {
1464				exlog("_UTIL.findPath", "frame check error : " + path + "[" + i + "]");
1465				return;
1466			}
1467		}
1468		return;
1469	},
1470	getOSInfo : function(){
1471		var
1472			tp = navigator.platform,
1473			ua = navigator.userAgent,
1474			tem;
1475			
1476		//exlog("platform", tp);
1477		//exlog("userAgent", ua);
1478		var result = {};
1479		
1480		// platform
1481    	if (tp == "Win32" || tp == "Win64"){
1482    		if(ua.search("Windows Phone") >= 0){
1483    			result.platform = "Windows Phone";
1484    			result.name="Windows Phone";
1485    		} else {
1486    			result.platform = "WINDOWS";
1487    		}
1488    	} else if (tp == "MacIntel") {
1489    		if((ua.search("iPhone") >= 0) || (ua.search("iPad") >= 0) || (ua.search("iPod") >= 0) || ("ontouchend" in document)){
1490    			result.platform = "iOS";
1491    			result.name="iOS";
1492    		} else {
1493    			result.platform = "MACOSX";
1494    		}
1495		} else if (tp.search("Linux") >= 0) {
1496			if(ua.search("Android") >= 0){
1497				result.platform = "Android";
1498				result.name="Android";
1499			} else {
1500				result.platform = "LINUX";
1501			}
1502		} else if (tp == "iPhone Simulator") {
1503			result.platform = "iOS";
1504			result.name="iPhone Simulator";
1505		} else if (tp == "iPhone") {
1506			result.platform = "iOS";
1507			result.name="iPhone";
1508		} else if (tp == "iPad") {
1509			result.platform = "iOS";
1510			result.name="iPad";
1511		} else if (tp == "iPod") {
1512			result.platform = "iOS";
1513			result.name="iPod";
1514		} else {
1515			result.platform = "UNKNOWN";
1516		}
1517		
1518		// version, bit
1519		if(result.platform == "WINDOWS"){
1520			if(ua.indexOf("Windows NT 5.1") != -1) {result.version="5.1"; result.name="XP";}
1521			else if(ua.indexOf("Windows NT 5.2") != -1) {result.version="5.2"; result.name="XP";}
1522			else if(ua.indexOf("Windows NT 6.0") != -1) {result.version="6.0"; result.name="VISTA";}
1523			else if(ua.indexOf("Windows NT 6.1") != -1) {result.version="6.1"; result.name="7";}
1524			else if(ua.indexOf("Windows NT 6.2") != -1) {result.version="6.2"; result.name="8";}
1525			else if(ua.indexOf("Windows NT 6.3") != -1) {result.version="6.3"; result.name="8.1";}
1526			else if(ua.indexOf("Windows NT 10.0") != -1) {result.version="10.0"; result.name="10";}
1527			else if(ua.indexOf("Windows NT 11.0") != -1) {result.version="11.0"; result.name="11";}																			  
1528			else if(ua.indexOf("Windows NT") != -1){
1529				result.version="99"; result.name="NewVersion";
1530			} else {
1531				result.version="UNKNOWN"; result.name="UNKNOWN";
1532			}
1533			
1534			if(ua.indexOf("WOW64") != -1 || ua.indexOf("Win64") != -1) result.bit="64";
1535			else result.bit="32";
1536			// 2020.11.30 ÀÓµ¿ QA, platformÃß°¡ ¿äû (11_0) -À̴϶óÀÎ ÀÛ¾÷¿Ï·á
1537		} else if(result.platform == "MACOSX"){
1538			if((ua.indexOf("Mac OS X 10_5") || ua.indexOf("Mac OS X 10.5")) != -1) {result.version="10.5"; result.name="Leopard";}
1539			else if((ua.indexOf("Mac OS X 10_6") || ua.indexOf("Mac OS X 10.6")) != -1) {result.version="10.6"; result.name="Snow Leopard";}
1540			else if((ua.indexOf("Mac OS X 10_7") || ua.indexOf("Mac OS X 10.7")) != -1) {result.version="10.7"; result.name="Lion";}
1541			else if((ua.indexOf("Mac OS X 10_8") || ua.indexOf("Mac OS X 10.8")) != -1) {result.version="10.8"; result.name="Mountain Lion";}
1542			else if((ua.indexOf("Mac OS X 10_9") || ua.indexOf("Mac OS X 10.9")) != -1) {result.version="10.9"; result.name="Mavericks";}
1543			else if((ua.indexOf("Mac OS X 10_10") || ua.indexOf("Mac OS X 10.10")) != -1) {result.version="10.10"; result.name="Yosemite";}
1544			else if((ua.indexOf("Mac OS X 10_11") || ua.indexOf("Mac OS X 10.11")) != -1) {result.version="10.11"; result.name="El Capitan";}
1545			else if((ua.indexOf("Mac OS X 10_12") || ua.indexOf("Mac OS X 10.12")) != -1) {result.version="10.12"; result.name="Sierra";}
1546			else if((ua.indexOf("Mac OS X 10_13") || ua.indexOf("Mac OS X 10.13")) != -1) {result.version="10.13"; result.name="High Sierra";}
1547			else if((ua.indexOf("Mac OS X 10_14") || ua.indexOf("Mac OS X 10.14")) != -1) {result.version="10.14"; result.name="Mojave";}
1548			else if((ua.indexOf("Mac OS X 10_15") || ua.indexOf("Mac OS X 10.15")) != -1) {result.version="10.15"; result.name="Catalina";}
1549			else if((ua.indexOf("Mac OS X 11_0") || ua.indexOf("Mac OS X 11.0")) != -1) {result.version="11.0"; result.name="Big Sur";}
1550            // 2020.11.30 ÀÓµ¿ QA, MAC OS unknown check·ÎÁ÷ º¯°æ(Mac OS X ¡æ Mac OS)
1551			else if(ua.indexOf("Mac OS") != -1){
1552				result.version="10.99"; result.name="NewVersion";
1553			} else {
1554				result.version="UNKNOWN"; result.name="UNKNOWN";
1555			}
1556			result.bit = "64";
1557		} else if(result.platform == "LINUX"){
1558			result.version="UNKNOWN"; result.name="UNKNOWN";
1559			if(ua.indexOf("Linux x86_64") != -1) result.bit="64";
1560			else result.bit="32";
1561		} else {
1562			result.version="UNKNOWN"; result.name="UNKNOWN";
1563		}
1564		
1565		//exlog("TOUCHENEX_UTIL.getOSInfo.result", result);
1566		return result;
1567	},
1568	isWin : function() {
1569		var OSInfo = TOUCHENEX_CONST.OSInfo.platform;
1570		if(!OSInfo) OSInfo = TOUCHENEX_UTIL.getOSInfo().platform;
1571		if (OSInfo == "WINDOWS") return true;
1572		return false;
1573	},
1574	isMac : function() {
1575		var OSInfo = TOUCHENEX_CONST.OSInfo.platform;
1576		if(!OSInfo) OSInfo = TOUCHENEX_UTIL.getOSInfo().platform;
1577		if (OSInfo == "MACOSX") return true;
1578		return false;
1579	},
1580	isLinux : function() {
1581		var OSInfo = TOUCHENEX_CONST.OSInfo.platform;
1582		if(!OSInfo) OSInfo = TOUCHENEX_UTIL.getOSInfo().platform;
1583		if (OSInfo == "LINUX") return true;
1584		return false;
1585	},
1586	isMobile : function() {
1587		var OSInfo = TOUCHENEX_CONST.OSInfo.platform;
1588		if(!OSInfo) OSInfo = TOUCHENEX_UTIL.getOSInfo().platform;
1589		if (OSInfo == "iOS" || OSInfo == "Android" || OSInfo == "Windows Phone") return true;
1590		return false;
1591	},
1592	getBrowserInfo : function(){
1593		var
1594			tp = navigator.platform,
1595			N= navigator.appName,
1596			ua= navigator.userAgent,
1597			tem;
1598		var result, M;
1599		
1600		//exlog("appName", N);
1601		//exlog("userAgent", ua);
1602		
1603		// if Edge
1604		M = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i);
1605		M = M ? {"browser":"Edge", "version":M[2]} : M;
1606		
1607		// if opera
1608		if(!M){
1609			M = ua.match(/(opera|opr)\/?\s*(\.?\d+(\.\d+)*)/i);
1610			if(M && (tem = ua.match(/version\/([\.\d]+)/i)) != null) M[2] = tem[1];
1611			M = M ? {"browser":"Opera", "version":M[2]} : M;
1612		}
1613		
1614		// if IE7 under
1615		/**
1616		if(!M) {
1617			M = ua.match(/MSIE ([67].\d+)/);
1618			if(M) M = {"browser":"MSIE", "version":M[1]};
1619		}
1620		**/
1621		// others
1622		if(!M) {
1623			M = ua.match(/(msie|trident|chrome|safari|firefox)\/?\s*(\.?\d+(\.\d+)*)/i);
1624			if(M){
1625				if((tem = ua.match(/rv:([\d]+)/)) != null) {
1626					M[2] = tem[1];
1627				} else if((tem = ua.match(/version\/([\.\d]+)/i)) != null) {
1628					M[2] = tem[1];
1629				}
1630				if(M[1] == "Trident") M[1] = "MSIE";
1631				M = M? {"browser":M[1], "version":M[2]} : {"browser":N, "version1":navigator.appVersion,"other":'-?'};
1632			}
1633		}
1634		
1635		if(!M){
1636			if(typeof Proxy){
1637				M = {"browser":"Edge", "version":""};
1638			}
1639		}
1640		
1641		if(!M){
1642			return {"browser":"UNDEFINED", "version":""};
1643		}
1644		
1645		if(M.version){
1646			var verArr = (M.version).split(".");
1647			M.version = verArr[0];
1648		}
1649		
1650		// bit
1651		if(tp){
1652			if(tp.toLowerCase().indexOf("win64") != -1){
1653				M.bit = "64";
1654			} else if (tp.toLowerCase().indexOf("win32") != -1){
1655				M.bit = "32";
1656			} else {
1657				M.bit = "";
1658			}
1659		}
1660		
1661		result = M;
1662		//exlog("CrossEXUtil.getBrowserInfo", result);
1663		return result;
1664	},
1665	getBrowserVer : function() {
1666		var browserInfo = TOUCHENEX_CONST.browserInfo;
1667		if(!browserInfo) browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
1668		return browserInfo.version;
1669	},
1670	getBrowserBit : function() {
1671		var browserInfo = TOUCHENEX_CONST.browserInfo;
1672		if(!browserInfo) browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
1673		return browserInfo.bit;
1674	},
1675	isIE : function() {
1676		var browserInfo = TOUCHENEX_CONST.browserInfo;
1677		if(!browserInfo) browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
1678		if(browserInfo.browser.toLowerCase().indexOf("msie") != -1) {
1679			return true;
1680		} else {
1681			return false;
1682		}
1683	},
1684	isEdge : function() {
1685		var browserInfo = TOUCHENEX_CONST.browserInfo;
1686		if(!browserInfo) browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
1687		if(browserInfo.browser.toLowerCase().indexOf("edge") != -1) {
1688			return true;
1689		} else {
1690			return false;
1691		}
1692	},
1693	isChrome : function() {
1694		// Chrome 1+
1695		//return !!window.chrome;
1696		var browserInfo = TOUCHENEX_CONST.browserInfo;
1697		if(!browserInfo) browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
1698		if(browserInfo.browser.toLowerCase().indexOf("chrome") != -1) {
1699			return true;
1700		} else {
1701			return false;
1702		}
1703	},
1704	isFirefox : function() {
1705		// Firefox 1.0+
1706		//return typeof InstallTrigger !== 'undefined';
1707		var browserInfo = TOUCHENEX_CONST.browserInfo;
1708		if(!browserInfo) browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
1709		if(browserInfo.browser.toLowerCase().indexOf("firefox") != -1) {
1710			return true;
1711		} else {
1712			return false;
1713		}
1714	},
1715	isOpera : function() {
1716		// Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
1717		//return !!window.opera || navigator.userAgent.indexOf('Opera') >= 0  || navigator.userAgent.indexOf('OPR') >= 0;
1718		var browserInfo = TOUCHENEX_CONST.browserInfo;
1719		if(!browserInfo) browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
1720		if(browserInfo.browser.toLowerCase().indexOf("opera") != -1) {
1721			return true;
1722		} else {
1723			return false;
1724		}
1725	},
1726	isSafari : function() {
1727		// At least Safari 3+: "[object HTMLElementConstructor]"
1728		//return Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
1729		var browserInfo = TOUCHENEX_CONST.browserInfo;
1730		if(!browserInfo) browserInfo = TOUCHENEX_UTIL.getBrowserInfo();
1731		if((browserInfo.browser).toLowerCase().indexOf("safari") != -1) {
1732			return true;
1733		} else {
1734			return false;
1735		}
1736	},
1737	typeEX : function() {
1738		if (TOUCHENEX_UTIL.isWin() && TOUCHENEX_UTIL.isIE()) return true;
1739		return false;
1740	},
1741	typeEdge : function() {
1742		if (TOUCHENEX_UTIL.isEdge()) return true;
1743		return false;
1744	},
1745	typeExtension : function() {
1746		if (
1747			(TOUCHENEX_UTIL.isWin() || TOUCHENEX_UTIL.isMac() || TOUCHENEX_UTIL.isLinux()) &&
1748			(TOUCHENEX_UTIL.isChrome() || TOUCHENEX_UTIL.isFirefox() || (TOUCHENEX_UTIL.isOpera() && TOUCHENEX_UTIL.getBrowserVer() > 26))
1749		) return true;
1750		return false;
1751	},
1752	typePlugin : function() {
1753		if ((TOUCHENEX_UTIL.isWin() || TOUCHENEX_UTIL.isMac()) && (TOUCHENEX_UTIL.isSafari())) return true;
1754		return false;
1755	},
1756	
1757	typeDaemon : function(){
1758		//"max supportBrowser": ["EDGE","CHROME","FIREFOX","OPERA","MSIE"]
1759		if(TOUCHENEX_UTIL.getOSInfo().platform == "WINDOWS" && TOUCHENEX_UTIL.getOSInfo().name == "10"){
1760			var daemonInfo = touchenexInfo.exEdgeInfo;
1761			var browserType = TOUCHENEX_UTIL.getBrowserInfo().browser;
1762			if(daemonInfo && daemonInfo.isUse
1763					&& daemonInfo.supportBrowser instanceof Array
1764					&& daemonInfo.supportBrowser.length > 0){
1765				for(var i = 0; i < daemonInfo.supportBrowser.length; i++){
1766					var reqBrowser = daemonInfo.supportBrowser[i];
1767					if(browserType.toUpperCase() == reqBrowser.toUpperCase()){
1768						return true;
1769					}
1770				}
1771			}
1772		}
1773		return false;
1774	},
1775	typeDaemonEX : function(pp){
1776		//20160620 Ãß°¡ - °øÅë »ç¿ëÇϵµ·Ï ¼öÁ¤
1777		//"max supportBrowser": ["EDGE","CHROME","FIREFOX","OPERA","MSIE"]
1778		if((TOUCHENEX_UTIL.isWin() && TOUCHENEX_UTIL.isSafari()) || TOUCHENEX_UTIL.isIE()){
1779			return false;
1780		}
1781		//mac safari 12¹öÀüºÎÅÍ´Â ¹«Á¶°Ç daemonÀ» Áö¿øÇÔ
1782		if(TOUCHENEX_UTIL.isMac() && TOUCHENEX_UTIL.isSafari() && TOUCHENEX_UTIL.getBrowserVer()>=12){
1783			return true;
1784		}
1785		
1786		//if(TOUCHENEX_UTIL.getOSInfo().platform == "WINDOWS"){
1787		if(typeof touchenexInfo != "undefined"){
1788			var daemonInfo = pp.exEdgeInfo;
1789			var supportBrowser;
1790			if(daemonInfo.allSupport == true){
1791				return true;
1792			}
1793			
1794			if(TOUCHENEX_UTIL.isWin()){
1795				supportBrowser = daemonInfo.supportBrowser;
1796			}else if(TOUCHENEX_UTIL.isMac()){
1797				supportBrowser = daemonInfo.macSupportBrowser;
1798			}else if(TOUCHENEX_UTIL.isLinux()){
1799				supportBrowser = daemonInfo.linuxSupportBrowser;
1800			}
1801			
1802			var browserType = TOUCHENEX_UTIL.getBrowserInfo().browser;
1803			if(daemonInfo && daemonInfo.isUse
1804					&& supportBrowser instanceof Array
1805					&& supportBrowser.length > 0){
1806				for(var i = 0; i < supportBrowser.length; i++){
1807					var reqBrowser = supportBrowser[i];
1808					if(browserType.toUpperCase() == reqBrowser.toUpperCase()){
1809						return true;
1810					}
1811				}
1812			}
1813		}
1814		return false;
1815	},
1816	chkOS : function(localOS, reqOS){
1817		//exlog("_UTIL.chkOS.localOS", localOS);
1818		//exlog("_UTIL.chkOS.reqOS", reqOS);
1819		var os = localOS.platform.toUpperCase();
1820		var ver = localOS.version;
1821		if(os == "WINDOWS" || os == "MACOSX" || os == "LINUX"){
1822			var reqVer = reqOS[os];
1823			if(reqVer){
1824				if(reqVer == "PASS" || reqVer == "ALL"){
1825					return true;
1826				} else if(reqVer == "NO"){
1827					return false;
1828				} else {
1829					if(ver == "UNKNOWN") return false;
1830					if(this.diffVersionOS(ver, reqVer)){
1831						return true;
1832					} else {
1833						if(this.isWin() && this.isSafari()){
1834							// windows safari´Â win8 ÀÌ»óÀº ¸ðµÎ 6.2·Î Ç¥½Ã
1835							if(ver == "6.2" && (reqVer == "6.2" || reqVer == "6.3" || reqVer == "10.0")){
1836								return true;
1837							}
1838						}
1839					}
1840				}
1841			}
1842		}
1843		return false;
1844	},
1845	chkBrowser : function(localBrowser, reqBrowser){
1846		//exlog("_UTIL.chkBrowser.localBrowser", localBrowser);
1847		//exlog("_UTIL.chkBrowser.reqBrowser", reqBrowser);
1848		var browser = localBrowser.browser;
1849		var ver = parseInt(localBrowser.version);
1850		
1851		var reqVer = reqBrowser[browser.toUpperCase()];
1852		if(!reqVer){
1853			if(this.isWin() && this.isSafari()){
1854				reqVer = reqBrowser.SAFARI_WIN;
1855			} else if(this.isMac() && this.isSafari()){
1856				reqVer = reqBrowser.SAFARI_MAC;
1857			} else {
1858				return false;
1859			}
1860		}
1861		
1862		if(reqVer){
1863			if(reqVer == "PASS" || reqVer == "ALL"){
1864				return true;
1865			} else if(reqVer == "NO"){
1866				return false;
1867			} else {
1868				reqVer = parseInt(reqVer);
1869				if(ver >= reqVer){
1870					return true;
1871				}
1872			}
1873		}
1874		return false;
1875	},
1876	createId : function() {
1877		//var id = new Date().getTime() + "_" + Math.floor(Math.random() * 10000)+1;
1878		var id = new Date().getTime() + "_" + TOUCHENEX_UTIL.random();
1879		//exlog("TOUCHENEX_UTIL.createId.id", id);
1880		return id;
1881	},
1882	/**
1883	 * true : ±âÁ¸ ¼³Ä¡µÈ ¸ðµâÀÌ ¹öÀü ´õ ³ô°Å³ª °°À½
1884	 * false : ±âÁ¸ ¼³Ä¡µÈ ¸ðµâÀÌ ¹öÀüÀÌ ³·À½. ¾÷±×·¹À̵尡 ÇÊ¿äÇÔ.
1885	 */
1886	diffVersion : function( curVersion, svrVersion ) {
1887		
1888		if(svrVersion == undefined)
1889			return true;
1890		
1891		exlog("_UTIL.diffVersion.client version", curVersion);
1892		exlog("_UTIL.diffVersion.server version", svrVersion);
1893	    var index;
1894	    try {
1895	    	index = curVersion.indexOf('version:', 0);
1896	    } catch (e){
1897	    	return false;
1898	    }
1899	    
1900	    if(index >= 0) {
1901	        curVersion = curVersion.substring(index + 8, curVersion.length);
1902	        var arrayOldVersion = curVersion.split('.');
1903	        if(arrayOldVersion.length < 4) arrayOldVersion = curVersion.split(',');
1904	        if(arrayOldVersion.length < 4) return false;
1905	        var arrayNewVersion = svrVersion.split('.');
1906
1907	        for(var i = 0; i < 4; i++) {
1908	        	if (parseInt(arrayOldVersion[i], 10) > parseInt(arrayNewVersion[i], 10)) {
1909	        		return true;
1910	        	} else if (parseInt(arrayOldVersion[i], 10) < parseInt(arrayNewVersion[i], 10)) {
1911	        		return false;
1912	        	}
1913	        }
1914	        return true;
1915	    } else {
1916	        var arrayOldVersion = curVersion.split('.');
1917	        if(arrayOldVersion.length < 4) arrayOldVersion = curVersion.split(',');
1918	        if(arrayOldVersion.length < 4) return false;	        
1919	        var arrayNewVersion = svrVersion.split('.');
1920	        
1921	        for(var i = 0; i < 4; i++) {
1922	        	if (parseInt(arrayOldVersion[i], 10) > parseInt(arrayNewVersion[i], 10)) {
1923	        		return true;
1924	        	} else if (parseInt(arrayOldVersion[i], 10) < parseInt(arrayNewVersion[i], 10)) {
1925	        		return false;
1926	        	}
1927	        }
1928	        return true;
1929	    }
1930	},
1931	diffVersionOS : function( curVersion, svrVersion ){
1932        var arrayOldVersion = curVersion.split('.');
1933        var arrayNewVersion = svrVersion.split('.');
1934        if(isNaN(parseInt(arrayOldVersion[0], 10))) return false;
1935        for(var i = 0; i < arrayNewVersion.length; i++) {
1936        	if (parseInt(arrayOldVersion[i], 10) > parseInt(arrayNewVersion[i], 10)) {
1937        		return true;
1938        	} else if (parseInt(arrayOldVersion[i], 10) < parseInt(arrayNewVersion[i], 10)) {
1939        		return false;
1940        	}
1941        }
1942        return true;
1943	},
1944	chkCrossEXDiv : function() {
1945		//if(TOUCHENEX_UTIL.typeEX() || TOUCHENEX_UTIL.isLinux()){
1946		if(TOUCHENEX_UTIL.typeEX()){
1947			// div, iframe, form, script name _CONST set...
1948			TOUCHENEX_CONST.exDivName = "crossexDiv";
1949			TOUCHENEX_CONST.exIframeName = "crossexIfr";
1950			TOUCHENEX_CONST.exScriptName = "crossexScr";
1951			TOUCHENEX_CONST.exFormName = "__CROSSEX_FORM__";
1952			TOUCHENEX_CONST.exFormDataName = "__CROSSEX_DATA__";
1953                     
1954			var chk = document.getElementById(TOUCHENEX_CONST.exDivName);
1955			if(!chk) {
1956				var exDiv = document.createElement("div");
1957				exDiv.id = TOUCHENEX_CONST.exDivName;
1958				exDiv.style.display = "none";
1959                                
1960				if(document.body) {
1961					document.body.appendChild(exDiv);
1962				} else {
1963					exalert("_UTIL.chkCrossEXDiv", "body ű׸¦ »ý¼ºÇØ ÁֽʽÿÀ");
1964					return;
1965				}
1966                                
1967				var exForm = document.createElement("form");
1968				exForm.method = "POST";
1969				exForm.id = TOUCHENEX_CONST.exFormName;
1970				exForm.name = TOUCHENEX_CONST.exFormName;
1971                                
1972				var exNode = document.createElement("input");
1973				exNode.type = "hidden";
1974				exNode.id = TOUCHENEX_CONST.exFormDataName;
1975				exNode.name = TOUCHENEX_CONST.exFormDataName;
1976                                
1977				exForm.appendChild(exNode);
1978				exDiv.appendChild(exForm);
1979			}
1980		}
1981		return;
1982	},
1983	loadScript : function( url ) {
1984		
1985		var newScript = document.createElement("script");
1986		newScript.type = "text/javascript";
1987		if(newScript.readyState) { // IE8 under
1988			newScript.onreadystatechange = function() {
1989				exlog("_UTIL.loadScript.readyState", newScript.readyState);
1990				if (newScript.readyState == 'loading' || newScript.readyState == 'loaded') {
1991					newScript.onreadystatechange = null;
1992					exlog("_UTIL.loadScript", "loadScript load error");
1993					//exalert("_UTIL.loadScript", "loadScript load error");
1994				}
1995			};
1996		} else {
1997			newScript.onerror = function() {
1998				exlog("_UTIL.loadScript", "loadScript load error");
1999				//exalert("_UTIL.loadScript", "loadScript load error");
2000			};
2001		}
2002		
2003		try {
2004			newScript.src = url;
2005		} catch (e) {
2006			exlog("_UTIL.loadscript", "LoadScript not https load error");
2007			//exalert("_UTIL.loadScript", "LoadScript not https load error");
2008		}
2009		//exlog("TOUCHENEX_UTIL.loadScript", url);
2010		//document.getElementsByTagName("head")[0].appendChild(newScript);
2011		window[TOUCHENEX_CONST.exDivName].appendChild(newScript);
2012	},
2013	random : function(){
2014		try{
2015			if(!window['_ex_m_w']) window['_ex_m_w'] = 123456789;
2016			if(!window['_ex_m_z']) window['_ex_m_z'] = 987654321;
2017			if(!window['_ex_mask']) window['_ex_mask'] = 0xffffffff;
2018			
2019			_ex_m_z = (36969 * (_ex_m_z & 65535) + (_ex_m_z >> 16)) & _ex_mask;
2020			_ex_m_w = (18000 * (_ex_m_w & 65535) + (_ex_m_w >> 16)) & _ex_mask;
2021		    var result = ((_ex_m_z << 16) + _ex_m_w) & _ex_mask;
2022		    result /= 4294967296;
2023		    return parseInt((result + 0.5) * 1000000).toString();
2024		} catch(e){
2025			return '';
2026		}
2027	},
2028	createFuncByName : function( functionName ) {
2029		var funcNameArr = functionName.split(".");
2030		var func = funcNameArr.pop();
2031		var funcArr;
2032		if(funcNameArr.length == 0){
2033			return window[func];
2034		} else {
2035			for (var i = 0; i < funcNameArr.length; i++) {
2036				if(i == 0){
2037					funcArr = window[funcNameArr[i]];
2038					this.thisObj = funcArr;
2039				} else {
2040					funcArr = funcArr[funcNameArr[i]];
2041				}
2042			}
2043			return funcArr[func];
2044		}
2045	},
2046	runCallback : function(func, args){
2047		//exlog("_UTIL.runCallback.func", func);
2048		//exlog("_UTIL.runCallback.args", args);
2049		try{
2050			if(typeof func == "function"){
2051				if(args instanceof Array){
2052					func.apply(this, args);
2053				} else {
2054					func(args);
2055				}
2056			} else if(typeof func == "string"){
2057				var runFunc = TOUCHENEX_UTIL.createFuncByName(func);
2058				if(args instanceof Array){
2059					runFunc.apply(this, args);
2060				} else {
2061					runFunc(args);
2062				}
2063			} else {
2064				exlog("_UTIL.runCallback", "func type not defined");
2065			}
2066		} catch(e){
2067			exlog("_UTIL.runCallback [exception]", e);
2068			exalert("_UTIL.runCallback [exception]", e);
2069		}
2070	},
2071	Base64 : {
2072		// private property
2073		_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
2074		// public method for encoding
2075		encode : function( input ) {
2076			var output = "";
2077			var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
2078			var i = 0;
2079			input = this._utf8_encode(input);
2080			while (i < input.length) {
2081				chr1 = input.charCodeAt(i++);
2082				chr2 = input.charCodeAt(i++);
2083				chr3 = input.charCodeAt(i++);
2084				enc1 = chr1 >> 2;
2085				enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
2086				enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
2087				enc4 = chr3 & 63;
2088				if ( isNaN(chr2) ) {
2089					enc3 = enc4 = 64;
2090				} else if ( isNaN(chr3) ) {
2091					enc4 = 64;
2092				}
2093				output = output + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
2094			}
2095			return output;
2096		},
2097		// public method for decoding
2098		decode : function( input ) {
2099			var output = "";
2100			var chr1, chr2, chr3;
2101			var enc1, enc2, enc3, enc4;
2102			var i = 0;
2103			input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
2104			while (i < input.length) {
2105				enc1 = this._keyStr.indexOf(input.charAt(i++));
2106				enc2 = this._keyStr.indexOf(input.charAt(i++));
2107				enc3 = this._keyStr.indexOf(input.charAt(i++));
2108				enc4 = this._keyStr.indexOf(input.charAt(i++));
2109				chr1 = (enc1 << 2) | (enc2 >> 4);
2110				chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
2111				chr3 = ((enc3 & 3) << 6) | enc4;
2112				output = output + String.fromCharCode(chr1);
2113				if ( enc3 != 64 ) {
2114					output = output + String.fromCharCode(chr2);
2115				}
2116				if ( enc4 != 64 ) {
2117					output = output + String.fromCharCode(chr3);
2118				}
2119			}
2120			output = this._utf8_decode(output);
2121			return output;
2122		},
2123		// private method for UTF-8 encoding
2124		_utf8_encode : function( string ) {
2125			string = string.replace(/\r\n/g, "\n");
2126			var utftext = "";
2127			for ( var n = 0; n < string.length; n++ ) {
2128				var c = string.charCodeAt(n);
2129				if ( c < 128 ) {
2130					utftext += String.fromCharCode(c);
2131				} else if ( (c > 127) && (c < 2048) ) {
2132					utftext += String.fromCharCode((c >> 6) | 192);
2133					utftext += String.fromCharCode((c & 63) | 128);
2134				} else {
2135					utftext += String.fromCharCode((c >> 12) | 224);
2136					utftext += String.fromCharCode(((c >> 6) & 63) | 128);
2137					utftext += String.fromCharCode((c & 63) | 128);
2138				}
2139			}
2140			return utftext;
2141		},
2142		// private method for UTF-8 decoding
2143		_utf8_decode : function( utftext ) {
2144			var string = "";
2145			var i = 0;
2146			var c = c1 = c2 = 0;
2147			while (i < utftext.length) {
2148				c = utftext.charCodeAt(i);
2149				if ( c < 128 ) {
2150					string += String.fromCharCode(c);
2151					i++;
2152				} else if ( (c > 191) && (c < 224) ) {
2153					c2 = utftext.charCodeAt(i + 1);
2154					string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
2155					i += 2;
2156				} else {
2157					c2 = utftext.charCodeAt(i + 1);
2158					c3 = utftext.charCodeAt(i + 2);
2159					string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
2160					i += 3;
2161				}
2162			}
2163			return string;
2164		}
2165	}
2166};
2167
2168window.exlog = TOUCHENEX_UTIL.exlog;
2169window.exalert = TOUCHENEX_UTIL.exalert;
2170

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.