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