PageRenderTime 68ms CodeModel.GetById 46ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/detector.js

https://github.com/wyrover/ChromeSnifferPlus
JavaScript | 502 lines | 435 code | 32 blank | 35 comment | 82 complexity | 30a017f6ad67e0668dc08d329cb6433b MD5 | raw file
  1/**
  2 * Chrome AppSniffer
  3 *
  4 * Detect apps run on current page and send back to background page.
  5 * Some part of this script was refered from Wappalyzer Firefox Addon.
  6 *
  7 * @author Bao Nguyen <contact@nqbao.com>
  8 * @author justjavac <justjavac@gmail.com>
  9 * @license GPLv3
 10 **/
 11 
 12(function () {
 13	var _apps = {};
 14	var doc = document.documentElement;
 15	var name;
 16  	var r;
 17
 18	// 1: detect by meta tags, the first matching group will be version
 19	// 根据 meta 信息判断
 20	var metas = doc.getElementsByTagName("meta");
 21	var meta_tests = {
 22		'generator': {
 23			'Joomla': /joomla!?\s*([\d\.]+)?/i,
 24			'vBulletin': /vBulletin\s*(.*)/i,
 25			'WordPress': /WordPress\s*(.*)/i,
 26			'XOOPS': /xoops/i,
 27			'Plone': /plone/i,
 28			'MediaWiki': /MediaWiki/i,
 29			'CMSMadeSimple': /CMS Made Simple/i,
 30			'SilverStripe': /SilverStripe/i,
 31			'Movable Type': /Movable Type/i,
 32			'Amiro.CMS': /Amiro/i,
 33			'Koobi': /koobi/i,
 34			'bbPress': /bbPress/i,
 35			'DokuWiki': /dokuWiki/i,
 36			'TYPO3': /TYPO3/i,
 37			'PHP-Nuke': /PHP-Nuke/i,
 38			'DotNetNuke': /DotNetNuke/i,
 39			'Sitefinity': /Sitefinity\s+(.*)/i,
 40			'WebGUI': /WebGUI/i,
 41			'ez Publish': /eZ\s*Publish/i,
 42			'BIGACE': /BIGACE/i,
 43			'TypePad': /typepad\.com/i,
 44			'Blogger': /blogger/i,
 45			'PrestaShop': /PrestaShop/i,
 46			'SharePoint': /SharePoint/,
 47			'JaliosJCMS': /Jalios JCMS/i,
 48			'ZenCart': /zen-cart/i,
 49			'WPML': /WPML/i,
 50			'PivotX': /PivotX/i,
 51			'OpenACS': /OpenACS/i,
 52			'AlphaCMS': /alphacms\s+(.*)/i,
 53			'concrete5': /concrete5 -\s*(.*)$/,
 54			'Webnode': /Webnode/,
 55			'GetSimple': /GetSimple/,
 56			'DataLifeEngine': /DataLife Engine/,
 57			'ClanSphere': /ClanSphere/,
 58		    'Mura CMS': /Mura CMS\s*(.*)/i,
 59		    'Tiki Wiki CMS Groupware': /Tiki/i
 60		},
 61		'copyright': {
 62			'phpBB': /phpBB/i
 63		},
 64		'elggrelease': {
 65			'Elgg': /.+/
 66		},
 67		'powered-by': {
 68      		'Serendipity': /Serendipity/i
 69		},
 70		'author': {
 71			'Avactis': /Avactis Team/i
 72		}
 73	};
 74
 75  for (var idx in metas) {
 76		var m = metas[idx];
 77    	name = m.name ? m.name.toLowerCase() : "";
 78
 79		if (!meta_tests[name]) continue;
 80		
 81    	for (var t in meta_tests[name]) {
 82			if (t in _apps) continue;
 83			
 84		    r = meta_tests[name][t].exec(m.content);
 85		    if (r) {
 86				_apps[t] = r[1] ? r[1] : -1;
 87			}
 88		}
 89	}
 90
 91	// 2: detect by script tags
 92	// 根据 script 标签判断
 93	var scripts = doc.getElementsByTagName("script");
 94	
 95	var script_tests = {
 96		'\u767e\u5ea6\u7edf\u8ba1': /hm\.baidu\.com\/h\.js/i,	// 百度统计
 97		'cnzz': /(w|s14)\.cnzz\.com\/(c|stat)\.php/i,
 98		'bShare':  /static\.bshare\.cn\/b/,
 99		'\u767e\u5ea6\u5206\u4eab': /bdimg\.share\.baidu\.com\/static\/js\//,	// 百度分享
100		'\u591a\u8bf4': /static\.duoshuo\.com\/embed\.js/,	// 多说
101		'\u53cb\u8350': /v\d\.ujian\.cc\/code\/ujian\.js/,	// 友荐 
102		'\u53cb\u8a00': /v\d\.uyan\.cc\/(code\/uyan\.js|js\/iframe\.js)/,	// 友言
103		'JiaThis': /v\d\.jiathis\.com\/code(_mini)?\/jiathis/,
104		'\u65e0\u89c5': /widget\.wumii\.(cn|com)\/ext\/relatedItemsWidget/,		// 无觅相关文章插件
105		'segmentfault': /w\.segmentfault\.com\/card\/\d+\.js/i,		
106
107		'Google Analytics': /google-analytics\.com\/(ga|urchin).js/i,
108		'Quantcast': /quantserve\.com\/quant\.js/i,
109		'Prototype': /prototype\.js/i,
110		'Joomla': /\/components\/com_/,
111		'Ubercart': /uc_cart/i,
112		'Closure': /\/goog\/base\.js/i,
113		'MODx': /\/min\/b=.*f=.*/,
114		'MooTools': /mootools/i,
115		'Dojo': /dojo(\.xd)?\.js/i,
116		'script.aculo.us': /scriptaculous\.js/i,
117    	'Disqus': /disqus.com/i,
118		'GetSatisfaction': /getsatisfaction\.com\/feedback/i,
119		'Wibiya': /wibiya\.com\/Loaders\//i,
120		'reCaptcha': /(google\.com\/recaptcha|api\.recaptcha\.net\/)/i,
121		'Mollom': /mollom\/mollom\.js/i, // only work on Drupal now
122		'ZenPhoto': /zp-core\/js/i,
123		'Gallery2': /main\.php\?.*g2_.*/i,
124		'AdSense': /pagead\/show_ads\.js/,
125		'XenForo': /js\/xenforo\//i,
126		'Cappuccino': /Frameworks\/Objective-J\/Objective-J\.js/,
127		'Avactis': /\/avactis-themes\//i,
128		'Volusion': /a\/j\/javascripts\.js/,
129		'AddThis': /addthis\.com\/js/,
130		
131		'BuySellAds': /buysellads.com\/.*bsa\.js/,
132		'Weebly': /weebly\.com\/weebly\//,
133		'Bootstrap': /bootstrap-.*\.js/,
134		'Jigsy': /javascripts\/asterion\.js/, // may change later
135		'Yola': /analytics\.yola\.net/, // may change later
136	    'Alfresco': /(alfresco)+(-min)?(\/scripts\/menu)?\.js/, // both Alfresco Share and Explorer apps
137	    'Mura CMS': /mura\/js/,
138	    'Tiki Wiki CMS Groupware': /tiki-js/,
139	    'OpenTag': /opentag.*\.js/,
140	    'KISSmetrics': /i.kissmetrics.com\/i.js/
141	};
142
143    for (var idx in scripts) {
144		var s = scripts[idx];
145		if (!s.src) continue;
146		s = s.src;
147
148    	for (var t in script_tests) {
149			if (t in _apps) continue;
150        	if (script_tests[t].test(s)) {
151				_apps[t] = -1;
152			}
153		}
154	}
155
156	// 3: detect by domains
157	// 根据 domain 信息判断
158
159	// 4: detect by regexp
160	// 用正则表达式判断
161	var text = document.documentElement.outerHTML;
162	var text_tests = {
163		'SMF': /<script .+\s+var smf_/i,
164		'Magento': /var BLANK_URL = '[^>]+js\/blank\.html'/i,
165		'Tumblr': /<iframe src=("|')http:\/\/\S+\.tumblr\.com/i,
166		'WordPress': /<link rel=("|')stylesheet("|') [^>]+wp-content/i,
167		'Closure': /<script[^>]*>.*goog\.require/i,
168		'Liferay': /<script[^>]*>.*LifeRay\.currentURL/i,
169		'vBulletin': /vbmenu_control/i,
170		'MODx': /(<a[^>]+>Powered by MODx<\/a>|var el= \$\('modxhost'\);|<script type=("|')text\/javascript("|')>var MODX_MEDIA_PATH = "media";)/i,
171		'miniBB': /<a href=("|')[^>]+minibb.+\s*<!--End of copyright link/i,
172		'PHP-Fusion': /(href|src)=["']?infusions\//i, // @todo: recheck this pattern again
173		'OpenX': /(href|src)=["'].*delivery\/(afr|ajs|avw|ck)\.php[^"']*/,
174		'GetSatisfaction': /asset_host\s*\+\s*"javascripts\/feedback.*\.js/igm, // better recognization
175		'Fatwire': /\/Satellite\?|\/ContentServer\?/,
176		'Contao': /powered by (TYPOlight|Contao)/i,
177		'Moodle' : /<link[^>]*\/theme\/standard\/styles.php".*>|<link[^>]*\/theme\/styles.php\?theme=.*".*>/,
178		'1c-bitrix' : /<link[^>]*\/bitrix\/.*?>/i,
179		'OpenCMS' : /<link[^>]*\.opencms\..*?>/i,
180    	'HumansTxt': /<link[^>]*rel=['"]?author['"]?/i,
181		'GoogleFontApi': /ref=["']?http:\/\/fonts.googleapis.com\//i,
182		'Prostores' : /-legacycss\/Asset">/,
183		'osCommerce': /(product_info\.php\?products_id|_eof \/\/-->)/,
184		'OpenCart': /index.php\?route=product\/product/,
185		'Shibboleth': /<form action="\/idp\/Authn\/UserPassword" method="post">/
186	};
187
188    for (var t in text_tests) {
189		if (t in _apps) continue;
190    	if (text_tests[t].test(text)) {
191			_apps[t] = -1;
192		}
193	}
194	
195	// TODO: merge inline detector with version detector
196	
197	// 5: detect by inline javascript
198	// 根据 inline javascript 判断
199	var js_tests = {		
200		'Highcharts': function() {
201			return window.Highcharts;
202		},
203		'Zepto.js': function() {
204			return window.Zepto && window.Zepto.fn;
205		},
206		'CodeIgniter': function() {
207			return document.cookie.indexOf("cisession") != -1;
208		},
209		'Java': function() {
210			return document.cookie.indexOf("JSESSIONID") != -1;
211		},
212		'Domino': function() {
213			return document.cookie.indexOf("LtpaToken") != -1||document.cookie.indexOf("DomAuthSessId") != -1;
214		},
215		'Drupal': function() {
216      		return window.Drupal;
217		},
218		'TomatoCMS': function() {
219      		return window.Tomato;
220		},
221		'MojoMotor': function() {
222      		return window.Mojo;
223		},
224		'ErainCart': function() {
225      		return window.fn_register_hooks;
226		},
227		'SugarCRM': function() {
228      		return window.SUGAR;
229		},
230		'YUI': function() {
231      		return window.YAHOO;
232		},
233		'YUI 3': function() {
234      		return window.YUI;
235		},
236		'jQuery': function() {
237      		return window.jQuery;
238		},
239		'jQuery UI': function() {
240      		return window.jQuery && window.jQuery.ui;
241		},
242		'Typekit': function() {
243      		return window.Typekit;
244		},
245		'Facebook': function() {
246      		return window.FB && window.FB.api;
247		},
248		'ExtJS': function() {
249      		return window.Ext;
250		},
251		'Modernizr': function() {
252      		return window.Modernizr;
253		},
254		'Raphael': function() {
255      		return window.Raphael;
256		},
257		'Cufon': function() {
258      		return window.Cufon;
259		},
260		'sIFR': function() {
261      		return window.sIFR;
262		},
263		'Xiti': function() {
264      		return window.xtsite && window.xtpage;
265		},
266		'Piwik': function() {
267      		return window.Piwik;
268		},
269		'IPB': function() {
270      		return window.IPBoard;
271		},
272		'MyBB': function() {
273      		return window.MyBB;
274		},
275		'Clicky': function() {
276      		return window.clicky;
277		},
278		'Woopra': function() {
279      		return window.woopraTracker;
280		},
281		'RightJS': function() {		
282      		return window.RightJS;
283		},
284		'OpenWebAnalytics': function() {
285      		return window.owa_baseUrl;
286		},
287		'Prettify': function() {
288      		return window.prettyPrint;
289		},
290		'SiteCatalyst': function() {
291      		return window.s_account;
292		},
293		'Twitter': function() {
294      		return window.twttr;
295		},
296		'Coremetrics': function() {
297      		return window.cmCreatePageviewTag;
298		},
299		'Buzz': function() {
300      		return window.google_buzz__base_url;
301		},
302		'Plus1': function() {
303			return window.gapi && window.gapi.plusone;
304		},
305		'Google Loader': function() {
306      		return window.google && window.google.load;
307		},
308		'GoogleMapApi': function() {
309      		return window.google && window.google.maps;
310		},
311		'Head JS': function() {
312      		return window.head && window.head.js;
313		},
314		'SWFObject': function() {
315      		return window.swfobject;
316		},
317		'Chitika': function() {
318			return window.ch_client && window.ch_write_iframe;
319		},
320		'Jimdo': function() {
321      		return window.jimdoData;
322		},
323		'Webs': function() {
324      		return window.webs;
325		},
326		'Backbone.js': function() {
327			return window.Backbone && typeof(window.Backbone.sync) === 'function';
328		},
329		'Underscore.js': function() {
330      		return window._ && typeof(window._.identity) === 'function' &&
331        		window._.identity('abc') === 'abc';
332		},
333		'Spine': function() {
334      		return window.Spine;
335    	},
336    	'Angular': function () {
337      		return window.angular;
338    	},
339    	'Ning': function () {
340      		return window.ning;
341    	},
342    	'ektron': function () {
343      		return window.Ektron;
344    	},
345    	'etracker': function () {
346      		return window.et_params;
347    	},
348    	'SPDY': function () {
349      		return window.chrome.loadTimes().wasFetchedViaSpdy;
350    	},
351    	'LiveStreet': function () {
352      		return window.LIVESTREET_SECURITY_KEY;
353		}
354	};
355	
356    for (var t in js_tests) {
357		if (t in _apps) continue;
358    	if (js_tests[t]()) {
359			_apps[t] = -1;
360		}
361	}
362
363	// 6: detect some script version when available
364	// 判断 javascript 版本
365	var js_versions = {
366		'Highcharts': function() {
367      		if ('Highcharts' in window && Highcharts.version !== undefined)
368        		return window.Highcharts.version;
369		},
370		'Prototype': function() {
371      		if ('Prototype' in window && Prototype.Version !== undefined)
372        		return window.Prototype.Version;
373		},
374		'script.aculo.us': function() {
375      		if ('Scriptaculous' in window && Scriptaculous.Version !== undefined)
376        		return window.Scriptaculous.Version;
377		},
378		'jQuery': function() {
379      		if (typeof jQuery === 'function' && jQuery.prototype.jquery !== undefined)
380        		return jQuery.prototype.jquery;
381		},
382		'jQuery UI': function() {
383      		if (typeof jQuery === 'function' && jQuery.ui && jQuery.ui.version !== undefined)
384        		return jQuery.ui.version;
385		},
386		'Dojo': function() {
387      		if (typeof dojo === 'object' && dojo.version.toString() !== undefined)
388        		return dojo.version;
389		},
390		'YUI': function() {
391      		if (typeof YAHOO === 'object' && YAHOO.VERSION !== undefined)
392        		return YAHOO.VERSION;
393		},
394		'YUI 3': function() {
395      		if ('YUI' in window && typeof YUI === 'function' && YUI().version !== undefined)
396        		return YUI().version;
397		},
398		'MooTools': function() {
399      		if (typeof MooTools === 'object' && MooTools.version !== undefined)
400        		return MooTools.version;
401		},
402		'ExtJS': function() {
403      		if (typeof Ext === 'object' && Ext.version !== undefined)
404        		return Ext.version;
405		},
406		'RightJS': function() {
407      		if ('RightJS' in window && RightJS.version !== undefined)
408        		return RightJS.version;
409		},
410		'Modernizr': function() {
411      		if (window.Modernizr && Modernizr._version !== undefined)
412        		return Modernizr._version;
413		},
414		'Raphael': function() {
415      		if (window.Raphael && Raphael.version !== undefined)
416        		return Raphael.version;
417		},
418		'Backbone.js': function() {
419			if (window.Backbone && window.Backbone.VERSION)
420				return window.Backbone.VERSION;
421		},
422		'Underscore.js': function() {
423			if (window._ && window._.VERSION)
424				return window._.VERSION;
425		},
426		'Spine': function() {
427			if(window.Spine && window.Spine.version)
428				return window.Spine.version;	
429    	},
430    	'Angular': function () {
431      		if (window.angular && window.angular.version && 'full' in window.angular.version)
432        		return window.angular.version.full;
433		}
434	};
435	
436  	for (var a in _apps) {
437    	if (_apps[a] === -1 && js_versions[a]) {
438      		r = js_versions[a]();
439      		_apps[a] = r ? r : -1;
440		}
441	}
442
443	// 7: detect by header
444	// 根据 header 信息判断
445	// @todo
446
447	// 8: detect based on built-in database
448	// 根据内建的数据库判断
449	// @todo
450
451	// 9: detect based on defined css classes
452	// 根据 css 类判断
453	var cssClasses = {
454		'Bootstrap': ['hero-unit', '.carousel-control', '[class^="icon-"]:last-child']
455	};
456
457  	for (var t in cssClasses) {
458		if (t in _apps) continue;
459
460		var found = true;
461    	for (var css in cssClasses[t]) {
462			var act = false;
463      		name = cssClasses[t][css];
464			
465			/* Iterate through all registered css classes and check for presence */
466      		for (var cssFile in document.styleSheets) {
467        		for (var cssRule in document.styleSheets[cssFile].cssRules) {
468					var style = document.styleSheets[cssFile].cssRules[cssRule];
469
470					if (typeof style === "undefined") continue;
471					if (typeof style.selectorText === "undefined") continue;
472
473          			if (style.selectorText.indexOf(name) !== -1) {
474						act = true;
475						break;
476					}
477				}
478				if (act === true) break;
479			}
480
481			found = found & act;
482		}
483
484    	if (found === true) {
485			_apps[t] = -1;
486    	}
487    	else {
488			break;
489		}
490	}
491
492	// convert to array
493	var jsonString = JSON.stringify(_apps);
494	// send back to background page
495	var meta = document.getElementById('chromesniffer_meta');
496	meta.content = jsonString;
497
498	//Notify Background Page
499	var done = document.createEvent('Event');
500	done.initEvent('ready', true, true);
501	meta.dispatchEvent(done);
502})();