PageRenderTime 35ms CodeModel.GetById 12ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/javascripts/d3/detector.js

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