/javascripts/d3/detector.js
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})();