wappalyzer_rb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in wappalyzer_rb.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+ # Capybara request specs
17
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
18
+ end
19
+
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ wappalyzer-ruby
2
+ ===============
3
+
4
+ Analyzes a provided url and returns any services it can detect.
5
+
6
+ Usage:
7
+
8
+ url = 'http://some.url.com'
9
+ WappalyzerRb.new(url).analysis #=> ['Ruby', 'nginx', ...]
10
+
11
+ It is a fork of https://github.com/ElbertF/Wappalyzer (commit 7431c5e1e1).
12
+
13
+ TODO
14
+ ----
15
+
16
+ * Break off wappalyzer.rb config into some other file
17
+ * Write a script to automatically translate apps.js to a ruby config file
18
+ * Turn this into a gem
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,349 @@
1
+ module WappalyzerRb
2
+ CATEGORIES = [
3
+ nil,
4
+ 'cms',
5
+ 'message-boards',
6
+ 'database-managers',
7
+ 'documentation-tools',
8
+ 'widgets',
9
+ 'web-shops',
10
+ 'photo-galleries',
11
+ 'wikis',
12
+ 'hosting-panels',
13
+ 'analytics',
14
+ 'blogs',
15
+ 'javascript-frameworks',
16
+ 'issue-trackers',
17
+ 'video-players',
18
+ 'comment-systems',
19
+ 'captchas',
20
+ 'font-scripts',
21
+ 'web-frameworks',
22
+ 'miscellaneous',
23
+ 'editors',
24
+ 'lms',
25
+ 'web-servers',
26
+ 'cache-tools',
27
+ 'rich-text editors',
28
+ 'javascript-graphics',
29
+ 'mobile-frameworks',
30
+ 'programming-languages',
31
+ 'operating-systems',
32
+ 'search-engines'
33
+ ]
34
+
35
+ APPS = {
36
+ '1und1' => { cats: [ 6 ], url: /\/shop\/catalog\/browse\?sessid\=/ },
37
+ '1C-Bitrix' => { cats: [ 1 ], html: /<link[^>]+components\/bitrix/i, script: /1c\-bitrix/i },
38
+ '2z Project' => { cats: [ 1 ], meta: { 'generator' => /2z project/i } },
39
+ 'AddThis' => { cats: [ 5 ], script: /addthis\.com\/js/, env: /^addthis$/ },
40
+ 'Adobe GoLive' => { cats: [ 20 ], meta: { 'generator' => /Adobe GoLive/i } },
41
+ 'Advanced Web Stats' => { cats: [ 10 ], html: /aws.src = [^<]+caphyon\-analytics/i },
42
+ 'Ametys' => { cats: [ 1 ], meta: { 'generator' => /(Ametys|Anyware Technologies)/i }, script: /STools.js/ },
43
+ 'Amiro.CMS' => { cats: [ 1 ], meta: { 'generator' => /Amiro/i } },
44
+ 'AOLserver' => { cats: [ 22 ], headers: { 'Server' => /AOLserver/i } },
45
+ 'Apache' => { cats: [ 22 ], headers: { 'Server' => /(Apache($|[^-])|HTTPD)/i } },
46
+ 'Apache Tomcat' => { cats: [ 22 ], headers: { 'Server' => /Apache-Coyote/i } },
47
+ 'Apache Traffic Server' => { cats: [ 22 ], headers: { 'Server' => /YTS/i } },
48
+ 'Arc Forum' => { cats: [ 2 ], html: /ping\.src = node\.href;/ },
49
+ 'ATG Web Commerce' => { cats: [ 6 ], headers: { 'X-ATG-Version' => /ATG/i }, html: /<[^>]+_DARGS/ },
50
+ 'Atlassian Confluence' => { cats: [ 8 ], html: /Powered by <a href=.http:\/\/www\.atlassian\.com\/software\/confluence/i },
51
+ 'Atlassian Jira' => { cats: [ 13 ], env: /^jira$/i, html: /Powered by <a href=.http:\/\/www\.atlassian\.com\/software\/jira/i, implies: [ 'Java' ] },
52
+ 'Alloy' => { cats: [ 12 ], env: /^AUI$/ },
53
+ 'AWStats' => { cats: [ 10 ], meta: { 'generator' => /AWStats/i } },
54
+ 'Banshee' => { cats: [ 1, 18 ], html: /Built upon the <a href=("|')[^>]+banshee-php\.org/i },
55
+ 'Backbone.js' => { cats: [ 12 ], script: /backbone.*\.js/, env: /^Backbone$/ },
56
+ 'BIGACE' => { cats: [ 1 ], meta: { 'generator' => /BIGACE/ }, html: /Powered by <a href=("|')[^>]+BIGACE|<!--\s+Site is running BIGACE/i },
57
+ 'BigDump' => { cats: [ 3 ], html: /<!-- <h1>BigDump: Staggered MySQL Dump Importer/ },
58
+ 'Bigware' => { cats: [ 6 ], html: /bigware/i },
59
+ 'blip.tv' => { cats: [ 14 ], html: /<(param|embed)[^>]+blip\.tv\/play/i },
60
+ 'Blogger' => { cats: [ 11 ], meta: { 'generator' => /blogger/i }, url: /^(www.)?.+\.blogspot\.com/i },
61
+ 'Bugzilla' => { cats: [ 13 ], html: /<[^>]+(id|title|name)=("|')bugzilla/i },
62
+ 'Burning Board' => { cats: [ 2 ], html: /<a href=('|")[^>]+woltlab\.com.+Burning Board/i },
63
+ 'Business Catalyst' => { cats: [ 1 ], script: /CatalystScripts/, html: /<!-- BC_OBNW -->/ },
64
+ 'CakePHP' => { cats: [ 18 ], headers: { 'set-cookie' => /cakephp=/ }, meta: { 'application-name' => /CakePHP/ } },
65
+ 'Cargo' => { cats: [ 1 ], script: /\/cargo\./i, html: /<link [^>]+Cargo feed/ },
66
+ 'CentOS' => { cats: [ 28 ], headers: { 'Server' => /CentOS/i, 'X-Powered-By' => /CentOS/i } },
67
+ 'Chameleon' => { cats: [ 1 ], meta: { 'generator' => /chameleon\-cms/i } },
68
+ 'chartbeat' => { cats: [ 10 ], html: /function loadChartbeat\(\) {/i },
69
+ 'Chamilo' => { cats: [ 21 ], meta: { 'generator' => /Chamilo/i }, headers: { 'X-Powered-By' => /Chamilo/ } },
70
+ 'Cherokee' => { cats: [ 22 ], headers: { 'Server' => /Cherokee/i } },
71
+ 'CKEditor' => { cats: [ 24 ], env: /^CKEDITOR$/ },
72
+ 'ClickHeat' => { cats: [ 10 ], script: /clickheat.*\.js/i, env: /^clickHeatBrowser$/ },
73
+ 'ClickTale' => { cats: [ 10 ], html: /if\(typeof ClickTale(Tag)*==("|')function("|')\)/, env: /^ClickTale/i },
74
+ 'Clicky' => { cats: [ 10 ], script: /static\.getclicky\.com/, env: /^clicky$/ },
75
+ 'CMS Made Simple' => { cats: [ 1 ], meta: { 'generator' => /CMS Made Simple/i } },
76
+ 'CO2Stats' => { cats: [ 10 ], html: /src=("|')http:\/\/www\.co2stats\.com\/propres\.php/ },
77
+ 'CodeIgniter' => { cats: [ 18 ], headers: { 'Set-Cookie' => /(exp_last_activity|exp_tracker|ci_session)/ }, implies: [ 'PHP' ] },
78
+ 'Commerce Server' => { cats: [ 6 ], headers: { 'COMMERCE-SERVER-SOFTWARE' => /.+/ } },
79
+ 'comScore' => { cats: [ 10 ], html: /<i{1}frame[^>]* (id=("|')comscore("|')|scr=[^>]+comscore)/, env: /^_?COMSCORE$/i },
80
+ 'Concrete5' => { cats: [ 1 ], meta: { 'generator' => /concrete5/i } },
81
+ 'Contao' => { cats: [ 1, 6 ], html: /(<!--\s+This website is powered by (TYPOlight|Contao)|<link[^>]+(typolight|contao).css)/i, implies: [ 'PHP' ] },
82
+ 'Contens' => { cats: [ 1 ], meta: { 'generator' => /contens/i } },
83
+ 'ConversionLab' => { cats: [ 10 ], script: /conversionlab\.trackset\.com\/track\/tsend\.js/ },
84
+ 'Coppermine' => { cats: [ 7 ], html: /<!--Coppermine Photo Gallery/i, implies: [ 'PHP' ] },
85
+ 'Cosmoshop' => { cats: [ 6 ], script: /cosmoshop_functions\.js/ },
86
+ 'Cotonti' => { cats: [ 1 ], meta: { 'generator' => /Cotonti/i } },
87
+ 'CouchDB' => { cats: [ 22 ], headers: { 'Server' => /CouchDB/i } },
88
+ 'cPanel' => { cats: [ 9 ], html: /<!-- cPanel/i },
89
+ 'Crazy Egg' => { cats: [ 10 ], script: /cetrk\.com\/pages\/scripts\/[0-9]+\/[0-9]+\.js/ },
90
+ 'CS Cart' => { cats: [ 6 ], html: /&nbsp;Powered by (<a href=.http:\/\/www\.cs\-cart\.com|CS\-Cart)/i },
91
+ 'CubeCart' => { cats: [ 6 ], html: /(Powered by <a href=.http:\/\/www\.cubecart\.com|<p[^>]+>Powered by CubeCart)/i },
92
+ 'cufon' => { cats: [ 17 ], script: /cufon\-yui\.js/, env: /^Cufon$/ },
93
+ 'd3' => { cats: [ 25 ], script: /d3(\.min)?\.js/ },
94
+ 'Dancer' => { cats: [ 18 ], headers: { 'X-Powered-By' => /Perl Dancer/, 'Server' => /Perl Dancer/ }, implies: [ 'Perl' ] },
95
+ 'Danneo CMS' => { cats: [ 1 ], meta: { 'generator' => /Danneo/i } },
96
+ 'DataLife Engine' => { cats: [ 1 ], meta: { 'generator' => /DataLife Engine/i } },
97
+ 'David Webbox' => { cats: [ 22 ], headers: { 'Server' => /David-WebBox/i } },
98
+ 'Debian' => { cats: [ 28 ], headers: { 'Server' => /Debian/i, 'X-Powered-By' => /(Debian|dotdeb|etch|lenny|squeeze|wheezy)/i } },
99
+ 'DedeCMS' => { cats: [ 1 ], env: /^Dede/, script: /dedeajax/ },
100
+ 'Demandware' => { cats: [ 6 ], html: /<[^>]+demandware.edgesuite/, env: /^dwAnalytics/ },
101
+ 'DHTMLX' => { cats: [ 12 ], script: /dhtmlxcommon\.js/ },
102
+ 'DirectAdmin' => { cats: [ 9 ], html: /<a[^>]+>DirectAdmin<\/a> Web Control Panel/i },
103
+ 'Disqus' => { cats: [ 15 ], script: /disqus_url/, html: /<div[^>]+id=("|')disqus_thread("|')/, env: /^DISQUS/i },
104
+ 'Django' => { cats: [ 18 ] },
105
+ 'Django CMS' => { cats: [ 1 ], script: /media\/cms\/js\/csrf\.js/, headers: { 'Set-Cookie' => /django/ }, implies: [ 'Django' ] },
106
+ 'dojo' => { cats: [ 12 ], script: /dojo(\.xd)?\.js/, env: /^dojo$/ },
107
+ 'Dokeos' => { cats: [ 21 ], meta: { 'generator' => /Dokeos/i }, html: /Portal <a[^>]+>Dokeos|@import "[^"]+dokeos_blue/i, headers: { 'X-Powered-By' => /Dokeos/ } },
108
+ 'DokuWiki' => { cats: [ 8 ], meta: { 'generator' => /DokuWiki/i } },
109
+ 'DotNetNuke' => { cats: [ 1 ], meta: { 'generator' => /DotNetNuke/i }, html: /(<!\-\- by DotNetNuke Corporation|<link[^>]+\/portals\/_default\/[^>]+\.css)/i, env: /^(DDN|DotNetNuke)/i },
110
+ 'DreamWeaver' => { cats: [ 20 ], html: /(<!\-\-[^>]*(InstanceBeginEditable|Dreamweaver[^>]+target|DWLayoutDefaultTable)|function MM_preloadImages\(\) {)/ },
111
+ 'Drupal' => { cats: [ 1 ], script: /drupal\.js/, html: /(jQuery\.extend\(Drupal\.settings, \{|Drupal\.extend\(\{ settings: \{|<link[^>]+sites\/(default|all)\/themes\/|<style[^>]+sites\/(default|all)\/(themes|modules)\/)/i, headers: { 'X-Drupal-Cache' => /.*/, 'X-Generator' => /Drupal/, 'Expires' => /19 Nov 1978/ }, env: /^Drupal$/, implies: [ 'PHP' ] },
112
+ 'Drupal Commerce' => { cats: [ 6 ], html: /id="block[_-]commerce[_-]cart[_-]cart|class="commerce[_-]product[_-]field/i, implies: [ 'PHP' ] },
113
+ 'Dynamicweb' => { cats: [ 1 ], meta: { 'generator' => /Dynamicweb/i } },
114
+ 'e107' => { cats: [ 1 ], script: /e107\.js/ },
115
+ 'Ecodoo' => { cats: [ 6 ], script: /addons\/lytebox\/lytebox\.js/ },
116
+ 'Exhibit' => { cats: [ 25 ], script: /exhibit.*\.js/, env: /^Exhibit$/ },
117
+ 'ExtJS' => { cats: [ 12 ], script: /ext\-base\.js/, env: /^Ext$/ },
118
+ 'ExpressionEngine' => { cats: [ 1 ], headers: { 'Set-Cookie' => /(exp_last_activity|exp_tracker)/ } },
119
+ 'eZ Publish' => { cats: [ 1 ], meta: { 'generator' => /eZ Publish/i } },
120
+ 'FAST Search for SharePoint' => { cats: [ 29 ], url: /Pages\/SearchResults\.aspx\?k\=/, implies: [ 'Microsoft ASP.NET' ] },
121
+ 'FAST ESP' => { cats: [ 29 ], html: /fastsearch|searchProfile\=|searchCategory\=/i, url: /esppublished|searchProfile\=|searchCategory\=/i },
122
+ 'Fact Finder' => { cats: [ 29 ], html: /\/images\/fact-finder\.gif|ViewParametricSearch|factfinder|Suggest\.ff/i, url: /ViewParametricSearch|factfinder|ffsuggest/i },
123
+ 'FlexCMP' => { cats: [ 1 ], meta: { 'generator' => /FlexCMP/ }, headers: { 'X-Powered-By' => /FlexCMP/ } },
124
+ 'FluxBB' => { cats: [ 2 ], html: /Powered by (<strong>)?<a href=("|')[^>]+fluxbb/i },
125
+ 'Flyspray' => { cats: [ 13 ], html: /(<a[^>]+>Powered by Flyspray|<map id=("|')projectsearchform)/ },
126
+ 'FreeBSD' => { cats: [ 28 ], headers: { 'Server' => /FreeBSD/i } },
127
+ 'FWP' => { cats: [ 6 ], meta: {'generator' => /FWP Shop/ } },
128
+ 'FrontPage' => { cats: [ 20 ], meta: { 'generator' => /Microsoft FrontPage/ }, html: /<html[^>]+urn:schemas\-microsoft\-com:office:office/i },
129
+ 'Gallery' => { cats: [ 7 ], env: /galleryAuthToken/, html: /<div id="gsNavBar" class="gcBorder1">/ },
130
+ 'Gambio' => { cats: [ 6 ], html: /brought to you by XT-Commerce|[Gg]ambio|content\.php\?coID=\d/},
131
+ 'Gauges' => { cats: [ 10 ], html: /t\.src = '\/\/secure\.gaug\.es\/track\.js/, env: /^_gauges$/ },
132
+ 'Gentoo' => { cats: [ 28 ], headers: { 'X-Powered-By' => /-?gentoo/} },
133
+ 'Get Satisfaction' => { cats: [ 13 ], html: /var feedback_widget = new GSFN\.feedback_widget\(feedback_widget_options\)/ },
134
+ 'Google Analytics' => { cats: [ 10 ], script: /(\.google\-analytics\.com\/ga\.js|google-analytics\.com\/urchin\.js)/, env: /^gaGlobal$/ },
135
+ 'Google App Engine' => { cats: [ 22 ], headers: { 'Server' => /Google Frontend/i } },
136
+ 'Google Font API' => { cats: [ 17 ], script: /googleapis.com\/.+webfont/, html: /<link[^>]* href=("|')http:\/\/fonts\.googleapis\.com/, env: /^WebFont/ },
137
+ 'Google Friend Connect' => { cats: [ 5 ], script: /google.com\/friendconnect/ },
138
+ 'Google Maps' => { cats: [ 5 ], script: /(maps\.google\.com\/maps\?file=api|maps\.google\.com\/maps\/api\/staticmap)/ },
139
+ 'Google Sites' => { cats: [ 1 ], url: /sites.google.com/ },
140
+ 'GoStats' => { cats: [ 10 ], env: /^_go(stats|_track)/i },
141
+ 'Graffiti CMS' => { cats: [ 1 ], meta: { 'generator' => /Graffiti CMS/i } },
142
+ 'Gravatar' => { cats: [ 19 ], env: /^Gravatar$/ },
143
+ 'Gravity Insights' => { cats: [ 10 ], html: /gravityInsightsParams\.site_guid = '/, env: /^GravityInsights$/ },
144
+ 'Handlebars' => { cats: [ 12 ], env: /^Handlebars$/ },
145
+ 'Hiawatha' => { cats: [ 22 ], headers: { 'Server' => /Hiawatha/i } },
146
+ 'Highcharts' => { cats: [ 25 ], script: /highcharts.*\.js/, env: /^Highcharts$/ },
147
+ 'Hotaru CMS' => { cats: [ 1 ], meta: { 'generator' => /Hotaru CMS/i } },
148
+ 'Hybris' => { cats: [ 6 ], html: /\/sys_master\/|\/hybr\//, header: { 'Set-Cookie' => /_hybris/ }, implies: [ 'Java' ] },
149
+ 'IIS' => { cats: [ 22 ], headers: { 'Server' => /IIS/i }, implies: [ 'Windows Server' ] },
150
+ 'Indexhibit' => { cats: [ 1 ], html: /<link [^>]+ndxz-studio/i },
151
+ 'InstantCMS' => { cats: [ 1 ], meta: { 'generator' => /InstantCMS/i } },
152
+ 'Intershop' => { cats: [ 6 ], url: /is-bin|INTERSHOP/i, script: /is-bin|INTERSHOP/i },
153
+ 'IPB' => { cats: [ 2 ], script: /jscripts\/ips_/, env: /^IPBoard/, html: /<link[^>]+ipb_[^>]+\.css/ },
154
+ 'iWeb' => { cats: [ 20 ], meta: { 'generator' => /iWeb/i } },
155
+ 'Jalios' => { cats: [ 1 ], meta: { 'generator' => /Jalios/i } },
156
+ 'Java' => { cats: [ 27 ] },
157
+ 'Javascript Infovis Toolkit' => { cats: [ 25 ], script: /jit.*\.js/, env: /^\$jit$/ },
158
+ 'Jo' => { cats: [ 26, 12 ], env: /^jo(Cache|DOM|Event)$/ },
159
+ 'JobberBase' => { cats: [ 19 ], meta: { 'generator' => /Jobberbase/i }, env: /^Jobber$/ },
160
+ 'Joomla' => { cats: [ 1 ], meta: { 'generator' => /Joomla/i }, html: /(<!\-\- JoomlaWorks "K2"|<[^>]+(feed|components)\/com_)/i, headers: { 'X-Content-Encoded-By' => /Joomla/ }, env: /^(jcomments)$/i },
161
+ 'jqPlot' => { cats: [ 25 ], script: /jqplot.*\.js/, env: /^jQuery.jqplot$/ },
162
+ 'jQTouch' => { cats: [ 26 ], script: /jqtouch.*\.js/i, env:/^jQT$/ },
163
+ 'jQuery UI' => { cats: [ 12 ], script: /jquery\-ui.*\.js/, implies: [ 'jQuery' ] },
164
+ 'jQuery' => { cats: [ 12 ], script: /jquery.*.js/, env: /^jQuery$/ },
165
+ 'jQuery Mobile' => { cats: [ 26 ], script: /jquery\.mobile.*\.js/i },
166
+ 'jQuery Sparklines' => { cats: [ 25 ], script: /jquery\.sparkline.*\.js/i },
167
+ 'JS Charts' => { cats: [ 25 ], script: /jscharts.*\.js/i, env: /^JSChart$/ },
168
+ 'JTL Shop' => { cats: [ 6 ], html: /(<input[^>]+name=('|")JTLSHOP|<a href=('|")jtl\.php)/i },
169
+ 'K2' => { cats: [ 19 ], html: /<!\-\- JoomlaWorks "K2"/, env: /^K2RatingURL$/, implies: [ 'Joomla' ] },
170
+ 'Kampyle' => { cats: [ 10 ], script: /cf\.kampyle\.com\/k_button\.js/ },
171
+ 'Kentico CMS' => { cats: [ 1 ], meta: { 'generator' => /Kentico CMS/i } },
172
+ 'Koego' => { cats: [ 10 ], script: /tracking\.koego\.com\/end\/ego\.js/ },
173
+ 'Kohana' => { cats: [ 18 ], headers: { 'Set-Cookie' => /kohanasession/i, 'X-Powered-By' => /Kohana/ }, implies: [ 'PHP' ] },
174
+ 'Kolibri CMS' => { cats: [ 1 ], meta: { 'generator' => /Kolibri/i } },
175
+ 'Koobi' => { cats: [ 1 ], meta: { 'generator' => /Koobi/i } },
176
+ 'lighttpd' => { cats: [ 22 ], headers: { 'Server' => /lighttpd/i } },
177
+ 'LiveJournal' => { cats: [ 11 ], url: /^(www.)?.+\.livejournal\.com/i },
178
+ 'Liferay' => { cats: [ 1 ], env: /^Liferay$/, headers: { 'Liferay-Portal' => /.*/i } },
179
+ 'Lotus Domino' => { cats: [ 22 ], headers: { 'Server' => /Lotus\-Domino/i } },
180
+ 'Magento' => { cats: [ 6 ], script: /\/(js\/mage|skin\/frontend\/(default|enterprise))\//, env: /^(Mage|VarienForm)$/, implies: [ 'PHP '] },
181
+ 'Mambo' => { cats: [ 1 ], meta: { 'generator' => /Mambo/i } },
182
+ 'MantisBT' => { cats: [ 13 ], html: /<img[^>]+ alt=("|')Powered by Mantis Bugtracker/i },
183
+ 'MaxSite CMS' => { cats: [ 1 ], meta: { 'generator' => /MaxSite CMS/i } },
184
+ 'MediaWiki' => { cats: [ 8 ], meta: { 'generator' => /MediaWiki/i }, html: /(<a[^>]+>Powered by MediaWiki<\/a>|<[^>]+id=("|')t\-specialpages)/i },
185
+ 'Meebo' => { cats: [ 5 ], html: /(<iframe id=("|')meebo\-iframe("|')|Meebo\('domReady'\))/ },
186
+ 'Microsoft ASP.NET' => { cats: [ 18 ], html: /<input[^>]+name=("|')__VIEWSTATE/, headers: { 'X-Powered-By' => /ASP\.NET/, 'X-AspNet-Version' => /.+/ }, implies: [ 'Windows Server' ] },
187
+ 'Microsoft SharePoint' => { cats: [ 1 ], meta: { 'generator' => /Microsoft SharePoint/i }, headers: { 'MicrosoftSharePointTeamServices' => /.*/, 'X-SharePointHealthScore' => /.*/, 'SPRequestGuid' => /.*/, 'SharePointHealthScore' => /.*/ } },
188
+ 'MiniBB' => { cats: [ 2 ], html: /<a href=("|')[^>]+minibb.+\s+<!--End of copyright link/i },
189
+ 'Mint' => { cats: [ 10 ], script: /mint\/\?js/, env: /^Mint$/ },
190
+ 'Mixpanel' => { cats: [ 10 ], script: /api\.mixpanel\.com\/track/ },
191
+ 'MochiKit' => { cats: [ 12 ], script: /MochiKit\.js/, env: /^MochiKit$/ },
192
+ 'Modernizr' => { cats: [ 12 ], script: /modernizr.*\.js/, env: /^Modernizr$/ },
193
+ 'MODx' => { cats: [ 1 ], html: /(<a[^>]+>Powered by MODx<\/a>|var el= \$\('modxhost'\);|<script type=("|')text\/javascript("|')>var MODX_MEDIA_PATH = "media";)|<(link|script)[^>]+assets\/snippets\//i },
194
+ 'Mojolicious' => { cats: [ 18 ], headers: { 'x-powered-by' => /mojolicious/ }, implies: [ 'PERL' ] },
195
+ 'Mollom' => { cats: [ 16 ], script: /mollom\.js/, html: /<img[^>]+\/.mollom\/.com/i },
196
+ 'Mondo Media' => { cats: [ 6 ], meta: { 'generator' => /Mondo Shop/ } },
197
+ 'Mongrel' => { cats: [ 22 ], headers: { 'Server' => /Mongrel/ }, implies: [ 'Ruby' ] },
198
+ 'Moodle' => { cats: [ 21 ], html: /(var moodleConfigFn = function\(me\)|<img[^>]+moodlelogo)/i, implies: [ 'PHP' ] },
199
+ 'Moogo' => { cats: [ 1 ], script: /kotisivukone.js/ },
200
+ 'MooTools' => { cats: [ 12 ], script: /mootools.*\.js/, env: /^MooTools$/ },
201
+ 'Movable Type' => { cats: [ 1 ], meta: { 'generator' => /Movable Type/i } },
202
+ 'Mustache' => { cats: [ 12 ], env: /^Mustache$/ },
203
+ 'Hiawatha' => { cats: [ 22 ], headers: { 'Server' => /Hiawatha/i } },
204
+ 'MyBB' => { cats: [ 2 ], html: /(<script [^>]+\s+<!--\s+lang\.no_new_posts|<a[^>]* title=("|')Powered By MyBB)/i, env: /^MyBB/ },
205
+ 'MyBlogLog' => { cats: [ 5 ], script: /pub\.mybloglog\.com/i },
206
+ 'Mynetcap' => { cats: [ 1 ], meta: { 'generator' => /Mynetcap/i } },
207
+ 'Nedstat' => { cats: [ 10 ], html: /sitestat\(("|')http:\/\/nl\.sitestat\.com/ },
208
+ 'Netmonitor' => { cats: [ 10 ], script: /netmonitor\.fi\/nmtracker\.js/, env: /^netmonitor/ },
209
+ 'Nginx' => { cats: [ 22 ], headers: { 'Server' => /nginx/i } },
210
+ 'NOIX' => { cats: [ 19 ], html: /<[^>]+(src|href)=[^>]*(\/media\/noix)|<!\-\- NOIX/i },
211
+ 'nopCommerce' => { cats: [ 6 ], html: /(<!\-\-Powered by nopCommerce|Powered by: <a[^>]+nopcommerce)/i },
212
+ 'OneStat' => { cats: [ 10 ], html: /var p=("|')http("|')\+\(d\.URL\.indexOf\('https:'\)==0\?'s':''\)\+("|'):\/\/stat\.onestat\.com\/stat\.aspx\?tagver/i },
213
+ 'OpenCart' => { cats: [ 6 ], html: /(Powered By <a href=("|')[^>]+OpenCart|route = getURLVar\(("|')route)/i },
214
+ 'openEngine' => { cats: [ 1 ], html: /<meta[^>]+openEngine/i },
215
+ 'OpenGSE' => { cats: [ 22 ], headers: { 'Server' => /GSE/i } },
216
+ 'OpenLayers' => { cats: [ 5 ], script: /openlayers/, env:/^OpenLayers$/ },
217
+ 'OpenNemas' => { cats: [ 1 ], headers: { 'X-Powered-By' => /OpenNemas/ } },
218
+ 'Open Web Analytics' => { cats: [ 10 ], html: /<!-- (Start|End) Open Web Analytics Tracker -->/, env: /^_?owa_/i },
219
+ 'Optimizely' => { cats: [ 10 ], env: /^optimizely/ },
220
+ 'Oracle Recommendations On Demand' => { cats: [ 10 ], script: /atgsvcs.+atgsvcs\.js/ },
221
+ 'osCommerce' => { cats: [ 6 ], html: /<a[^>]*osCsid/i },
222
+ 'osCSS' => { cats: [ 6 ], html: /<body onload=("|')window\.defaultStatus='oscss templates';("|')/i },
223
+ 'OXID eShop' => { cats: [ 6 ], html: /<!--.*OXID eShop/, env: /^ox(TopMenu|ModalPopup|LoginBox|InputValidator)/ },
224
+ 'PANSITE' => { cats: [ 1 ], meta: { 'generator' => /PANSITE/i } },
225
+ 'papaya CMS' => { cats: [ 1 ], html: /<link[^>]*\/papaya-themes\//i },
226
+ 'Parse.ly' => { cats: [ 10 ], env: /^PARSELY$/ },
227
+ 'Perl' => { cats: [ 27 ] },
228
+ 'PHP' => { cats: [ 27 ], headers: { 'Server' => /php/i, 'X-Powered-By' => /php/i, 'Set-Cookie' => /PHPSESSID/ }, url: /\.php$/ },
229
+ 'Phpcms' => { cats: [ 1 ], env: /^phpcms/ },
230
+ 'PHP-Fusion' => { cats: [ 1 ], html: /Powered by <a href=("|')[^>]+php-fusion/i },
231
+ 'PHP-Nuke' => { cats: [ 2 ], meta: { 'generator' => /PHP-Nuke/i }, html: /<[^>]+Powered by PHP\-Nuke/i },
232
+ 'phpBB' => { cats: [ 2 ], meta: { 'copyright' => /phpBB Group/ }, html: /(Powered by <a[^>]+phpbb|<a[^>]+phpbb[^>]+class=.copyright|\tphpBB style name|<[^>]+styles\/(sub|pro)silver\/theme|<img[^>]+i_icon_mini|<table class="forumline)/i, env: /^(style_cookie_settings|phpbb_)/, headers: { 'Set-Cookie' => /^phpbb/ }, implies: [ 'PHP' ] },
233
+ 'phpDocumentor' => { cats: [ 4 ], html: /<!-- Generated by phpDocumentor/, implies: [ 'PHP' ] },
234
+ 'phpMyAdmin' => { cats: [ 3 ], html: /(var pma_absolute_uri = '|PMA_sendHeaderLocation\(|<title>phpMyAdmin<\/title>)/i, implies: [ 'PHP' ] },
235
+ 'phpPgAdmin' => { cats: [ 3 ], html: /(<title>phpPgAdmin<\/title>|<span class=("|')appname("|')>phpPgAdmin)/i },
236
+ 'Piwik' => { cats: [ 10 ], html: /var piwikTracker = Piwik\.getTracker\(/i, env: /^Piwik$/ },
237
+ 'Plentymarkets' => { cats: [ 6 ], meta: { 'generator' => /www\.plentyMarkets\./i } },
238
+ 'Plesk' => { cats: [ 9 ], script: /common\.js\?plesk/i },
239
+ 'Plone' => { cats: [ 1 ], meta: { 'generator' => /Plone/i }, implies: [ 'Python' ] },
240
+ 'Plura' => { cats: [ 19 ], html: /<iframe src="http:\/\/pluraserver\.com/ },
241
+ 'posterous' => { cats: [ 1, 11 ], html: /<div class=("|')posterous/i, env: /^Posterous/i },
242
+ 'Powergap' => { cats: [ 6 ], html: /(s\d\d)\.php\?shopid=\1/ },
243
+ 'Prestashop' => { cats: [ 6 ], meta: { 'generator' => /PrestaShop/i }, html: /Powered by <a href=("|')[^>]+PrestaShop/i },
244
+ 'Prototype' => { cats: [ 12 ], script: /(prototype|protoaculous)\.js/, env: /^Prototype$/ },
245
+ 'Protovis' => { cats: [ 25 ], script: /protovis.*\.js/, env: /^protovis$/ },
246
+ 'punBB' => { cats: [ 2 ], html: /Powered by <a href=("|')[^>]+punbb/i },
247
+ 'Python' => { cats: [ 27 ] },
248
+ 'Quantcast' => { cats: [ 10 ], script: /edge\.quantserve\.com\/quant\.js/, env: /^quantserve$/ },
249
+ 'Quick.Cart' => { cats: [ 6 ], html: /<a href="[^>]+opensolution\.org\/">Powered by/i },
250
+ 'ReallyCMS' => { cats: [ 1 ], meta: { 'generator' => /ReallyCMS/ } },
251
+ 'Red Hat' => { cats: [ 28 ], headers: { 'Server' => /Red Hat/i, 'X-Powered-By' => /Red Hat/i } },
252
+ 'Raphael' => { cats: [ 25 ], script: /raphael.*\.js/, env: /^Raphael$/ },
253
+ 'reCAPTCHA' => { cats: [ 16 ], script: /(api\-secure\.recaptcha\.net|recaptcha_ajax\.js)/, html: /<div[^>]+id=("|')recaptcha_image/, env: /^Recaptcha$/ },
254
+ 'Reddit' => { cats: [ 2 ], html: /(<script[^>]+>var reddit = {|<a[^>]+Powered by Reddit|powered by <a[^>]+>reddit<)/i, url: /^(www\.)?reddit\.com/, env: /^reddit$/, implies: [ 'Python' ] },
255
+ 'Redmine' => { cats: [ 13 ], meta: { 'description' => /Redmine/i }, html: /Powered by <a href=("|')[^>]+Redmine/i, implies: [ 'Ruby' ] },
256
+ 'Reinvigorate' => { cats: [ 10 ], html: /reinvigorate\.track\("/ },
257
+ 'RequireJS' => { cats: [ 12 ], script: /require.*\.js/ , env: /^requirejs$/},
258
+ 'Ruby' => { cats: [ 27 ], headers: { 'Server' => /(Mongrel|WEBrick|Ruby|mod_rails|mod_rack|Phusion.Passenger)/i, 'X-Powered-By' => /(mod_rails|mod_rack|Phusion.Passenger)/i } },
259
+ 'S.Builder' => { cats: [ 1 ], meta: { 'generator' => /S\.Builder/i } },
260
+ 's9y' => { cats: [ 1 ], meta: { 'generator' => /Serendipity/i, 'Powered-By' => /Serendipity/i } },
261
+ 'script.aculo.us' => { cats: [ 12 ], script: /(scriptaculous|protoaculous)\.js/, env: /^Scriptaculous$/ },
262
+ 'Sencha Touch' => { cats: [ 26, 12 ], script: /sencha\-touch.*\.js/ },
263
+ 'Seoshop' => { cats: [ 6 ], html: /http:\/\/www\.getseoshop\.com/ },
264
+ 'ShareThis' => { cats: [ 5 ], script: /w\.sharethis\.com\//, env: /^SHARETHIS$/ },
265
+ 'Shopify' => { cats: [ 6 ], html: /<link[^>]+=cdn\.shopify\.com/, env: /^Shopify$/ },
266
+ 'sIFR' => { cats: [ 17 ], script: /sifr\.js/ },
267
+ 'Site Meter' => { cats: [ 10 ], script: /sitemeter.com\/js\/counter\.js\?site=/ },
268
+ 'SiteCatalyst' => { cats: [ 10 ], html: /var s_code=s\.t\(\);if\(s_code\)document\.write\(s_code\)/i, env: /^s_account$/ },
269
+ 'SiteEdit' => { cats: [ 1 ], meta: { 'generator' => /SiteEdit/i } },
270
+ 'Smartstore' => { cats: [ 6 ], script: /smjslib\.js/ },
271
+ 'SMF' => { cats: [ 2 ], html: /<script [^>]+\s+var smf_/i, env: /^smf_/ },
272
+ 'sNews' => { cats: [ 1 ], meta: { 'generator' => /sNews/ } },
273
+ 'Snoobi' => { cats: [ 10 ], script: /snoobi\.com\/snoop\.php/ },
274
+ 'SOBI 2' => { cats: [ 19 ], html: /(<!\-\- start of Sigsiu Online Business Index|<div[^>]* class=("|')sobi2)/i },
275
+ 'SoundManager' => { cats: [ 12 ], env: /^(SoundManager|BaconPlayer)$/ },
276
+ 'SPIP' => { cats: [ 1 ], meta: { 'generator' => /SPIP/i }, headers: { 'X-Spip-Cache' => /.*/ } },
277
+ 'SQL Buddy' => { cats: [ 3 ], html: /(<title>SQL Buddy<\/title>|<[^>]+onclick=("|')sideMainClick\(("|')home\.php)/i },
278
+ 'Squarespace' => { cats: [ 1 ], html: /Squarespace\.Constants\.CURRENT_MODULE_ID/i },
279
+ 'Squiz Matrix' => { cats: [ 1 ], meta: { 'generator' => /Squiz Matrix/ }, html: / Running (MySource|Squiz) Matrix/i, 'X-Powered-By' => /Squiz Matrix/ },
280
+ 'StatCounter' => { cats: [ 10 ], script: /statcounter\.com\/counter\/counter/ },
281
+ 'Store Systems' => { cats: [ 6 ], html: /Shopsystem von <a href="http:\/\/www\.store-systems\.de"|\.mws_boxTop/ },
282
+ 'SWFObject' => { cats: [ 19 ], script: /swfobject.*\.js/i, env: /^SWFObject$/ },
283
+ 'swift.engine' => { cats: [ 1 ], headers: { 'X-Powered-By' => /swift\.engine/ } },
284
+ 'Swiftlet' => { cats: [ 18 ], meta: { 'generator' => /Swiftlet/i }, html: /Powered by <a href=("|')[^>]+Swiftlet/i, headers: { 'X-Swiftlet-Cache' => /.*/, 'X-Powered-By' => /Swiftlet/, 'X-Generator' => /Swiftlet/ }, implies: [ 'PHP' ] },
285
+ 'Textpattern CMS' => { cats: [ 1 ], meta: { 'generator' => /Textpattern/i } },
286
+ 'Tiki Wiki CMS Groupware' => { cats: [ 1, 2, 8, 11, 13 ], script: /(\/|_)tiki/, meta: { 'generator' => /^Tiki/i } },
287
+ 'Timeplot' => { cats: [ 25 ], script: /timeplot.*\.js/, env: /^Timeplot$/ },
288
+ 'TinyMCE' => { cats: [ 24 ], env: /^tinyMCE$/ },
289
+ 'TomatoCart' => { cats: [ 6 ], meta: { 'generator' => /TomatoCart/i } },
290
+ 'Trac' => { cats: [ 13 ], html: /(<a id=("|')tracpowered)/i, implies: [ 'Python' ] },
291
+ 'Tumblr' => { cats: [ 11 ], html: /<iframe src=("|')http:\/\/www\.tumblr\.com/i, url: /^(www.)?.+\.tumblr\.com/i, headers: { 'X-Tumblr-Usec' => /.*/ } },
292
+ 'Twilight CMS' => { cats: [ 1 ], headers: { 'X-Powered-CMS' => /Twilight CMS/ } },
293
+ 'Twitter Bootstrap' => { cats: [ 18 ], script: /twitter\.github\.com\/bootstrap/, html: /<link[^>]+bootstrap[^>]+css/, env: /^Twipsy$/ },
294
+ 'Typekit' => { cats: [ 17 ], script: /use.typekit.com/, env: /^Typekit$/ },
295
+ 'TypePad' => { cats: [ 11 ], meta: { 'generator' => /typepad/i }, url: /^(www.)?.+\.typepad\.com/i },
296
+ 'TYPO3' => { cats: [ 1 ], headers: { 'Set-Cookie' => /fe_typo_user/ }, meta: { 'generator' => /TYPO3/i }, html: /(<(script[^>]* src|link[^>]* href)=[^>]*fileadmin|<!--TYPO3SEARCH)/i, url: /\/typo3/i },
297
+ 'Ubercart' => { cats: [ 6 ], script: /uc_cart\/uc_cart_block\.js/ },
298
+ 'Ubuntu' => { cats: [ 28 ], headers: { 'Server' => /Ubuntu/i, 'X-Powered-By' => /Ubuntu/i } },
299
+ 'Umbraco' => { cats: [ 1 ], meta: { 'generator' => /umbraco/i }, headers: { 'X-Umbraco-Version' => /.+/ }, html: /powered by <a href=[^>]+umbraco/i, implies: [ 'Microsoft ASP.NET' ] },
300
+ 'Underscore.js' => { cats: [ 12 ], script: /underscore.*\.js/ },
301
+ 'UNIX' => { cats: [ 28 ], headers: { 'Server' => /Unix/i } },
302
+ 'UserRules' => { cats: [ 13 ], html: /var _usrp =/ , env: /^\_usrp$/ },
303
+ 'UserVoice' => { cats: [ 13 ], env: /^UserVoice$/ },
304
+ 'Vanilla' => { cats: [ 2 ], html: /<body id=("|')(DiscussionsPage|vanilla)/i, headers: { 'X-Powered-By' => /Vanilla/ } },
305
+ 'Varnish' => { cats: [ 22 ], headers: { 'X-Varnish' => /.+/, 'X-Varnish-Age' => /.+/, 'X-Varnish-Cache' => /.+/, 'X-Varnish-Action' => /.+/, 'X-Varnish-Hostname' => /.+/, 'Via' => /Varnish/i } },
306
+ 'vBulletin' => { cats: [ 2 ], meta: { 'generator' => /vBulletin/i }, env: /^(vBulletin|vB_)/ },
307
+ 'viennaCMS' => { cats: [ 1 ], html: /powered by <a href=("|')[^>]+viennacms/i },
308
+ 'Vignette' => { cats: [ 1 ], html: /<[^>]+?=("|')(vgn\-ext|vgnext)/i },
309
+ 'Vimeo' => { cats: [ 14 ], html: /<(param|embed)[^>]+vimeo\.com\/moogaloop/i },
310
+ 'VirtueMart' => { cats: [ 6 ], html: /<div id=("|')vmMainPage/, headers: { 'Set-Cookie' => /^virtuemart\=/ } },
311
+ 'VisualPath' => { cats: [ 10 ], script: /visualpath[^\/]*\.trackset\.it\/[^\/]+\/track\/include\.js/ },
312
+ 'VIVVO' => { cats: [ 1 ], headers: { 'Set-Cookie' => /VivvoSessionId/, env: /^vivvo/i } },
313
+ 'Vox' => { cats: [ 11 ], url: /^(www.)?.+\.vox\.com/i },
314
+ 'VP-ASP' => { cats: [ 6 ], script: /vs350\.js/, html: /<a[^>]+>Powered By VP\-ASP Shopping Cart<\/a>/, implies: [ 'Microsoft ASP.NET' ] },
315
+ 'W3Counter' => { cats: [ 10 ], script: /w3counter\.com\/tracker\.js/ },
316
+ 'Web Optimizer' => { cats: [ 10 ], html: /<title [^>]*lang=("|')wo("|')>/ },
317
+ 'Websale' => { cats: [ 6 ], url: /\/websale7\// },
318
+ 'webEdition' => { cats: [ 1 ], meta: { 'generator' => /webEdition/i, 'DC.title' => /webEdition/i } },
319
+ 'WebGUI' => { cats: [ 1 ], meta: { 'generator' => /WebGUI/i } },
320
+ 'WebPublisher' => { cats: [ 1 ], meta: { 'generator' => /WEB\|Publisher/i } },
321
+ 'WebsiteBaker' => { cats: [ 1 ], meta: { 'generator' => /WebsiteBaker/i } },
322
+ 'Webtrekk' => { cats: [ 10 ], html: /var webtrekk = new Object/ },
323
+ 'Webtrends' => { cats: [ 10 ], html: /<img[^>]+id=("|')DCSIMG("|')[^>]+webtrends/i, env: /^(WTOptimize|WebTrends)/i },
324
+ 'Weebly' => { cats: [ 1 ], html: /<[^>]+class=("|')weebly/i },
325
+ 'WikkaWiki' => { cats: [ 8 ], meta: { 'generator' => /WikkaWiki/ }, html: /Powered by <a href=("|')[^>]+WikkaWiki/i },
326
+ 'Windows Server' => { cats: [ 28 ] },
327
+ 'wink' => { cats: [ 26, 12 ], script: /(\_base\/js\/base|wink).*\.js/i, env: /^wink$/ },
328
+ 'Wolf CMS' => { cats: [ 1 ], html: /<a href=("|')[^>]+wolfcms.org.+Wolf CMS.+inside/i },
329
+ 'Woopra' => { cats: [ 10 ], script: /static\.woopra\.com/ },
330
+ 'WordPress' => { cats: [ 1, 11 ], meta: { 'generator' => /WordPress/i }, html: /<link rel=("|')stylesheet("|') [^>]+wp-content/i, env: /^wp_username$/, implies: [ 'PHP' ] },
331
+ 'xajax' => { cats: [ 12 ], script: /xajax_core.*\.js/i },
332
+ 'Xanario' => { cats: [ 6 ], meta: { 'generator' => /xanario shopsoftware/i } },
333
+ 'XenForo' => { cats: [ 2 ], html: /(jQuery\.extend\(true, XenForo|Forum software by XenForo&trade;|<!\-\-XF:branding)/ },
334
+ 'XiTi' => { cats: [ 10 ], html: /<[^>]+src=("|')[^>]+xiti.com\/hit.xiti/i, env: /^Xt_/ },
335
+ 'XMB' => { cats: [ 2 ], html: /<!-- Powered by XMB/i },
336
+ 'xui' => { cats: [ 26, 12 ], script: /[^a-zA-Z]xui.*\.js/i, env: /^xui$/ },
337
+ 'XOOPS' => { cats: [ 1 ], meta: { 'generator' => /XOOPS/i } },
338
+ 'xtCommerce' => { cats: [ 6 ], meta: { 'generator' => /xt:Commerce/ }, html: /<div class=("|')copyright("|')>.+<a[^>]+>xt:Commerce/i },
339
+ 'YaBB' => { cats: [ 2 ], html: /Powered by <a href=("|')[^>]+yabbforum/i },
340
+ 'Yahoo! Web Analytics' => { cats: [ 10 ], script: /d\.yimg\.com\/mi\/ywa\.js/ },
341
+ 'Yandex.Metrika' => { cats: [ 10 ], script: /mc\.yandex\.ru\/metrika\/watch\.js/ },
342
+ 'YouTube' => { cats: [ 14 ], html: /<(param|embed|iframe)[^>]+youtube(-nocookie)?\.com\/(v|embed)/i },
343
+ 'YUI Doc' => { cats: [ 4 ], html: /<html[^>]* yuilibrary\.com\/rdf\/[0-9.]+\/yui\.rdf/i },
344
+ 'YUI' => { cats: [ 12 ], script: /\/yui\/|yui\.yahooapis\.com/, env: /^YAHOO$/ },
345
+ 'Zen Cart' => { cats: [ 6 ], meta: { 'generator' => /Zen Cart/i } },
346
+ 'Zend' => { cats: [ 22 ], headers: { 'X-Powered-By' => /Zend/ } },
347
+ 'Zepto' => { cats: [ 12 ], script: /zepto.*.js/, env: /^Zepto$/ }
348
+ }
349
+ end
@@ -0,0 +1,3 @@
1
+ module WappalyzerRb
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,97 @@
1
+ require "wappalyzer_rb/version"
2
+ require "wappalyzer_rb/apps"
3
+
4
+ module WappalyzerRb
5
+ class Some
6
+ attr_reader :analysis
7
+
8
+ def initialize(url)
9
+ @url = url
10
+ analyze!
11
+ end
12
+
13
+ private
14
+
15
+ def hostname
16
+ @hostname ||= URI.parse(@url).host
17
+ end
18
+
19
+ def data
20
+ response.body
21
+ end
22
+
23
+ def url
24
+ @url
25
+ end
26
+
27
+ def scripts
28
+ @scripts ||= begin
29
+ data.scan(/<script[^>]+src=("|')([^"']+)\1/i).transpose[1] || []
30
+ end
31
+ end
32
+
33
+ def metas
34
+ @metas ||= begin
35
+ data.scan(/<meta[^>]+>/i).flatten.reduce(Hash.new) do |hash, line|
36
+ name = line[/name=("|')([^"']+)\1/, 2]
37
+ content = line[/content=("|')([^"']+)\1/, 2]
38
+
39
+ hash[name] = content
40
+ hash
41
+ end
42
+ end
43
+ end
44
+
45
+ def headers
46
+ response
47
+ end
48
+
49
+ def response
50
+ @response ||= begin
51
+ uri = URI.parse(@url)
52
+ http = Net::HTTP.new(uri.host, uri.port)
53
+ request = Net::HTTP::Get.new(uri.request_uri)
54
+ http.request(request)
55
+ end
56
+ end
57
+
58
+ def analyze!
59
+ @analysis ||= begin
60
+ matched_apps = []
61
+
62
+ APPS.each do |app, tells|
63
+ tells.each do |type, matcher|
64
+ next if type == :cats
65
+
66
+ case type
67
+ when :url
68
+ matched_apps << app if url =~ matcher
69
+ when :html
70
+ matched_apps << app if data =~ matcher
71
+ when :script
72
+ if scripts.any?{|script| script =~ matcher}
73
+ matched_apps << app
74
+ end
75
+ when :meta
76
+ matcher.each do |name, content_rx|
77
+ if metas[name] =~ content_rx
78
+ matched_apps << app
79
+ end
80
+ end
81
+ when :headers
82
+ matcher.each do |type, content_rx|
83
+ if headers[type.downcase] =~ content_rx
84
+ matched_apps << app
85
+ end
86
+ end
87
+ when :env
88
+ # Not way to peer into the page's DOM yet
89
+ end
90
+ end
91
+ end
92
+
93
+ matched_apps.uniq
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe WappalyzerRb::Some do
4
+ let(:mock_response) do
5
+ mock(:response, body: "nobody", :[] => nil)
6
+ end
7
+
8
+ it "should initialize" do
9
+ WappalyzerRb::Some.any_instance.stub(:response).and_return(mock_response)
10
+ WappalyzerRb::Some.new('http://someurl.com')
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require 'wappalyzer_rb'
8
+
9
+ RSpec.configure do |config|
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "wappalyzer_rb/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "wappalyzer_rb"
7
+ s.version = WappalyzerRb::VERSION
8
+ s.authors = ["Kostas Karachalios"]
9
+ s.email = ["kostas.karachalios@me.com"]
10
+ s.homepage = "https://github.com/vrinek/wappalyzer-ruby"
11
+ s.summary = %q{Analyzes a provided url and returns any services it can detect}
12
+ s.description = %q{This is merely a port of the javascript parts of Wappalyzer extension for Firefox and Chrome}
13
+
14
+ s.rubyforge_project = "wappalyzer_rb"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ s.add_development_dependency "guard"
24
+ s.add_development_dependency "guard-rspec"
25
+ # s.add_runtime_dependency "rest-client"
26
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wappalyzer_rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kostas Karachalios
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: guard
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard-rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: This is merely a port of the javascript parts of Wappalyzer extension
63
+ for Firefox and Chrome
64
+ email:
65
+ - kostas.karachalios@me.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - .gitignore
71
+ - .rspec
72
+ - Gemfile
73
+ - Guardfile
74
+ - README.md
75
+ - Rakefile
76
+ - lib/wappalyzer_rb.rb
77
+ - lib/wappalyzer_rb/apps.rb
78
+ - lib/wappalyzer_rb/version.rb
79
+ - spec/lib/wappalyzer_rb_spec.rb
80
+ - spec/spec_helper.rb
81
+ - wappalyzer_rb.gemspec
82
+ homepage: https://github.com/vrinek/wappalyzer-ruby
83
+ licenses: []
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project: wappalyzer_rb
102
+ rubygems_version: 1.8.24
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Analyzes a provided url and returns any services it can detect
106
+ test_files: []
107
+ has_rdoc: