Merge pull request #2 from AliasIO/master

Update
main
DaAwesomeP 9 years ago
commit 8db2ee624b

@ -10,9 +10,8 @@ install:
- sudo apt-get update -y
- sudo apt-get install -y curl zip sudo -y --force-yes
- sudo apt-get clean
- npm install jsonlint -g
- npm install jsonlint jpm -g
- ln -s docker/node/package.json package.json && npm install
- mkdir mozilla && curl -L https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/jetpack-sdk-latest.tar.gz | tar xvzC mozilla && ln -s $WAPPALYZER_ROOT/mozilla/addon-sdk-*/bin/cfx bin/cfx
- mkdir phantomjs && curl -L https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.8-linux-x86_64.tar.bz2 | tar xvjC phantomjs && ln -s $WAPPALYZER_ROOT/phantomjs/phantomjs-*-linux-x86_64/bin/phantomjs bin/phantomjs
script: wappalyzer build
after_script: ls build

@ -17,10 +17,18 @@ jsonlint -ist $'\t' $WAPPALYZER_ROOT/src/apps.json
wappalyzer links
# Npm Module
mkdir -p $WAPPALYZER_ROOT/build/wappalyzer_npm/
cp -R $WAPPALYZER_ROOT/src/drivers/npm/* $WAPPALYZER_ROOT/build/wappalyzer_npm/
# Mozilla Firefox
echo "Building Firefox driver..."
cfx xpi --pkgdir=$WAPPALYZER_ROOT/src/drivers/firefox --output-file=$WAPPALYZER_ROOT/build/wappalyzer_firefox.xpi
pushd $WAPPALYZER_ROOT/src/drivers/firefox > /dev/null
jpm xpi && mv *.xpi $WAPPALYZER_ROOT/build/wappalyzer_firefox.xpi
popd > /dev/null
# Google Chrome
echo "Building Chrome driver..."

@ -33,14 +33,7 @@ RUN su wappalyzer -c "mkdir $WAPPALYZER_NODE_PATH"
ADD node/package.json $WAPPALYZER_NODE_PATH/package.json
RUN npm install jsonlint -g && su wappalyzer -c "cd $WAPPALYZER_NODE_PATH && npm install"
# Mozilla Add-on SDK
RUN su wappalyzer -c "\
mkdir mozilla && \
curl -L https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/jetpack-sdk-latest.tar.gz | tar xvzC mozilla && \
ln -s /home/wappalyzer/mozilla/addon-sdk-*/bin/cfx bin/cfx"
RUN npm install jsonlint jpm -g && su wappalyzer -c "cd $WAPPALYZER_NODE_PATH && npm install"
# PhantomJS

@ -262,6 +262,19 @@
"script": "adzerk\\.net/ados\\.js",
"website": "adzerk.com"
},
"Aegea": {
"cats": [
11
],
"headers": {
"X-Powered-By": "^E2 Aegea v(\\d+)$\\;version:\\1"
},
"implies": [
"PHP",
"jQuery"
],
"website": "blogengine.ru"
},
"Airee": {
"cats": [
31
@ -431,6 +444,19 @@
"script": "adnxs\\.(?:net|com)",
"website": "appnexus.com"
},
"Arastta": {
"cats": [
6
],
"excludes": "OpenCart",
"headers": {
"Arastta": "([0-9.]+)\\;version:\\1"
},
"html": "Powered By <a href=\"[^>]+Arastta",
"implies": "PHP",
"script": "arastta\\.js",
"website": "arastta.org"
},
"Arc Forum": {
"cats": [
2
@ -507,7 +533,7 @@
"Set-cookie": "FESESSIONID"
},
"html": "<title>(?:Log in to )?FishEye (?:and Crucible )?([\\d.]+)?</title>\\;version:\\1",
"website": "www.atlassian.com/software/fisheyet/overview/"
"website": "www.atlassian.com/software/fisheye/overview/"
},
"Atlassian Jira": {
"cats": [
@ -1240,7 +1266,8 @@
1
],
"headers": {
"Set-Cookie": "CraftSessionId="
"Set-Cookie": "CraftSessionId=",
"X-Powered-By": "Craft CMS"
},
"implies": "PHP",
"website": "buildwithcraft.com"
@ -1303,6 +1330,39 @@
"script": "dhtmlxcommon\\.js",
"website": "dhtmlx.com"
},
"DM Polopoly": {
"cats": [
1
],
"html": "<(?:link [^>]*href|img [^>]*src)=\"/polopoly_fs/",
"implies": "Java",
"website": "www.atex.com/products/dm-polopoly"
},
"DNN": {
"cats": [
1
],
"env": "^DotNetNuke$",
"headers": {
"Cookie": "dnn_IsMobile=",
"DNNOutputCache": "",
"Set-Cookie": "DotNetNukeAnonymous=",
"X-Compressed-By": "DotNetNuke"
},
"html": [
"<!-- by DotNetNuke Corporation",
"<!-- DNN Platform"
],
"implies": "Microsoft ASP.NET",
"meta": {
"generator": "DotNetNuke"
},
"script": [
"/js/dnncore\\.js",
"/js/dnn\\.js"
],
"website": "dnnsoftware.com"
},
"DTG": {
"cats": [
1
@ -1364,6 +1424,14 @@
},
"website": "dle-news.ru"
},
"DataTables": {
"cats": [
12
],
"implies": "jQuery",
"script": "dataTables.*\\.js",
"website": "datatables.net"
},
"David Webbox": {
"cats": [
22
@ -1453,6 +1521,20 @@
},
"website": "discourse.org"
},
"Discuz! X": {
"cats": [
2
],
"env": [
"^discuz_uid$",
"^DISCUZCODE$"
],
"implies": "PHP",
"meta": {
"generator": "Discuz! X([\\d\\.]+)?\\;version:\\1"
},
"website": "discuz.com"
},
"Disqus": {
"cats": [
15
@ -1518,24 +1600,6 @@
},
"website": "www.dokuwiki.org"
},
"DotNetNuke": {
"cats": [
1
],
"env": "^DotNetNuke$",
"headers": {
"DNNOutputCache": "",
"Set-Cookie": "DotNetNukeAnonymous=",
"X-Compressed-By": "DotNetNuke"
},
"html": "<!-- by DotNetNuke Corporation",
"implies": "Microsoft ASP.NET",
"meta": {
"generator": "DotNetNuke"
},
"script": "/js/dnncore\\.js",
"website": "dotnetnuke.com"
},
"Dotclear": {
"cats": [
1
@ -1543,6 +1607,38 @@
"implies": "PHP",
"website": "dotclear.org"
},
"DoubleClick Ad Exchange (AdX)": {
"cats": [
36
],
"script": [
"googlesyndication\\.com/pagead/show_ads\\.js",
"tpc\\.googlesyndication\\.com/safeframe",
"googlesyndication\\.com.*abg\\.js"
],
"website": "www.doubleclickbygoogle.com/solutions/digital-marketing/ad-exchange/"
},
"DoubleClick Campaign Manager (DCM)": {
"cats": [
36
],
"script": "2mdn\\.net",
"website": "www.doubleclickbygoogle.com/solutions/digital-marketing/campaign-manager/"
},
"DoubleClick Floodlight": {
"cats": [
36
],
"script": "https?://fls.doubleclick.net",
"website": "support.google.com/ds/answer/6029713?hl=en"
},
"DoubleClick for Publishers (DFP)": {
"cats": [
36
],
"script": "googletagservices\\.com/tag/js/gpt(_mobile|)\\.js",
"website": "www.google.com/dfp"
},
"Doxygen": {
"cats": [
4
@ -1551,7 +1647,7 @@
"meta": {
"generator": "Doxygen ([\\d.]+)\\;version:\\1"
},
"website": "stack.nl/~dimitri/doxygen"
"website": "www.stack.nl/~dimitri/doxygen/"
},
"DreamWeaver": {
"cats": [
@ -1582,7 +1678,7 @@
"cats": [
6
],
"html": "<[^]+(?:id=\"block[_-]commerce[_-]cart[_-]cart|class=\"commerce[_-]product[_-]field)",
"html": "<[^>]+(?:id=\"block[_-]commerce[_-]cart[_-]cart|class=\"commerce[_-]product[_-]field)",
"implies": "Drupal",
"website": "drupalcommerce.org"
},
@ -1678,6 +1774,19 @@
"url": "https?://(?:[^/]+\\.)?edgecastcdn\\.net/",
"website": "www.edgecast.com"
},
"Elcodi": {
"cats": [
6
],
"headers": {
"X-Elcodi": ""
},
"implies": [
"PHP",
"Symfony"
],
"website": "elcodi.io"
},
"Eleanor CMS": {
"cats": [
1
@ -1736,7 +1845,7 @@
26
],
"env": "^enyo$",
"script": "enyo\\.js",
"script": "\benyo\\.js",
"website": "enyojs.com"
},
"Epoch": {
@ -1858,6 +1967,13 @@
},
"website": "fedoraproject.org"
},
"Firebase": {
"cats": [
34
],
"script": "firebase.*\\.js",
"website": "firebase.com"
},
"Fireblade": {
"cats": [
31
@ -2138,7 +2254,8 @@
"script": [
"googlesyndication\\.com/",
"ad\\.ca\\.doubleclick\\.net",
"2mdn\\.net"
"2mdn\\.net",
"ad\\.ca\\.doubleclick\\.net"
],
"website": "google.com/adsense"
},
@ -2231,6 +2348,15 @@
],
"website": "wallet.google.com"
},
"Google Web Server": {
"cats": [
22
],
"headers": {
"Server": "gws"
},
"website": "en.wikipedia.org/wiki/Google_Web_Server"
},
"Google Web Toolkit": {
"cats": [
18
@ -2273,7 +2399,7 @@
"PHP"
],
"meta": {
"generator": "Grav(?:\\s([\\d.]+))?\\;version:\\1"
"generator": "GravCMS(?:\\s([\\d.]+))?\\;version:\\1"
},
"website": "getgrav.org"
},
@ -2282,7 +2408,7 @@
19
],
"env": "^Gravatar$",
"html": "<[^]+gravatar\\.com/avatar/",
"html": "<[^>]+gravatar\\.com/avatar/",
"website": "gravatar.com"
},
"Gravity Insights": {
@ -2309,6 +2435,16 @@
"script": "https?://js\\.cit\\.api\\.here\\.com/se/([\\d.]+)\\/\\;version:\\1",
"website": "developer.here.com"
},
"HHVM": {
"cats": [
22
],
"headers": {
"X-Powered-By": "HHVM/?([\\d.]+)?\\;version:\\1"
},
"implies": "PHP\\;confidence:50",
"website": "hhvm.com"
},
"HP": {
"cats": [
40
@ -2361,6 +2497,16 @@
},
"website": "hp.com"
},
"HTTP Kit": {
"cats": [
22
],
"headers": {
"Server": "^http-kit"
},
"implies": "Java",
"website": "http-kit.org"
},
"HTTP-Server": {
"cats": [
22
@ -2412,6 +2558,14 @@
"script": "head\\.(?:core|load)(?:\\.min)?\\.js",
"website": "headjs.com"
},
"Heap": {
"cats": [
10
],
"env": "^heap$",
"script": "heap-\\d+.js",
"website": "heapanalytics.com"
},
"Hello Bar": {
"cats": [
5
@ -2491,7 +2645,7 @@
"headers": {
"Set-Cookie": "_hybris"
},
"html": "<[^]+(?:/sys_master/|/hybr/|/_ui/desktop/)",
"html": "<[^>]+(?:/sys_master/|/hybr/|/_ui/desktop/)",
"implies": "Java",
"website": "hybris.com"
},
@ -3027,9 +3181,9 @@
"MySQL"
],
"meta": {
"generator": "Koken ([\\d.]+);version:\\1"
"generator": "Koken ([\\d.]+)\\;version:\\1"
},
"script": "koken(?:\\.js\\?([\\d.]+)|/storage);version:\\1",
"script": "koken(?:\\.js\\?([\\d.]+)|/storage)\\;version:\\1",
"website": "koken.me"
},
"Kolibri CMS": {
@ -3075,6 +3229,13 @@
"script": "/Kooboo",
"website": "kooboo.com"
},
"Kotisivukone": {
"cats": [
1
],
"script": "kotisivukone(?:\\.min)?\\.js",
"website": "www.kotisivukone.fi"
},
"LEPTON": {
"cats": [
1
@ -3243,6 +3404,19 @@
"script": "livefyre_init\\.js",
"website": "livefyre.com"
},
"Liveinternet": {
"cats": [
10
],
"html": [
"<script[^<>]*>[^]{0,128}?src\\s*=\\s*['\"]//counter\\.yadro\\.ru/hit(?:;\\S+)?\\?(?:t\\d+\\.\\d+;)?r",
"<!--LiveInternet counter-->",
"<!--/LiveInternet-->",
"<a href=\"http://www.liveinternet.ru/click\""
],
"script": "/js/al/common.js\\?[0-9_]+",
"website": "liveinternet.ru/rating/"
},
"Lo-dash": {
"cats": [
12
@ -3350,6 +3524,14 @@
"implies": "PHP",
"website": "modxcms.com"
},
"MadAdsMedia": {
"cats": [
36
],
"env": "^setM(?:Iframe|RefURL)$",
"script": "^https?://(?:ads-by|pixel)\\.madadsmedia.com/",
"website": "madadsmedia.com"
},
"Magento": {
"cats": [
6
@ -3397,6 +3579,15 @@
"script": "munchkin\\.marketo\\.net/munchkin\\.js",
"website": "www.marketo.com"
},
"Materialize CSS": {
"cats": [
18
],
"html": "<link[^>]* href=\"[^\"]*materialize(?:\\.min)?\\.css",
"implies": "jQuery",
"script": "materialize(?:\\.min)?\\.js",
"website": "materializecss.com"
},
"MathJax": {
"cats": [
25
@ -3713,13 +3904,6 @@
"implies": "PHP",
"website": "moodle.org"
},
"Moogo": {
"cats": [
1
],
"script": "kotisivukone(?:\\.min)?\\.js",
"website": "www.moogo.com"
},
"Motion-httpd": {
"cats": [
22
@ -3921,12 +4105,37 @@
"implies": "Laravel",
"website": "octobercms.com"
},
"Odoo": {
"cats": [
1,
6
],
"html": "<link[^>]* href=[^>]+/web/css/(?:web\\.assets_common/|website\\.assets_frontend/)\\;confidence:25",
"implies": [
"Python",
"PostgreSQL",
"node.js",
"Less"
],
"meta": {
"generator": "Odoo"
},
"script": "/web/js/(?:web\\.assets_common/|website\\.assets_frontend/)\\;confidence:25",
"website": "odoo.com"
},
"OmniTouch 8660 My Teamwork": {
"cats": [
19
],
"website": "enterprise.alcatel-lucent.com"
},
"OneAPM": {
"cats": [
10
],
"env": "^BWEUM",
"website": "www.oneapm.com"
},
"OneStat": {
"cats": [
10
@ -4047,6 +4256,19 @@
},
"website": "www.opennemas.com"
},
"OpenResty": {
"cats": [
22
],
"headers": {
"Server": "openresty(?:/([\\d.]+))?\\;version:\\1"
},
"implies": [
"Nginx",
"Lua"
],
"website": "openresty.org"
},
"OpenSSL": {
"cats": [
33
@ -4064,6 +4286,16 @@
"implies": "Microsoft ASP.NET",
"website": "websolutions.opentext.com"
},
"OpenX": {
"cats": [
36
],
"script": [
"https?://[^/]*\\.openx\\.net",
"https?://[^/]*\\.servedbyopenx\\.com"
],
"website": "openx.com"
},
"Ophal": {
"cats": [
1,
@ -4141,6 +4373,19 @@
},
"website": "orchardproject.net"
},
"osTicket": {
"cats": [
13
],
"implies": [
"PHP",
"MySQL"
],
"headers": {
"Set-Cookie": "OSTSESSID"
},
"website": "osticket.com"
},
"Outbrain": {
"cats": [
5
@ -4257,6 +4502,15 @@
},
"website": "pencilblue.org"
},
"Penguin": {
"cats": [
18
],
"env": "^penguin$",
"html": "<link[^>]+?href=\"[^\"]+penguin(?:\\.min)?\\.css",
"script": "penguin(?:\\.min)?\\.js",
"website": "penguin.docs.bqws.io"
},
"Percussion": {
"cats": [
1
@ -4369,7 +4623,7 @@
"X-Powered-By-Plesk": "Plesk"
},
"script": "common\\.js\\?plesk",
"website": "parallels.com/products/plesk"
"website": "plesk.com"
},
"Pligg": {
"cats": [
@ -4448,7 +4702,7 @@
"script": "prefixfree\\.js",
"website": "leaverou.github.io/prefixfree/"
},
"Prestashop": {
"PrestaShop": {
"cats": [
6
],
@ -4484,6 +4738,13 @@
"script": "protovis.*\\.js",
"website": "mbostock.github.com/protovis"
},
"PubMatic": {
"cats": [
36
],
"script": "https?://[^/]*\\.pubmatic\\.com",
"website": "www.pubmatic.com/"
},
"Pure CSS": {
"cats": [
18
@ -4544,6 +4805,22 @@
},
"website": "???"
},
"RainLoop": {
"cats": [
30
],
"env": "^rainloop",
"headers": {
"Server": "RainLoop"
},
"html": [
"<meta [^>]*(?:content=\"([^\"]+)[^>]+ id=\"rlAppVersion\"|id=\"rlAppVersion\"[^>]+ content=\"([^\"]+))\\;version:\\1?\\1:\\2",
"<link[^>]* href=\"[^\"]*rainloop/v/([^/]+)\\;version:\\1"
],
"implies": "PHP",
"script": "rainloop/v/([^/]+))\\;version:\\1",
"website": "rainloop.net"
},
"RBS Change": {
"cats": [
1,
@ -4668,6 +4945,16 @@
"script": "require.*\\.js",
"website": "requirejs.org"
},
"Resin": {
"cats": [
22
],
"headers": {
"Server": "^Resin(?:/(\\S*))?;version=\\1"
},
"implies": "Java",
"website": "caucho.com"
},
"Reveal.js": {
"cats": [
12
@ -4714,6 +5001,17 @@
},
"website": "ritecms.com"
},
"Roadiz CMS": {
"cats": [
1,
11
],
"implies": "PHP",
"meta": {
"generator": "^Roadiz ([a-z0-9\\s\\.]+) - \\;version:\\1"
},
"website": "www.roadiz.io"
},
"RoundCube": {
"cats": [
30
@ -4723,6 +5021,13 @@
"implies": "PHP",
"website": "roundcube.net"
},
"Rubicon Project": {
"cats": [
36
],
"script": "https?://[^/]*\\.rubiconproject\\.com",
"website": "rubiconproject.com/"
},
"Ruby": {
"cats": [
27
@ -4911,6 +5216,25 @@
},
"website": "scientificlinux.org"
},
"Select2": {
"cats": [
12
],
"implies": "jQuery",
"script": "select2.*\\.js",
"website": "select2.github.io"
},
"Semantic-ui": {
"cats": [
18
],
"html": [
"(?:<div class=\"ui\\s[^>]+\">)\\;confidence:30",
"(?:<link[^>]+semantic(?:\\.css|\\.min\\.css)\">)"
],
"script": "(?:semantic(?:\\.js|\\.min\\.js))",
"website": "semantic-ui.com"
},
"Sencha Touch": {
"cats": [
12,
@ -5025,11 +5349,15 @@
"cats": [
6
],
"implies": "PHP",
"implies": [
"PHP",
"MySQL",
"jQuery"
],
"meta": {
"application-name": "Shopware"
},
"script": "shopware\\.js",
"script": "(?:(shopware)|/web/cache/[0-9]{10}_.+)\\.js\\;version:\\1?4:5",
"website": "shopware.com"
},
"Silva": {
@ -5303,6 +5631,21 @@
},
"website": "squiz.net"
},
"Stackla": {
"cats": [
5
],
"env": "^Stackla$",
"script": "assetscdn\\.stackla\\.com\\/media\\/js\\/widget\\/(?:[a-zA-Z0-9.]+)?\\.js",
"website": "stackla.com/"
},
"Stackla Social Hub": {
"cats": [
1
],
"env": "^stacklaSocialHub$",
"website": "stackla.com/"
},
"Starlet": {
"cats": [
22
@ -5468,7 +5811,18 @@
"TYPO3 Flow"
],
"url": "/neos/",
"website": "neos.typo3.org"
"website": "neos.io"
},
"Taiga": {
"cats": [
13
],
"env": "^taigaConfig$",
"implies": [
"Django",
"AngularJS"
],
"website": "taiga.io"
},
"Tealeaf": {
"cats": [
@ -5786,8 +6140,8 @@
},
"Unbounce": {
"cats": [
1,
20
20,
51
],
"headers": {
"X-Unbounce-PageId": ""
@ -5989,7 +6343,7 @@
"script": [
"vue(?:\\-|\\.)([\\d.]*\\d)[^/]*\\.js\\;version:\\1",
"/([\\d.]+)/vue(\\.min)?\\.js\\;version:\\1",
"vue.*\\.js;\\confidence:20"
"vue.*\\.js\\;confidence:20"
],
"website": "vuejs.org"
},
@ -6022,6 +6376,16 @@
"implies": "WordPress",
"website": "wp-rocket.me"
},
"Warp": {
"cats": [
22
],
"headers": {
"Server": "^Warp/(\\d+(?:\\.\\d+)+)?$;version:\\1"
},
"implies": "Haskell",
"website": "www.stackage.org/package/warp"
},
"Web Optimizer": {
"cats": [
10
@ -6136,6 +6500,16 @@
"script": "cdn\\d+\\.editmysite\\.com",
"website": "www.weebly.com"
},
"Wikispaces": {
"cats": [
8
],
"html": [
"<script[^>]*>[^<]*session_url:\\s*'https://session\\.wikispaces\\.com/",
"<\\w+[^>]*\\s+class=\"[^\"]*WikispacesContent\\s+WikispacesBs3[^\"]*\""
],
"website": "www.wikispaces.com"
},
"WikkaWiki": {
"cats": [
8
@ -6428,16 +6802,17 @@
"script": "mc\\.yandex\\.ru\\/metrika\\/watch\\.js",
"website": "metrika.yandex.com"
},
"Yesod": {
"Yaws": {
"cats": [
18,
22
],
"headers": {
"Server": "Warp/\\d+(\\.\\d+)+"
"Server": "Yaws(?: ([\\d.]+))?\\;version:\\1"
},
"implies": "Haskell",
"website": "www.yesodweb.com"
"implies": [
"Erlang"
],
"website": "yaws.hyber.org"
},
"Yieldlab": {
"cats": [
@ -6458,6 +6833,15 @@
],
"website": "yiiframework.com"
},
"Yoast SEO": {
"cats": [
32
],
"html": [
"<!-- This site is optimized with the Yoast"
],
"website": "yoast.com"
},
"YouTube": {
"cats": [
14
@ -6604,7 +6988,7 @@
"cats": [
19
],
"html": "<[^]+id='cgit'",
"html": "<[^>]+id='cgit'",
"implies": "Perl",
"website": "git.zx2c4.com/cgit"
},
@ -7278,6 +7662,13 @@
},
"website": "webedition.de/en"
},
"webpack": {
"cats": [
44
],
"env": "^webpackJsonp$",
"website": "webpack.github.io"
},
"xCharts": {
"cats": [
25
@ -7370,6 +7761,7 @@
"47": "dev-tools",
"48": "network-storage",
"49": "feed-readers",
"50": "document-management-systems"
"50": "document-management-systems",
"51": "landing-page-builders"
}
}
}

@ -0,0 +1,59 @@
{
"github": { "message": "Κάνε fork το Wappalyzer στο GitHub!" },
"twitter": { "message": "Ακολούθησε το Wappalyzer στο Twitter" },
"website": { "message": "Πήγαινε στο wappalyzer.com" },
"options": { "message": "Ρυθμίσεις Wappalyzer" },
"optionsSave": { "message": "Ρυθμίσεις αποθήκευσης" },
"optionsSaved": { "message": "Αποθηκεύτηκε" },
"optionUpgradeMessage": { "message": "Ενημερώστε με για αναβαθμίσεις" },
"optionTracking": { "message": "Ανώνυμη αποστολή αναφορών για εντοπισμένες εφαρμογές στο wappalyzer.com για έρευνα" },
"nothingToDo": { "message": "Καμία ενέργεια." },
"noAppsDetected": { "message": "Δεν ανιχνεύθηκαν εφαρμογές." },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Διαδικτυακό Φόρουμ" },
"categoryName3": { "message": "Διαχειριστής Βάσης Δεδομένων" },
"categoryName4": { "message": "Εργαλείο Τεκμηρίωσης" },
"categoryName5": { "message": "Widget" },
"categoryName10": { "message": "Analytics" },
"categoryName11": { "message": "Blog" },
"categoryName12": { "message": "Framework της Javascript" },
"categoryName13": { "message": "Issue Tracker" },
"categoryName14": { "message": "Πρόγραμμα αναπαραγωγής Βίντεο" },
"categoryName15": { "message": "Σύστημα Σχολίων" },
"categoryName16": { "message": "Captcha" },
"categoryName17": { "message": "Script Γραμματοσειράς" },
"categoryName18": { "message": "Framework Διαδικτύου" },
"categoryName19": { "message": "Διάφορα" },
"categoryName20": { "message": "Επεξεργαστής Κειμένου" },
"categoryName21": { "message": "LMS" },
"categoryName22": { "message": "Διακομιστής Διαδικτύου" },
"categoryName23": { "message": "Εργαλείο Μνήμης Cache" },
"categoryName24": { "message": "Επεξεργαστής Εμπλουτισμένου Κειμένου" },
"categoryName25": { "message": "Γραφικά Javascript" },
"categoryName26": { "message": "Framework για Κινητά" },
"categoryName27": { "message": "Γλώσσα Προγραμματισμού" },
"categoryName28": { "message": "Λειτουργικό Σύστημα" },
"categoryName29": { "message": "Μηχανή Αναζήτησης" },
"categoryName30": { "message": "Web Mail" },
"categoryName31": { "message": "CDN" },
"categoryName32": { "message": "Αυτοματοποίηση Marketing" },
"categoryName33": { "message": "Επέκταση Διακομιστή Διαδικτύου" },
"categoryName34": { "message": "Βάση Δεδομένων" },
"categoryName35": { "message": "Χάρτης" },
"categoryName36": { "message": "Δίκτυο Διαφημίσεων" },
"categoryName37": { "message": "Υπηρεσία Δικτύου" },
"categoryName38": { "message": "Διακομιστής Πολυμέσων" },
"categoryName39": { "message": "Διαδικτυακή κάμερα" },
"categoryName40": { "message": "Εκτυπωτής" },
"categoryName41": { "message": "Σύστημα Επεξεργασίας Πληρωμών" },
"categoryName42": { "message": "Σύστημα Διαχείρισης Tags" },
"categoryName43": { "message": "Paywall" },
"categoryName44": { "message": "Σύστημα Build/CI" },
"categoryName45": { "message": "Σύστημα SCADA" },
"categoryName46": { "message": "Απομακρυσμένη Πρόσβαση" },
"categoryName47": { "message": "Εργαλείο Ανάπτυξης" },
"categoryName48": { "message": "Δικτυακός Αποθηκευτικός Χώρος" },
"categoryName49": { "message": "Feed Readers" },
"categoryName50": { "message": "Συστήματα Διαχειρίσης Εγγράφων" },
"categoryName51": { "message": "Σύστημα Κατασκευής Σελίδων Υποδοχής" }
}

@ -54,5 +54,6 @@
"categoryName47": { "message": "Development Tool" },
"categoryName48": { "message": "Network Storage" },
"categoryName49": { "message": "Feed Readers" },
"categoryName50": { "message": "Document Management Systems" }
}
"categoryName50": { "message": "Document Management Systems" },
"categoryName51": { "message": "Landing Page Builder" }
}

@ -58,5 +58,6 @@
"categoryName47": { "message": "Development Tool" },
"categoryName48": { "message": "Network Storage" },
"categoryName49": { "message": "Feed Readers" },
"categoryName50": { "message": "Document Management Systems" }
"categoryName50": { "message": "Document Management Systems" },
"categoryName51": { "message": "Landing Page Builder" }
}

@ -58,5 +58,6 @@
"categoryName47": { "message": "Outil de développement" },
"categoryName48": { "message": "Stockage réseau" },
"categoryName49": { "message": "Lecteur RSS" },
"categoryName50": { "message": "Système de gestion de documents" }
"categoryName50": { "message": "Système de gestion de documents" },
"categoryName51": { "message": "Landing Page Builder" }
}

@ -0,0 +1,59 @@
{
"github": { "message": "Κάνε fork το Wappalyzer στο GitHub!" },
"twitter": { "message": "Ακολούθησε το Wappalyzer στο Twitter" },
"website": { "message": "Πήγαινε στο wappalyzer.com" },
"options": { "message": "Ρυθμίσεις Wappalyzer" },
"optionsSave": { "message": "Ρυθμίσεις αποθήκευσης" },
"optionsSaved": { "message": "Αποθηκεύτηκε" },
"optionUpgradeMessage": { "message": "Ενημερώστε με για αναβαθμίσεις" },
"optionTracking": { "message": "Ανώνυμη αποστολή αναφορών για εντοπισμένες εφαρμογές στο wappalyzer.com για έρευνα" },
"nothingToDo": { "message": "Καμία ενέργεια." },
"noAppsDetected": { "message": "Δεν ανιχνεύθηκαν εφαρμογές." },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Διαδικτυακό Φόρουμ" },
"categoryName3": { "message": "Διαχειριστής Βάσης Δεδομένων" },
"categoryName4": { "message": "Εργαλείο Τεκμηρίωσης" },
"categoryName5": { "message": "Widget" },
"categoryName10": { "message": "Analytics" },
"categoryName11": { "message": "Blog" },
"categoryName12": { "message": "Framework της Javascript" },
"categoryName13": { "message": "Issue Tracker" },
"categoryName14": { "message": "Πρόγραμμα αναπαραγωγής Βίντεο" },
"categoryName15": { "message": "Σύστημα Σχολίων" },
"categoryName16": { "message": "Captcha" },
"categoryName17": { "message": "Script Γραμματοσειράς" },
"categoryName18": { "message": "Framework Διαδικτύου" },
"categoryName19": { "message": "Διάφορα" },
"categoryName20": { "message": "Επεξεργαστής Κειμένου" },
"categoryName21": { "message": "LMS" },
"categoryName22": { "message": "Διακομιστής Διαδικτύου" },
"categoryName23": { "message": "Εργαλείο Μνήμης Cache" },
"categoryName24": { "message": "Επεξεργαστής Εμπλουτισμένου Κειμένου" },
"categoryName25": { "message": "Γραφικά Javascript" },
"categoryName26": { "message": "Framework για Κινητά" },
"categoryName27": { "message": "Γλώσσα Προγραμματισμού" },
"categoryName28": { "message": "Λειτουργικό Σύστημα" },
"categoryName29": { "message": "Μηχανή Αναζήτησης" },
"categoryName30": { "message": "Web Mail" },
"categoryName31": { "message": "CDN" },
"categoryName32": { "message": "Αυτοματοποίηση Marketing" },
"categoryName33": { "message": "Επέκταση Διακομιστή Διαδικτύου" },
"categoryName34": { "message": "Βάση Δεδομένων" },
"categoryName35": { "message": "Χάρτης" },
"categoryName36": { "message": "Δίκτυο Διαφημίσεων" },
"categoryName37": { "message": "Υπηρεσία Δικτύου" },
"categoryName38": { "message": "Διακομιστής Πολυμέσων" },
"categoryName39": { "message": "Διαδικτυακή κάμερα" },
"categoryName40": { "message": "Εκτυπωτής" },
"categoryName41": { "message": "Σύστημα Επεξεργασίας Πληρωμών" },
"categoryName42": { "message": "Σύστημα Διαχείρισης Tags" },
"categoryName43": { "message": "Paywall" },
"categoryName44": { "message": "Σύστημα Build/CI" },
"categoryName45": { "message": "Σύστημα SCADA" },
"categoryName46": { "message": "Απομακρυσμένη Πρόσβαση" },
"categoryName47": { "message": "Εργαλείο Ανάπτυξης" },
"categoryName48": { "message": "Δικτυακός Αποθηκευτικός Χώρος" },
"categoryName49": { "message": "Feed Readers" },
"categoryName50": { "message": "Συστήματα Διαχειρίσης Εγγράφων" },
"categoryName51": { "message": "Σύστημα Κατασκευής Σελίδων Υποδοχής" }
}

@ -0,0 +1,64 @@
{
"github": { "message": "Fork Wappalyzer su GitHub!" },
"twitter": { "message": "Follow Wappalyzer su Twitter" },
"website": { "message": "Vai su wappalyzer.com" },
"options": { "message": "Opzioni Wappalyzer" },
"optionsSave": { "message": "Salva opzioni" },
"optionsSaved": { "message": "Salvato" },
"optionUpgradeMessage": { "message": "Parlami dell'upgrade" },
"optionTracking": { "message": "Inviare anonimamente un report sulle applicazioni rilevate a wappalyzer.com per l'analisi" },
"nothingToDo": { "message": "Niente da fare qui." },
"noAppsDetected": { "message": "Nessuna applicazione rilevata." },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Forum" },
"categoryName3": { "message": "Gestore di Database" },
"categoryName4": { "message": "Strumento di documentazione" },
"categoryName5": { "message": "Widget" },
"categoryName6": { "message": "eCommerce" },
"categoryName7": { "message": "Galleria fotografica" },
"categoryName8": { "message": "Wiki" },
"categoryName9": { "message": "Pannello Hosting" },
"categoryName10": { "message": "Analytics" },
"categoryName11": { "message": "Blog" },
"categoryName12": { "message": "Framework Javascript" },
"categoryName13": { "message": "Issue Tracker" },
"categoryName14": { "message": "Player Video" },
"categoryName15": { "message": "Sistema di commenti" },
"categoryName16": { "message": "Captcha" },
"categoryName17": { "message": "Font Script" },
"categoryName18": { "message": "Framework Web" },
"categoryName19": { "message": "Miscellanea" },
"categoryName20": { "message": "Editor" },
"categoryName21": { "message": "LMS" },
"categoryName22": { "message": "Web Server" },
"categoryName23": { "message": "Cache Tool" },
"categoryName24": { "message": "Editor di Testo Ricco" },
"categoryName25": { "message": "Javascript Graphics" },
"categoryName26": { "message": "Framework Mobile" },
"categoryName27": { "message": "Linguaggio di programmazione" },
"categoryName28": { "message": "Sistema Operativo" },
"categoryName29": { "message": "Motore di Ricerca" },
"categoryName30": { "message": "Web Mail" },
"categoryName31": { "message": "CDN" },
"categoryName32": { "message": "Marketing Automation" },
"categoryName33": { "message": "Estensione Web Server" },
"categoryName34": { "message": "Database" },
"categoryName35": { "message": "Mappa" },
"categoryName36": { "message": "Network Pubblicitario" },
"categoryName37": { "message": "Network Service" },
"categoryName38": { "message": "Media Server" },
"categoryName39": { "message": "Webcam" },
"categoryName40": { "message": "Stampante" },
"categoryName41": { "message": "Payment Processor" },
"categoryName42": { "message": "Tag Manager" },
"categoryName43": { "message": "Paywall" },
"categoryName44": { "message": "Sistema Build/CI" },
"categoryName45": { "message": "SCADA System" },
"categoryName46": { "message": "Accesso" },
"categoryName47": { "message": "Strumenti di Sviluppo" },
"categoryName48": { "message": "Network Storage" },
"categoryName49": { "message": "Lettore di Feed" },
"categoryName50": { "message": "Sistema di Gestione Documenti" },
"categoryName51": { "message": "Landing Page Builder" }
}

@ -54,5 +54,6 @@
"categoryName47": { "message": "Development Tool" },
"categoryName48": { "message": "Network Storage" },
"categoryName49": { "message": "Feed Readers" },
"categoryName50": { "message": "Document Management Systems" }
"categoryName50": { "message": "Document Management Systems" },
"categoryName51": { "message": "Landing Page Builder" }
}

@ -45,6 +45,7 @@
"categoryName48" : { "message" : "Сетевое хранилище" },
"categoryName49" : { "message" : "Граббер контента" },
"categoryName50" : { "message" : "Управление документами" },
"categoryName51": { "message": "Landing Page Builder" },
"github" : { "message" : "Форкнуть на GitHub!" },
"noAppsDetected" : { "message" : "Нет данных о сайте" },
"nothingToDo" : { "message" : "Тут нечего искать" },
@ -55,4 +56,4 @@
"optionsSaved" : { "message" : "Успешно сохранено!" },
"twitter" : { "message" : "Следите за новостями в Твиттере" },
"website" : { "message" : "Перейти на Wappalyzer.com" }
}
}

@ -0,0 +1,699 @@
'use strict';
var exports = {};
(function(exports) {
var utils = {
pageMeta: {
url: window.location.hostname,
isHP: window.location.pathname === '/',
referrer: window.document.referrer,
rand: Math.floor(Math.random() * 10e12),
startTime: new Date().getTime()
},
realArray: function(a) {
return Array.prototype.slice.apply(a);
},
SCRIPT_IN_WINDOW_TOP: window === window.top,
isFriendlyWindow: function(win) {
var href;
try {
href = win.location.href;
} catch(e) {
return false;
}
return true;
},
elementWindow: function(el) {
return el.ownerDocument.defaultView;
},
viewport: function(win) {
return {width: win.innerWidth, height: win.innerHeight};
},
parseQS: function(qs) {
if (qs.indexOf('http') === 0) {
qs = qs.split('?')[1];
}
var i, kvs, key, val;
var dict = {};
qs = qs.split('&');
for ( i = 0; i < qs.length; i++ ) {
kvs = qs[i].split('=');
key = kvs[0];
val = kvs.slice(1).join('=');
try {
dict[key] = window.decodeURIComponent(val);
} catch (e) {
this.log('URI decode error', kvs);
continue;
}
}
return dict;
},
makeLog: function(opt_adData, opt_msgNum, opt_pageTags) {
var assets = [opt_adData] || [];
return {
doc: this.pageMeta,
assets: assets,
version: '3',
msgNum: opt_msgNum || 0,
pageTags: opt_pageTags || []
};
},
expBackoff: function(callback, initTimeoutMS, opt_maxTimeoutMS) {
var curTimeout = initTimeoutMS;
var wrapped = function() {
callback();
var nextTimeout = 2 * curTimeout;
curTimeout = opt_maxTimeoutMS ? Math.min(nextTimeout, opt_maxTimeoutMS) : nextTimeout;
setTimeout(wrapped, curTimeout);
};
setTimeout(wrapped, curTimeout);
},
};
utils.SCRIPT_IN_FRIENDLY_IFRAME = !utils.SCRIPT_IN_WINDOW_TOP && utils.isFriendlyWindow(window.parent);
utils.SCRIPT_IN_HOSTILE_IFRAME = !utils.SCRIPT_IN_WINDOW_TOP && !utils.SCRIPT_IN_FRIENDLY_IFRAME;
exports.utils = utils;
})(exports);
(function(exports) {
var VALID_AD_SIZES = [
[160, 600],
[300, 250],
[300, 600],
[300, 1050],
[336, 280],
[336, 850],
[468, 60],
[728, 90],
[728, 270],
[970, 66],
[970, 90],
[970, 250],
[970, 400],
[970, 415]
];
var
PX_SIZE_TOL = 10,
MIN_WINDOW_PX = 10,
MAX_SEARCHES_PER_WINDOW = 10,
MAX_SEARCHES_PER_ELEMENT = 2;
var SIZE_SET = (function makeSizeSet() {
var
set = {},
i,
xfuz,
yfuz,
size,
width,
height;
for ( i = 0; i < VALID_AD_SIZES.length; i++ ) {
for (xfuz = -PX_SIZE_TOL; xfuz <= PX_SIZE_TOL; xfuz++ ) {
for ( yfuz = -PX_SIZE_TOL; yfuz <= PX_SIZE_TOL; yfuz++ ) {
size = VALID_AD_SIZES[i];
width = size[0] + xfuz;
height = size[1] + yfuz;
set[width] = set[width] || {};
set[width][height] = true;
}
}
}
return set;
})();
function elementIsAd(el) {
if ( typeof el.searches !== 'number' ) {
el.searches = 0;
}
if ( el.searches >= MAX_SEARCHES_PER_ELEMENT ) {
return false;
}
el.searches ++;
var w = el.offsetWidth;
return SIZE_SET[w] && SIZE_SET[w][el.offsetHeight];
}
function windowMightContainAds(win) {
return win.innerWidth >= MIN_WINDOW_PX && win.innerHeight >= MIN_WINDOW_PX;
}
function isNewAd(el) {
return el.mp_adFound !== true;
}
function getFriendlyIframes(win) {
var iframes = win.document.querySelectorAll('iframe');
iframes = exports.utils.realArray(iframes);
var friendlyIframes = iframes.filter(function(ifr) {
return exports.utils.isFriendlyWindow(ifr.contentWindow);
});
return friendlyIframes;
}
function findAds(win, opt_ads) {
if ( !windowMightContainAds(win) ) {
return;
}
if ( typeof win.searches !== 'number' ) {
win.searches = 0;
}
var ads = opt_ads || [];
if ( exports.utils.SCRIPT_IN_WINDOW_TOP || win.searches < MAX_SEARCHES_PER_WINDOW ) {
var adCandidates = win.document.querySelectorAll('img, object, embed');
adCandidates = exports.utils.realArray(adCandidates);
adCandidates.forEach(function(el) {
if (elementIsAd(el) && isNewAd(el)) {
el.mp_adFound = true;
ads.push(el);
}
});
win.searches ++;
}
var iframes = getFriendlyIframes(win);
iframes.forEach(function(ifr) {
findAds(ifr.contentWindow, ads);
});
return ads;
}
exports.adfinder = {
findAds: findAds
};
})(exports);
(function(exports) {
var parser = {
TAGS_WITH_SRC_ATTR: {
'IMG': true,
'SCRIPT': true,
'IFRAME': true,
'EMBED': true
},
MAX_ATTR_LEN: 100,
getUrl: function(el, params) {
var url;
if ( this.TAGS_WITH_SRC_ATTR.hasOwnProperty(el.tagName) ) {
url = el.src;
} else if ( el.tagName === 'OBJECT' ) {
url = el.data || (params && params.movie) || null;
} else if ( el.tagName === 'A' ) {
url = el.href;
}
if ( url && url.indexOf('http') === 0 ) {
return url;
} else {
return null;
}
},
getParams: function(el) {
if ( el.tagName !== 'OBJECT' ) {
return null;
}
var i, child;
var params = {};
var children = el.children;
for ( i = 0; i < children.length; i++ ) {
child = children[i];
if ( child.tagName === 'PARAM' && child.name ) {
params[child.name.toLowerCase()] = child.value;
}
}
return params;
},
getPosition: function(el) {
var rect = el.getBoundingClientRect();
var win = exports.utils.elementWindow(el);
return {
width: rect.width,
height: rect.height,
left: rect.left + win.pageXOffset,
top: rect.top + win.pageYOffset
};
},
getFlashvars: function(el, params, url) {
var flashvars;
var urlQS = url && url.split('?')[1];
if ( el.tagName === 'EMBED' ) {
flashvars = el.getAttribute('flashvars') || urlQS;
} else if (el.tagName === 'OBJECT') {
flashvars = params.flashvars || el.getAttribute('flashvars') || urlQS;
}
return (flashvars && exports.utils.parseQS(flashvars)) || null;
},
findClickThru: function(el, flashvars) {
var key;
if ( el.tagName === 'IMG' && el.parentElement.tagName === 'A' ) {
return el.parentElement.href;
} else if ( flashvars ) {
for ( key in flashvars ) {
if ( flashvars.hasOwnProperty(key) ) {
if (key.toLowerCase().indexOf('clicktag') === 0) {
return flashvars[key];
}
}
}
}
return null;
},
getAttr: function(el, name) {
var val = el.getAttribute(name);
if ( val && val.slice && val.toString ) {
return val.slice(0, this.MAX_ATTR_LEN).toString();
} else {
return null;
}
},
putPropIfExists: function(obj, name, val) {
if (val) {
obj[name] = val;
}
},
putAttrIfExists: function(obj, el, name) {
var val = this.getAttr(el, name);
this.putPropIfExists(obj, name, val);
},
elementToJSON: function(el, opt_findClickThru) {
var pos = this.getPosition(el);
var params = this.getParams(el);
var url = this.getUrl(el, params);
var flashvars = this.getFlashvars(el, params, url);
var clickThru = opt_findClickThru && this.findClickThru(el, flashvars);
var json = {
tagName: el.tagName,
width: pos.width,
height: pos.height,
left: pos.left,
top: pos.top,
children: []
};
if (params) {
delete params.flashvars;
}
this.putAttrIfExists(json, el, 'id');
this.putAttrIfExists(json, el, 'class');
this.putAttrIfExists(json, el, 'name');
this.putPropIfExists(json, 'flashvars', flashvars);
this.putPropIfExists(json, 'url', url);
this.putPropIfExists(json, 'params', params);
this.putPropIfExists(json, 'clickThru', clickThru);
return json;
}
};
exports.parser = { elementToJSON: parser.elementToJSON.bind(parser) };
})(exports);
(function(exports) {
var ContextManager = function(adData) {
this.adData = adData;
};
ContextManager.prototype = {
CONTAINER_SIZE_TOL: 0.4,
ASPECT_RATIO_FOR_LEADERBOARDS: 2,
isValidContainer: function(el, opt_curWin) {
var cWidth = el.clientWidth;
var cHeight = el.clientHeight;
var adWidth = this.adData.width;
var adHeight = this.adData.height;
var winWidth = opt_curWin && opt_curWin.innerWidth;
var winHeight = opt_curWin && opt_curWin.innerHeight;
var similarWin = opt_curWin && this.withinTol(adWidth, winWidth) && this.withinTol(adHeight, winHeight);
var similarSizeX = this.withinTol(adWidth, cWidth);
var similarSizeY = this.withinTol(adHeight, cHeight);
var adAspect = adWidth / adHeight;
return similarWin || el.tagName === 'A' || ( adAspect >= this.ASPECT_RATIO_FOR_LEADERBOARDS && similarSizeY ) || (similarSizeX && similarSizeY);
},
withinTol: function(adlen, conlen) {
var pct = (conlen - adlen) / adlen;
return pct <= this.CONTAINER_SIZE_TOL;
},
serializeElements: function(el) {
if ( !el ) {
return;
}
var i;
var ifrWin;
var adId = this.adData.adId;
var elIsAd = false;
if ( adId && el[adId] && el[adId].isAd === true ) {
elIsAd = true;
}
var json = exports.parser.elementToJSON(el, elIsAd);
if ( elIsAd ) {
json.adId = adId;
this.adData.element = json;
}
var children = exports.utils.realArray(el.children).filter(function(el) {
var param = el.tagName === 'PARAM';
var inlineScript = el.tagName === 'SCRIPT' && !(el.src && el.src.indexOf('http') >= 0);
var noScript = el.tagName === 'NOSCRIPT';
return !(param || inlineScript || noScript);
});
for ( i = 0; i < children.length; i++ ) {
json.children.push(this.serializeElements(children[i]));
}
if ( el.tagName === 'IFRAME' ) {
ifrWin = el.contentWindow;
if ( adId && el[adId] && el[adId].needsWindow ) {
json.contents = this.adData.serializedIframeContents;
el[adId].needsWindow = false;
delete this.adData.serializedIframeContents;
} else if ( exports.utils.isFriendlyWindow(ifrWin) ) {
json.contents = this.serializeElements(ifrWin.document.documentElement);
}
}
return json;
},
captureHTML: function(containerEl) {
this.adData.context = this.serializeElements(containerEl);
if ( this.adData.html ) {
this.adData.html.push(containerEl.outerHTML);
}
},
nodeCount: function(el) {
return el.getElementsByTagName('*').length + 1;
},
highestContainer: function(curWin, referenceElement) {
var curContainer = referenceElement;
var docEl = curWin.document.documentElement;
var parentContainer;
if ( curWin !== curWin.top && this.isValidContainer(docEl, curWin) ) {
return docEl;
}
while ( true ) {
parentContainer = curContainer.parentElement;
if (this.isValidContainer(parentContainer)) {
curContainer = parentContainer;
} else {
return curContainer;
}
}
}
};
var tagfinder = {
prepToSend: function(adData) {
delete adData.width;
delete adData.height;
},
setPositions: function(adData, opt_el, opt_winPos) {
var el = opt_el || adData.context;
var winPos = opt_winPos || {left: 0, top: 0};
var ifrPos;
el.left += winPos.left;
el.top += winPos.top;
el.children.forEach(function(child) {
this.setPositions(adData, child, winPos);
}, this);
if ( el.contents ) {
ifrPos = {left: el.left, top: el.top};
this.setPositions(adData, el.contents, ifrPos);
}
if ( el.adId === adData.adId ) {
adData.element.left = el.left;
adData.element.top = el.top;
}
},
appendTags: function(adData, referenceElement) {
var mgr = new ContextManager(adData);
var curWin = exports.utils.elementWindow(referenceElement);
var highestContainer;
while (true) {
highestContainer = mgr.highestContainer(curWin, referenceElement);
mgr.captureHTML(highestContainer);
if (curWin === window.top) {
break;
} else {
mgr.adData.serializedIframeContents = mgr.adData.context;
if (exports.utils.isFriendlyWindow(curWin.parent)) {
referenceElement = curWin.frameElement;
referenceElement[mgr.adData.adId] = { needsWindow: true };
curWin = curWin.parent;
} else {
break;
}
}
}
return {
referenceElement:referenceElement,
highestContainer: highestContainer
};
}
};
exports.tagfinder = tagfinder;
})(exports);
(function(exports) {
var _onAdFound;
var _getFullHTML;
var _logsSent = 0;
var _pageTags;
var INIT_MS_BW_SEARCHES = 2000;
var PAGE_TAG_RE = new RegExp('gpt|oascentral');
function getPageTags(doc) {
var scripts = doc.getElementsByTagName('script');
var pageTags = [];
scripts = exports.utils.realArray(scripts);
scripts.forEach(function(script) {
if (PAGE_TAG_RE.exec(script.src)) {
pageTags.push({'tagName': 'SCRIPT', 'url': script.src});
}
});
return pageTags;
}
function messageAllParentFrames(adData) {
adData.dummyId = true;
var win = window;
while ( win !== win.top ) {
win = win.parent;
win.postMessage(adData, '*');
}
}
function appendTagsAndSendToParent(adData, referenceElement) {
var results = exports.tagfinder.appendTags(adData, referenceElement);
if ( exports.utils.SCRIPT_IN_HOSTILE_IFRAME ) {
messageAllParentFrames(adData);
} else if ( exports.utils.SCRIPT_IN_WINDOW_TOP ) {
exports.tagfinder.setPositions(adData);
exports.tagfinder.prepToSend(adData);
var html = adData.html;
delete adData.html;
adData.curPageUrl = window.location.href;
_pageTags = _pageTags || getPageTags(document);
var log = exports.utils.makeLog(adData, _logsSent, _pageTags);
if ( _onAdFound ) {
_onAdFound(log, html, results.referenceElement);
_logsSent++;
}
}
}
function extractAdsWrapper() {
extractAds();
setTimeout(extractAdsWrapper, INIT_MS_BW_SEARCHES);
}
function extractAds() {
var ads = exports.adfinder.findAds(window);
if ( !ads ) {
return;
}
ads.forEach(function(ad) {
var startTime = new Date().getTime();
var adId = startTime + '-' + Math.floor(Math.random() * 10e12);
var adData = {
width: ad.offsetWidth,
height: ad.offsetHeight,
startTime: startTime,
html: ( _getFullHTML && [] ) || null,
adId: adId
};
ad[adId] = { isAd: true };
appendTagsAndSendToParent(adData, ad);
});
}
function onPostMessage(event) {
var adData = event.data;
var ifrTag;
if ( !adData.dummyId ) {
return;
}
delete adData.dummyId;
try {
ifrTag = event.source.frameElement;
} catch(e) {
return false;
}
ifrTag[adData.adId] = {needsWindow: true};
appendTagsAndSendToParent(adData, ifrTag);
}
exports.coordinator = {
init: function(onAdFound, opt_getFullHTML) {
if (exports.utils.SCRIPT_IN_FRIENDLY_IFRAME) {
return false;
}
_onAdFound = onAdFound;
_getFullHTML = opt_getFullHTML;
if ( exports.utils.SCRIPT_IN_WINDOW_TOP ) {
chrome.runtime.sendMessage({ event: 'new-page', url: window.location.href });
}
window.addEventListener('message', onPostMessage, false);
if ( document.readyState !== 'loading' ) {
extractAdsWrapper();
} else {
document.addEventListener('DOMContentLoaded', extractAdsWrapper);
}
}
};
})(exports);
(function(exports) {
var onAdFound = function(log) {
chrome.extension.sendRequest({ id: 'ad_log', subject: log });
};
var getFullHTML = false;
exports.coordinator.init(onAdFound, getFullHTML);
})(exports);

@ -44,7 +44,7 @@
document.documentElement.removeChild(container);
document.documentElement.removeChild(script);
c.log('getEnvironmentVars: ' + environmentVars);
//c.log('getEnvironmentVars: ' + environmentVars);
environmentVars = environmentVars.split(' ').slice(0, 500);

@ -3,14 +3,17 @@
*/
(function() {
if ( wappalyzer == null ) { return; }
if ( wappalyzer == null ) {
return;
}
var w = wappalyzer,
firstRun = false,
upgraded = false,
tab,
tabCache = {},
headersCache = {};
headersCache = {},
adCache = [];
w.driver = {
/**
@ -26,8 +29,6 @@
init: function() {
w.log('init');
//chrome.browserAction.setBadgeBackgroundColor({ color: [255, 102, 0, 255] });
// Load apps.json
var xhr = new XMLHttpRequest();
@ -88,6 +89,10 @@
w.analyze(hostname, a.href, request.subject);
break;
case 'ad_log':
adCache.push(request.subject);
break;
case 'get_apps':
sendResponse({
@ -189,7 +194,6 @@
for ( appName in w.detected[url] ) {
w.apps[appName].cats.forEach(function(cat) {
if ( cat == match && !found ) {
//chrome.browserAction.setIcon({ tabId: tab.id, path: 'images/icons/' + appName + '.png' });
chrome.pageAction.setIcon({ tabId: tab.id, path: 'images/icons/' + appName + '.png' });
found = true;
@ -198,7 +202,6 @@
}
});
//chrome.browserAction.setBadgeText({ tabId: tab.id, text: count });
chrome.pageAction.show(tab.id);
};
},
@ -208,30 +211,45 @@
*/
ping: function() {
if ( Object.keys(w.ping.hostnames).length && localStorage['tracking'] ) {
// Make POST request
var xhr = new XMLHttpRequest();
w.driver.post(w.config.websiteURL + 'ping/v2/', w.ping);
xhr.open('POST', w.config.websiteURL + 'ping/v2/', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
w.log('w.driver.ping: ' + JSON.stringify(w.ping));
xhr.onreadystatechange = function(e) {
if ( xhr.readyState == 4 ) { w.log('w.driver.ping: status ' + xhr.status); }
};
w.ping = { hostnames: {} };
xhr.send('json=' + encodeURIComponent(JSON.stringify(w.ping)));
w.driver.post('https://ad.wappalyzer.com/log/wp/', adCache);
w.log('w.driver.ping: ' + JSON.stringify(w.ping));
w.log('adCache: ' + JSON.stringify(adCache)); //
w.ping = { hostnames: {} };
adCache = [];
}
},
/**
* Make POST request
*/
post: function(url, data) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function(e) {
if ( xhr.readyState == 4 ) {
w.log('w.driver.post: status ' + xhr.status + ' (' + url + ')');
}
};
xhr.send('json=' + encodeURIComponent(JSON.stringify(data)));
},
categoryOrder: [ // Used to pick the main application
1, // CMS
11, // Blog
6, // Web Shop
2, // Message Board
51, // Landing Page Builder
8, // Wiki
13, // Issue Tracker
30, // Web Mail

@ -1,7 +1,7 @@
{ "name": "Wappalyzer",
"homepage_url": "https://wappalyzer.com?pk_campaign=chrome&pk_kwd=context",
"description": "Identifies software on the web",
"version": "2.37",
"version": "2.38",
"default_locale": "en",
"manifest_version": 2,
"icons": {
@ -16,10 +16,15 @@
},
"background": { "page": "background.html" },
"content_scripts": [{
"matches": [ "http://*/*", "https://*/*" ],
"js": [ "js/content.js" ],
"run_at": "document_idle"
}],
"matches": [ "http://*/*", "https://*/*" ],
"js": [ "js/content.js" ],
"run_at": "document_idle"
}, {
"matches": [ "http://*/*", "https://*/*" ],
"js": [ "js/ad.js" ],
"run_at": "document_start",
"all_frames": true
}],
"web_accessible_resources": [
"js/inject.js"
],

@ -10,8 +10,8 @@
Window,
Tab,
Panel,
Widget,
widget, // Keep track of a global widget instance. A widget per window does not work.
Button,
button,
UrlBar;
exports.main = function(options, callbacks) {
@ -40,21 +40,28 @@
this.window = win;
this.tabs = {};
this.urlBar = null;
this.widget = null;
if ( button ) {
button.destroy();
}
if ( require('sdk/simple-prefs').prefs.urlbar ) {
this.urlBar = new UrlBar(this.window);
} else {
this.widget = widget || ( widget = new Widget() );
button = new Button();
}
require('sdk/simple-prefs').on('urlbar', function() {
self.destroy();
if ( button ) {
button.destroy();
}
if ( require('sdk/simple-prefs').prefs.urlbar ) {
self.urlBar = new UrlBar(this.window);
} else {
self.widget = widget || ( widget = new Widget() );
button = new Button();
}
self.displayApps();
@ -120,8 +127,8 @@
this.urlBar.panel.get().port.emit('displayApps', message);
}
if ( this.widget ) {
this.widget.setIcon();
if ( button ) {
button.setIcon();
if ( count ) {
var
@ -133,7 +140,7 @@
for ( appName in w.detected[url] ) {
w.apps[appName].cats.forEach(function(cat) {
if ( cat == match && !found ) {
self.widget.setIcon(appName);
button.setIcon(appName);
found = true;
}
@ -142,7 +149,7 @@
});
}
this.widget.panel.get().port.emit('displayApps', message);
button.panel.get().port.emit('displayApps', message);
}
};
@ -152,12 +159,6 @@
this.urlBar = null;
}
if ( this.widget ) {
this.widget.destroy();
this.widget = null;
}
};
Tab = function(tab) {
@ -190,7 +191,12 @@
height: 50,
contentURL: require('sdk/self').data.url('panel.html'),
contentScriptFile: require('sdk/self').data.url('js/panel.js'),
position: { right: 30, top: 30 }
position: { right: 30, top: 30 },
onHide: function() {
if ( button ) {
button.get().state('window', { checked: false });
}
}
});
this.panel.port.on('resize', function(height) {
@ -212,31 +218,37 @@
this.panel.destroy();
};
Widget = function() {
Button = function() {
var self = this;
this.panel = new Panel();
this.widget = require('sdk/widget').Widget({
this.button = require('sdk/ui/button/toggle').ToggleButton({
id: 'wappalyzer',
label: 'Wappalyzer',
contentURL: require('sdk/self').data.url('images/icon32.png'),
panel: this.panel.get()
icon: './images/icon32.png',
onChange: function(state) {
if ( state.checked ) {
self.panel.get().show({ position: self.button });
}
}
});
};
Widget.prototype.setIcon = function(appName) {
var url = typeof appName === 'undefined' ? 'images/icon32_hot.png' : 'images/icons/' + appName + '.png';
Button.prototype.setIcon = function(appName) {
var url = typeof appName === 'undefined' ? './images/icon32.png' : './images/icons/' + appName + '.png';
this.get().contentURL = require('sdk/self').data.url(url);
this.button.icon = url;
};
Widget.prototype.get = function() {
return this.widget;
Button.prototype.get = function() {
return this.button;
};
Widget.prototype.destroy = function() {
Button.prototype.destroy = function() {
this.panel.destroy();
this.widget.destroy();
this.button.destroy();
};
UrlBar = function(window) {
@ -249,7 +261,7 @@
}
// Can't get document from sdk/windows. Use active window instead.
// This breaks switching between URL bar and widget with multiple windows open
// This breaks switching between URL bar and button with multiple windows open
this.document = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator)
.getMostRecentWindow('navigator:browser').document;
@ -440,6 +452,7 @@
11, // Blog
6, // Web Shop
2, // Message Board
51, // Landing Page Builder
8, // Wiki
13, // Issue Tracker
30, // Web Mail

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,529 @@
/**
* Wappalyzer v2
*
* Created by Elbert Alias <elbert@alias.io>
*
* License: GPLv3 http://www.gnu.org/licenses/gpl-3.0.txt
*/
var wappalyzer = (function() {
//'use strict';
/**
* Application class
*/
var Application = function(app, detected) {
this.app = app;
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.excludes = [];
this.version = '';
this.versions = [];
};
Application.prototype = {
/**
* Calculate confidence total
*/
getConfidence: function() {
var total = 0, id;
for ( id in this.confidence ) {
total += this.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
},
/**
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
getVersion: function() {
var i, resolved;
if ( !this.versions.length ) {
return;
}
this.versions.sort(function(a, b) {
return a.length - b.length;
});
resolved = this.versions[0];
for ( i = 1; i < this.versions.length; i++ ) {
if ( this.versions[i].indexOf(resolved) === -1 ) {
break;
}
resolved = this.versions[i];
}
return this.version = resolved;
},
setDetected: function(pattern, type, value, key) {
this.detected = true;
// Set confidence level
this.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value);
if ( matches ) {
matches.forEach(function(match, i) {
// Parse ternary operator
var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.*)$').exec(version);
if ( ternary && ternary.length === 3 ) {
w.log({ match: match, i: i, ternary: ternary });
version = version.replace(ternary[0], match ? ternary[1] : ternary[2]);
w.log({ version: version });
}
// Replace back references
version = version.replace(new RegExp('\\\\' + i, 'g'), match ? match : '');
});
if ( version && this.versions.indexOf(version) < 0 ) {
this.versions.push(version);
}
this.getVersion();
}
}
}
};
var Profiler = function() {
this.regexCount = 0;
this.startTime = new Date().getTime();
this.lastTime = new Date().getTime();
this.slowest = { duration: null, app: '', type: '', pattern: '' };
this.timedOut = false;
};
Profiler.prototype = {
checkPoint: function(app, type, regex) {
var duration = new Date().getTime() - this.lastTime;
if ( !this.slowest.duration || duration > this.slowest.duration ) {
this.slowest.duration = duration;
this.slowest.app = app;
this.slowest.type = type;
this.slowest.regex = regex;
}
this.regexCount++;
this.lastTime = new Date().getTime();
this.timedOut = this.lastTime - this.startTime > 1000;
}
};
/**
* Call driver functions
*/
var driver = function(func, args) {
if ( typeof w.driver[func] !== 'function' ) {
w.log('not implemented: w.driver.' + func, 'warn');
return;
}
if ( func !== 'log' ) {
w.log('w.driver.' + func);
}
return w.driver[func](args);
};
/**
* Parse apps.json patterns
*/
var parse = function(patterns) {
var
attrs,
parsed = [];
// Convert single patterns to an array
if ( typeof patterns === 'string' ) {
patterns = [ patterns ];
}
patterns.forEach(function(pattern) {
attrs = {};
pattern.split('\\;').forEach(function(attr, i) {
if ( i ) {
// Key value pairs
attr = attr.split(':');
if ( attr.length > 1 ) {
attrs[attr.shift()] = attr.join(':');
}
} else {
attrs.string = attr;
try {
attrs.regex = new RegExp(attr.replace('/', '\/'), 'i'); // Escape slashes in regular expression
} catch (e) {
attrs.regex = new RegExp();
w.log(e + ': ' + attr, 'error');
}
}
});
parsed.push(attrs);
});
return parsed;
};
/**
* Main script
*/
var w = {
apps: {},
cats: null,
ping: { hostnames: {} },
detected: {},
config: {
websiteURL: 'https://wappalyzer.com/',
twitterURL: 'https://twitter.com/Wappalyzer',
githubURL: 'https://github.com/AliasIO/Wappalyzer',
},
/**
* Log messages to console
*/
log: function(message, type) {
if ( type === undefined ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
},
/**
* Initialize
*/
init: function() {
w.log('w.init');
// Checks
if ( w.driver === undefined ) {
w.log('no driver, exiting');
return;
}
// Initialize driver
driver('init');
},
/**
* Analyze the request
*/
analyze: function(hostname, url, data) {
var
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version, id,
profiler = new Profiler(),
apps = {},
excludes = [],
checkImplies = true;
w.log('w.analyze');
// Remove hash from URL
data.url = url = url.split('#')[0];
if ( w.apps === undefined || w.categories === undefined ) {
w.log('apps.json not loaded, check for syntax errors');
return;
}
if ( w.detected[url] === undefined ) {
w.detected[url] = {};
}
for ( app in w.apps ) {
// Exit loop after one second to prevent CPU hogging
// Remaining patterns will not be evaluated
if ( profiler.timedOut ) {
w.log('Timeout, exiting loop');
break;
}
apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
case 'url':
parse(w.apps[app][type]).forEach(function(pattern) {
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type, url);
}
profiler.checkPoint(app, type, pattern.regex);
});
break;
case 'html':
if ( typeof data[type] !== 'string' || !data.html ) {
break;
}
parse(w.apps[app][type]).forEach(function(pattern) {
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type, data[type]);
}
profiler.checkPoint(app, type, pattern.regex);
});
break;
case 'script':
if ( typeof data.html !== 'string' || !data.html ) {
break;
}
regexScript = new RegExp('<script[^>]+src=("|\')([^"\']+)', 'ig');
parse(w.apps[app][type]).forEach(function(pattern) {
while ( match = regexScript.exec(data.html) ) {
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type, match[2]);
}
}
profiler.checkPoint(app, type, pattern.regex);
});
break;
case 'meta':
if ( typeof data.html !== 'string' || !data.html ) {
break;
}
regexMeta = /<meta[^>]+>/ig;
while ( match = regexMeta.exec(data.html) ) {
for ( meta in w.apps[app][type] ) {
profiler.checkPoint(app, type, regexMeta);
if ( new RegExp('name=["\']' + meta + '["\']', 'i').test(match) ) {
content = match.toString().match(/content=("|')([^"']+)("|')/i);
parse(w.apps[app].meta[meta]).forEach(function(pattern) {
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, content[2], meta);
}
profiler.checkPoint(app, type, pattern.regex);
});
}
}
}
break;
case 'headers':
if ( typeof data[type] !== 'object' || !data[type] ) {
break;
}
for ( header in w.apps[app].headers ) {
parse(w.apps[app][type][header]).forEach(function(pattern) {
if ( typeof data[type][header.toLowerCase()] === 'string' && pattern.regex.test(data[type][header.toLowerCase()]) ) {
apps[app].setDetected(pattern, type, data[type][header.toLowerCase()], header);
}
profiler.checkPoint(app, type, pattern.regex);
});
}
break;
case 'env':
if ( typeof data[type] !== 'object' || !data[type] ) {
break;
}
parse(w.apps[app][type]).forEach(function(pattern) {
for ( i in data[type] ) {
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type, data[type][i]);
}
}
profiler.checkPoint(app, type, pattern.regex);
});
break;
}
}
}
w.log('[ profiler ] Tested ' + profiler.regexCount + ' regular expressions in ' + ( (new Date().getTime() - profiler.startTime) / 1000 ) + 's');
w.log('[ profiler ] Slowest pattern took ' + ( profiler.slowest.duration / 1000 ) + 's: ' + profiler.slowest.app + ' | ' + profiler.slowest.type + ' | ' + profiler.slowest.regex);
for ( app in apps ) {
if ( !apps[app].detected ) {
delete apps[app];
}
}
// Exclude app in detected apps only
for ( app in apps ) {
if (w.apps[app].excludes ) {
if ( typeof w.apps[app].excludes === 'string' ) {
w.apps[app].excludes = [ w.apps[app].excludes ];
}
w.apps[app].excludes.forEach(function(excluded) {
excludes.push(excluded);
});
}
}
// Remove excluded applications
for ( app in apps ) {
if ( excludes.indexOf(app) !== -1 ) {
delete apps[app];
}
}
// Implied applications
// Run several passes as implied apps may imply other apps
while ( checkImplies ) {
checkImplies = false;
for ( app in apps ) {
confidence = apps[app].confidence;
if ( w.apps[app] && w.apps[app].implies ) {
// Cast strings to an array
if ( typeof w.apps[app].implies === 'string' ) {
w.apps[app].implies = [ w.apps[app].implies ];
}
w.apps[app].implies.forEach(function(implied) {
implied = parse(implied)[0];
if ( !w.apps[implied.string] ) {
w.log('Implied application ' + implied.string + ' does not exist', 'warn');
return;
}
if ( !apps.hasOwnProperty(implied.string) ) {
apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true);
checkImplies = true;
}
// Apply app confidence to implied app
for ( id in confidence ) {
apps[implied.string].confidence[id + ' implied by ' + app] = confidence[id] * ( implied.confidence ? implied.confidence / 100 : 1 );
}
});
}
}
}
w.log(Object.keys(apps).length + ' apps detected: ' + Object.keys(apps).join(', ') + ' on ' + url);
// Keep history of detected apps
for ( app in apps ) {
confidence = apps[app].confidence;
version = apps[app].version;
// Per URL
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];
}
if ( w.detected[url][app].getConfidence() >= 100 ) {
// Per hostname
if ( /(www.)?((.+?)\.(([a-z]{2,3}\.)?[a-z]{2,6}))$/.test(hostname) && !/((local|dev(elopment)?|stag(e|ing)?|test(ing)?|demo(shop)?|admin|google|cache)\.|\/admin|\.local)/.test(url) ) {
if ( !w.ping.hostnames.hasOwnProperty(hostname) ) {
w.ping.hostnames[hostname] = { applications: {}, meta: {} };
}
if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) {
w.ping.hostnames[hostname].applications[app] = { hits: 0 };
}
w.ping.hostnames[hostname].applications[app].hits ++;
if ( version ) {
w.ping.hostnames[hostname].applications[app].version = version;
}
} else {
w.log('Ignoring hostname "' + hostname + '"');
}
}
}
// Additional information
if ( w.ping.hostnames.hasOwnProperty(hostname) ) {
if ( typeof data.html === 'string' && data.html ) {
match = data.html.match(/<html[^>]*[: ]lang="([a-z]{2}((-|_)[A-Z]{2})?)"/i);
if ( match && match.length ) {
w.ping.hostnames[hostname].meta['language'] = match[1];
}
regexMeta = /<meta[^>]+>/ig;
while ( match = regexMeta.exec(data.html) ) {
if ( !match.length ) {
continue;
}
match = match[0].match(/name="(author|copyright|country|description|keywords)"[^>]*content="([^"]+)"/i);
if ( match && match.length === 3 ) {
w.ping.hostnames[hostname].meta[match[1]] = match[2];
}
}
}
}
if ( Object.keys(w.ping.hostnames).length >= 20 ) {
driver('ping');
}
apps = null;
data = null;
driver('displayApps');
}
};
return w;
})();
// CommonJS package
// See http://wiki.commonjs.org/wiki/CommonJS
if ( typeof exports === 'object' ) {
exports.wappalyzer = wappalyzer;
}

@ -63,4 +63,5 @@ cat46 = Remote Access
cat47 = Development Tool
cat48 = Network Storage
cat49 = Feed Readers
cat50 = Document Management Systems
cat50 = Document Management Systems
cat51 = Landing Page Builder

@ -0,0 +1,67 @@
name = Wappalyzer
noAppsDetected = Δεν ανιχνεύθηκαν εφαρμογές
clickForDetails = Κάντε κλικ για λεπτομέρειες
preferences = Ρυθμίσεις
categories = Κατηγορίες
tracking_title = Παρακολούθηση
tracking_description = Ανώνυμη αποστολή αναφορών για εντοπισμένες εφαρμογές στο wappalyzer.com για έρευνα
urlbar_title = Προβολή εικονιδίων στη μπάρα διεύθυνσης
urlbar_description = Αποεπιλέξτε για να εμφανίσετε το κουμπί της εργαλειοθήκης.
feedback = Feedback
github = Github
twitter = Twitter
website = Πήγαινε στο wappalyzer.com
cat1 = CMS
cat2 = Διαδικτυακό Φόρουμ
cat3 = Διαχειριστής Βάσης Δεδομένων
cat4 = Εργαλείο Τεκμηρίωσης
cat5 = Widget
cat6 = eCommerce
cat7 = Gallery Φωτογραφιών
cat8 = Wiki
cat9 = Hosting Panel
cat10 = Analytics
cat11 = Blog
cat12 = Framework της JavaScript
cat13 = Πρόγραμμα Παρακολούθησης Προβλημάτων
cat14 = Πρόγραμμα αναπαραγωγής Βίντεο
cat15 = Σύστημα Σχολίων
cat16 = CAPTCHA
cat17 = Script Γραμματοσειράς
cat18 = Framework Διαδικτύου
cat19 = Διάφορα
cat20 = Επεξεργαστής Κειμένου
cat21 = LMS
cat22 = Διακομιστής Διαδικτύου
cat23 = Εργαλείο Μνήμης Cache
cat24 = Επεξεργαστής Εμπλουτισμένου Κειμένου
cat25 = Γραφικά Javascript
cat26 = Framework για Κινητά
cat27 = Γλώσσα Προγραμματισμού
cat28 = Λειτουργικό Σύστημα
cat29 = Μηχανή Αναζήτησης
cat30 = Web Mail
cat31 = CDN
cat32 = Αυτοματοποίηση Marketing
cat33 = Επέκταση Διακομιστή Διαδικτύου
cat34 = Βάση Δεδομένων
cat35 = Χάρτης
cat36 = Δίκτυο Διαφημίσεων
cat37 = Υπηρεσία Δικτύου
cat38 = Διακομιστής Πολυμέσων
cat39 = Διαδικτυακή κάμερα
cat40 = Εκτυπωτής
cat41 = Σύστημα Επεξεργασίας Πληρωμών
cat42 = Σύστημα Διαχείρισης Tags
cat43 = Paywall
cat44 = Σύστημα Build/CI
cat45 = Σύστημα SCADA
cat46 = Απομακρυσμένη Πρόσβαση
cat47 = Εργαλείο Ανάπτυξης
cat48 = Δικτυακός Αποθηκευτικός Χώρος
cat49 = Feed Readers
cat50 = Συστήματα Διαχειρίσης Εγγράφων
cat51 = Σύστημα Κατασκευής Σελίδων Υποδοχής

@ -63,4 +63,5 @@ cat46 = Remote Access
cat47 = Development Tool
cat48 = Network Storage
cat49 = Feed Readers
cat50 = Document Management Systems
cat50 = Document Management Systems
cat51 = Landing Page Builder

@ -63,4 +63,5 @@ cat46 = Remote Access
cat47 = Development Tool
cat48 = Network Storage
cat49 = Feed Readers
cat50 = Document Management Systems
cat50 = Document Management Systems
cat51 = Landing Page Builder

@ -63,4 +63,5 @@ cat46 = Remote Access
cat47 = Development Tool
cat48 = Network Storage
cat49 = Feed Readers
cat50 = Document Management Systems
cat50 = Document Management Systems
cat51 = Landing Page Builder

@ -63,4 +63,5 @@ cat46 = Accès à distance
cat47 = Outil de développement
cat48 = Stockage réseau
cat49 = Lecteur RSS
cat50 = Système de gestion de documents
cat50 = Système de gestion de documents
cat51 = Landing Page Builder

@ -0,0 +1,67 @@
name = Wappalyzer
noAppsDetected = Nessuna applicazione rilevata
clickForDetails = Clicca per i dettagli
preferences = Opzioni
categories = Categorie
tracking_title = Tracking
tracking_description = Inviare anonimamente un report sulle applicazioni rilevate a wappalyzer.com per l'analisi
urlbar_title = Mostra le icone nella barra delle URL
urlbar_description = Deselezionare per visualizzare il pulsante nella barra degli strumenti.
feedback = Feedback
github = Github
twitter = Twitter
website = Vai su wappalyzer.com
cat1 = CMS
cat2 = Forum
cat3 = Gestore di database
cat4 = Strumento di documentazione
cat5 = Widget
cat6 = eCommerce
cat7 = Galleria fotografica
cat8 = Wiki
cat9 = Pannello Hosting
cat10 = Analytics
cat11 = Blog
cat12 = Framework JavaScript
cat13 = Issue Tracker
cat14 = Player Video
cat15 = Sistema di commenti
cat16 = CAPTCHA
cat17 = Font Script
cat18 = Framework Web
cat19 = Miscellanea
cat20 = Editor
cat21 = LMS
cat22 = Web Server
cat23 = Cache Tool
cat24 = Editor di Testo Ricco
cat25 = Javascript Graphics
cat26 = Framework Mobile
cat27 = Linguaggio di Programmazione
cat28 = Sistema Operativo
cat29 = Motore di Ricerca
cat30 = Web Mail
cat31 = CDN
cat32 = Marketing Automation
cat33 = Estensione Web Server
cat34 = Database
cat35 = Mappa
cat36 = Network Pubblicitario
cat37 = Network Device
cat38 = Media Server
cat39 = Webcam
cat40 = Stampante
cat41 = Payment Processor
cat42 = Tag Manager
cat43 = Paywall
cat44 = Sistema Build/CI
cat45 = SCADA System
cat46 = Accesso Remoto
cat47 = Strumenti di Sviluppo
cat48 = Network Storage
cat49 = Lettore di Feed
cat50 = Sistema di Gestione Documenti
cat51 = Landing Page Builder

@ -63,4 +63,5 @@ cat46 = Remote Access
cat47 = Development Tool
cat48 = Network Storage
cat49 = Feed Readers
cat50 = Document Management Systems
cat50 = Document Management Systems
cat51 = Landing Page Builder

@ -60,4 +60,5 @@ cat46 = Remote Access
cat47 = Development Tool
cat48 = Network Storage
cat49 = Feed Readers
cat50 = Document Management Systems
cat50 = Document Management Systems
cat51 = Landing Page Builder

@ -8,8 +8,8 @@
"description": "Identifies software on the web",
"author": "Elbert Alias",
"license": "GPLv3",
"version": "3.0.15",
"main": "driver",
"version": "3.1.1",
"main": "driver.js",
"preferences": [{
"name": "tracking",
"title": "Tracking",

@ -0,0 +1,529 @@
/**
* Wappalyzer v2
*
* Created by Elbert Alias <elbert@alias.io>
*
* License: GPLv3 http://www.gnu.org/licenses/gpl-3.0.txt
*/
var wappalyzer = (function() {
//'use strict';
/**
* Application class
*/
var Application = function(app, detected) {
this.app = app;
this.confidence = {};
this.confidenceTotal = 0;
this.detected = Boolean(detected);
this.excludes = [];
this.version = '';
this.versions = [];
};
Application.prototype = {
/**
* Calculate confidence total
*/
getConfidence: function() {
var total = 0, id;
for ( id in this.confidence ) {
total += this.confidence[id];
}
return this.confidenceTotal = Math.min(total, 100);
},
/**
* Resolve version number (find the longest version number that contains all shorter detected version numbers)
*/
getVersion: function() {
var i, resolved;
if ( !this.versions.length ) {
return;
}
this.versions.sort(function(a, b) {
return a.length - b.length;
});
resolved = this.versions[0];
for ( i = 1; i < this.versions.length; i++ ) {
if ( this.versions[i].indexOf(resolved) === -1 ) {
break;
}
resolved = this.versions[i];
}
return this.version = resolved;
},
setDetected: function(pattern, type, value, key) {
this.detected = true;
// Set confidence level
this.confidence[type + ' ' + ( key ? key + ' ' : '' ) + pattern.regex] = pattern.confidence ? pattern.confidence : 100;
// Detect version number
if ( pattern.version ) {
var
version = pattern.version,
matches = pattern.regex.exec(value);
if ( matches ) {
matches.forEach(function(match, i) {
// Parse ternary operator
var ternary = new RegExp('\\\\' + i + '\\?([^:]+):(.*)$').exec(version);
if ( ternary && ternary.length === 3 ) {
w.log({ match: match, i: i, ternary: ternary });
version = version.replace(ternary[0], match ? ternary[1] : ternary[2]);
w.log({ version: version });
}
// Replace back references
version = version.replace(new RegExp('\\\\' + i, 'g'), match ? match : '');
});
if ( version && this.versions.indexOf(version) < 0 ) {
this.versions.push(version);
}
this.getVersion();
}
}
}
};
var Profiler = function() {
this.regexCount = 0;
this.startTime = new Date().getTime();
this.lastTime = new Date().getTime();
this.slowest = { duration: null, app: '', type: '', pattern: '' };
this.timedOut = false;
};
Profiler.prototype = {
checkPoint: function(app, type, regex) {
var duration = new Date().getTime() - this.lastTime;
if ( !this.slowest.duration || duration > this.slowest.duration ) {
this.slowest.duration = duration;
this.slowest.app = app;
this.slowest.type = type;
this.slowest.regex = regex;
}
this.regexCount++;
this.lastTime = new Date().getTime();
this.timedOut = this.lastTime - this.startTime > 1000;
}
};
/**
* Call driver functions
*/
var driver = function(func, args) {
if ( typeof w.driver[func] !== 'function' ) {
w.log('not implemented: w.driver.' + func, 'warn');
return;
}
if ( func !== 'log' ) {
w.log('w.driver.' + func);
}
return w.driver[func](args);
};
/**
* Parse apps.json patterns
*/
var parse = function(patterns) {
var
attrs,
parsed = [];
// Convert single patterns to an array
if ( typeof patterns === 'string' ) {
patterns = [ patterns ];
}
patterns.forEach(function(pattern) {
attrs = {};
pattern.split('\\;').forEach(function(attr, i) {
if ( i ) {
// Key value pairs
attr = attr.split(':');
if ( attr.length > 1 ) {
attrs[attr.shift()] = attr.join(':');
}
} else {
attrs.string = attr;
try {
attrs.regex = new RegExp(attr.replace('/', '\/'), 'i'); // Escape slashes in regular expression
} catch (e) {
attrs.regex = new RegExp();
w.log(e + ': ' + attr, 'error');
}
}
});
parsed.push(attrs);
});
return parsed;
};
/**
* Main script
*/
var w = {
apps: {},
cats: null,
ping: { hostnames: {} },
detected: {},
config: {
websiteURL: 'https://wappalyzer.com/',
twitterURL: 'https://twitter.com/Wappalyzer',
githubURL: 'https://github.com/AliasIO/Wappalyzer',
},
/**
* Log messages to console
*/
log: function(message, type) {
if ( type === undefined ) {
type = 'debug';
}
if ( typeof message === 'object' ) {
message = JSON.stringify(message);
}
driver('log', { message: '[wappalyzer ' + type + '] ' + message, type: type });
},
/**
* Initialize
*/
init: function() {
w.log('w.init');
// Checks
if ( w.driver === undefined ) {
w.log('no driver, exiting');
return;
}
// Initialize driver
driver('init');
},
/**
* Analyze the request
*/
analyze: function(hostname, url, data) {
var
i, j, app, confidence, type, regexMeta, regexScript, match, content, meta, header, version, id,
profiler = new Profiler(),
apps = {},
excludes = [],
checkImplies = true;
w.log('w.analyze');
// Remove hash from URL
data.url = url = url.split('#')[0];
if ( w.apps === undefined || w.categories === undefined ) {
w.log('apps.json not loaded, check for syntax errors');
return;
}
if ( w.detected[url] === undefined ) {
w.detected[url] = {};
}
for ( app in w.apps ) {
// Exit loop after one second to prevent CPU hogging
// Remaining patterns will not be evaluated
if ( profiler.timedOut ) {
w.log('Timeout, exiting loop');
break;
}
apps[app] = w.detected[url] && w.detected[url][app] ? w.detected[url][app] : new Application(app);
for ( type in w.apps[app] ) {
switch ( type ) {
case 'url':
parse(w.apps[app][type]).forEach(function(pattern) {
if ( pattern.regex.test(url) ) {
apps[app].setDetected(pattern, type, url);
}
profiler.checkPoint(app, type, pattern.regex);
});
break;
case 'html':
if ( typeof data[type] !== 'string' || !data.html ) {
break;
}
parse(w.apps[app][type]).forEach(function(pattern) {
if ( pattern.regex.test(data[type]) ) {
apps[app].setDetected(pattern, type, data[type]);
}
profiler.checkPoint(app, type, pattern.regex);
});
break;
case 'script':
if ( typeof data.html !== 'string' || !data.html ) {
break;
}
regexScript = new RegExp('<script[^>]+src=("|\')([^"\']+)', 'ig');
parse(w.apps[app][type]).forEach(function(pattern) {
while ( match = regexScript.exec(data.html) ) {
if ( pattern.regex.test(match[2]) ) {
apps[app].setDetected(pattern, type, match[2]);
}
}
profiler.checkPoint(app, type, pattern.regex);
});
break;
case 'meta':
if ( typeof data.html !== 'string' || !data.html ) {
break;
}
regexMeta = /<meta[^>]+>/ig;
while ( match = regexMeta.exec(data.html) ) {
for ( meta in w.apps[app][type] ) {
profiler.checkPoint(app, type, regexMeta);
if ( new RegExp('name=["\']' + meta + '["\']', 'i').test(match) ) {
content = match.toString().match(/content=("|')([^"']+)("|')/i);
parse(w.apps[app].meta[meta]).forEach(function(pattern) {
if ( content && content.length === 4 && pattern.regex.test(content[2]) ) {
apps[app].setDetected(pattern, type, content[2], meta);
}
profiler.checkPoint(app, type, pattern.regex);
});
}
}
}
break;
case 'headers':
if ( typeof data[type] !== 'object' || !data[type] ) {
break;
}
for ( header in w.apps[app].headers ) {
parse(w.apps[app][type][header]).forEach(function(pattern) {
if ( typeof data[type][header.toLowerCase()] === 'string' && pattern.regex.test(data[type][header.toLowerCase()]) ) {
apps[app].setDetected(pattern, type, data[type][header.toLowerCase()], header);
}
profiler.checkPoint(app, type, pattern.regex);
});
}
break;
case 'env':
if ( typeof data[type] !== 'object' || !data[type] ) {
break;
}
parse(w.apps[app][type]).forEach(function(pattern) {
for ( i in data[type] ) {
if ( pattern.regex.test(data[type][i]) ) {
apps[app].setDetected(pattern, type, data[type][i]);
}
}
profiler.checkPoint(app, type, pattern.regex);
});
break;
}
}
}
w.log('[ profiler ] Tested ' + profiler.regexCount + ' regular expressions in ' + ( (new Date().getTime() - profiler.startTime) / 1000 ) + 's');
w.log('[ profiler ] Slowest pattern took ' + ( profiler.slowest.duration / 1000 ) + 's: ' + profiler.slowest.app + ' | ' + profiler.slowest.type + ' | ' + profiler.slowest.regex);
for ( app in apps ) {
if ( !apps[app].detected ) {
delete apps[app];
}
}
// Exclude app in detected apps only
for ( app in apps ) {
if (w.apps[app].excludes ) {
if ( typeof w.apps[app].excludes === 'string' ) {
w.apps[app].excludes = [ w.apps[app].excludes ];
}
w.apps[app].excludes.forEach(function(excluded) {
excludes.push(excluded);
});
}
}
// Remove excluded applications
for ( app in apps ) {
if ( excludes.indexOf(app) !== -1 ) {
delete apps[app];
}
}
// Implied applications
// Run several passes as implied apps may imply other apps
while ( checkImplies ) {
checkImplies = false;
for ( app in apps ) {
confidence = apps[app].confidence;
if ( w.apps[app] && w.apps[app].implies ) {
// Cast strings to an array
if ( typeof w.apps[app].implies === 'string' ) {
w.apps[app].implies = [ w.apps[app].implies ];
}
w.apps[app].implies.forEach(function(implied) {
implied = parse(implied)[0];
if ( !w.apps[implied.string] ) {
w.log('Implied application ' + implied.string + ' does not exist', 'warn');
return;
}
if ( !apps.hasOwnProperty(implied.string) ) {
apps[implied.string] = w.detected[url] && w.detected[url][implied.string] ? w.detected[url][implied.string] : new Application(implied.string, true);
checkImplies = true;
}
// Apply app confidence to implied app
for ( id in confidence ) {
apps[implied.string].confidence[id + ' implied by ' + app] = confidence[id] * ( implied.confidence ? implied.confidence / 100 : 1 );
}
});
}
}
}
w.log(Object.keys(apps).length + ' apps detected: ' + Object.keys(apps).join(', ') + ' on ' + url);
// Keep history of detected apps
for ( app in apps ) {
confidence = apps[app].confidence;
version = apps[app].version;
// Per URL
w.detected[url][app] = apps[app];
for ( id in confidence ) {
w.detected[url][app].confidence[id] = confidence[id];
}
if ( w.detected[url][app].getConfidence() >= 100 ) {
// Per hostname
if ( /(www.)?((.+?)\.(([a-z]{2,3}\.)?[a-z]{2,6}))$/.test(hostname) && !/((local|dev(elopment)?|stag(e|ing)?|test(ing)?|demo(shop)?|admin|google|cache)\.|\/admin|\.local)/.test(url) ) {
if ( !w.ping.hostnames.hasOwnProperty(hostname) ) {
w.ping.hostnames[hostname] = { applications: {}, meta: {} };
}
if ( !w.ping.hostnames[hostname].applications.hasOwnProperty(app) ) {
w.ping.hostnames[hostname].applications[app] = { hits: 0 };
}
w.ping.hostnames[hostname].applications[app].hits ++;
if ( version ) {
w.ping.hostnames[hostname].applications[app].version = version;
}
} else {
w.log('Ignoring hostname "' + hostname + '"');
}
}
}
// Additional information
if ( w.ping.hostnames.hasOwnProperty(hostname) ) {
if ( typeof data.html === 'string' && data.html ) {
match = data.html.match(/<html[^>]*[: ]lang="([a-z]{2}((-|_)[A-Z]{2})?)"/i);
if ( match && match.length ) {
w.ping.hostnames[hostname].meta['language'] = match[1];
}
regexMeta = /<meta[^>]+>/ig;
while ( match = regexMeta.exec(data.html) ) {
if ( !match.length ) {
continue;
}
match = match[0].match(/name="(author|copyright|country|description|keywords)"[^>]*content="([^"]+)"/i);
if ( match && match.length === 3 ) {
w.ping.hostnames[hostname].meta[match[1]] = match[2];
}
}
}
}
if ( Object.keys(w.ping.hostnames).length >= 20 ) {
driver('ping');
}
apps = null;
data = null;
driver('displayApps');
}
};
return w;
})();
// CommonJS package
// See http://wiki.commonjs.org/wiki/CommonJS
if ( typeof exports === 'object' ) {
exports.wappalyzer = wappalyzer;
}

@ -1,78 +1,145 @@
# Wappalyzer
This is npm module for wappalyzer
npm install wappalyzer
var wappalyzer = require("wappalyzer");
var options={
url : "http://codelanka.github.io/Presentation-Engines",
hostname:"codelanka.github.io",
debug:false
}
wappalyzer.detectFromUrl(options,function (err,apps,appInfo) {
console.log(err,apps,appInfo);
})
####Output
null [ 'AngularJS',
'Font Awesome',
'Google Font API',
'jQuery',
'Twitter Bootstrap' ] { AngularJS:
{ app: 'AngularJS',
confidence:
{ 'script //([\\d.]+(\\-?rc[.\\d]*)*)/angular(\\.min)?\\.js/i': 100,
'script /angular.*\\.js/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '1.3.5',
versions: [ '1.3.5' ] },
'Font Awesome':
{ app: 'Font Awesome',
confidence: { 'html /<link[^>]* href=[^>]+font-awesome(?:\\.min)?\\.css/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: [] },
'Google Font API':
{ app: 'Google Font API',
confidence: { 'html /<link[^>]* href=[^>]+fonts\\.(?:googleapis|google)\\.com/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: [] },
jQuery:
{ app: 'jQuery',
confidence: { 'script /jquery.*\\.js/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: [] },
'Twitter Bootstrap':
{ app: 'Twitter Bootstrap',
confidence:
{ 'script /(?:twitter\\.github\\.com/bootstrap|bootstrap(?:\\.js|\\.min\\.js))/i': 100,
'html /<link.+?href="[^"]+bootstrap(?:\\.min)?\\.css/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: [] } }
Wappalyzer Author - Elbert Alias
## Install
Install wappalyzer from NPM with:
```bash
npm install wappalyzer
```
## Quickstart
```javascript
// load in the lib
var wappalyzer = require("wappalyzer");
// set our options
var options={
url : "http://codelanka.github.io/Presentation-Engines",
hostname:"codelanka.github.io",
debug:false
}
// detect from the url directly, library will make a request
wappalyzer.detectFromUrl(options,function (err,apps,appInfo) {
// output for the test
console.dir(apps);
console.dir(appInfo);
})
// sample data
var data = {
url: options.url,
headers: {
test: 1
},
html: '<p>HTML CONTENT OF PAGE HERE</p>'
};
// detect from content you have already
wappalyzer.detectFromHTML(options,function (err,apps,appInfo) {
// output for the test
console.dir(apps);
console.log(appInfo);
})
```
### Output from QuickStart
```javascript
// Apps
[
'CloudFlare',
'Font Awesome',
'Google Maps',
'Modernizr',
'Nginx',
'RequireJS',
'jQuery'
]
// Detailed info on links
{
CloudFlare: {
app: 'CloudFlare',
confidence: { 'headers Server /cloudflare/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: []
},
'Font Awesome': {
app: 'Font Awesome',
confidence: { 'html /<link[^>]* href=[^>]+font-awesome(?:\.min)?\.css/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: []
},
'Google Maps': {
app: 'Google Maps',
confidence: { 'script ///maps.googleapis.com/maps/api/js/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: []
},
'Modernizr': {
app: 'Modernizr',
confidence: { 'script /modernizr(?:-([\d.]*[\d]))?.*\.js/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '2.6.2',
versions: [ '2.6.2' ]
},
'Nginx': {
app: 'Nginx',
confidence: { 'headers Server /nginx(?:/([\d.]+))?/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: []
},
'RequireJS': {
app: 'RequireJS',
confidence: { 'script /require.*\.js/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '',
versions: []
},
'jQuery': {
app: 'jQuery',
confidence:
{ 'script //([\d.]+)/jquery(\.min)?\.js/i': 100,
'script /jquery.*\.js/i': 100 },
confidenceTotal: 100,
detected: true,
excludes: [],
version: '1.10.1',
versions: [ '1.10.1' ]
}
}
```
## Credits
### Wappalyzer Author - Elbert Alias
[Wappalyzer](https://wappalyzer.com/) is a
[cross-platform](https://github.com/AliasIO/Wappalyzer/wiki/Drivers) utility that uncovers the
@ -89,8 +156,17 @@ Refer to the [wiki](https://github.com/AliasIO/Wappalyzer/wiki) for
[contribute](https://github.com/AliasIO/Wappalyzer/wiki/Contributing) and
[more](https://github.com/AliasIO/Wappalyzer/wiki/_pages).
### NPM Module
* [Pasindu De Silva](https://github.com/pasindud) - Initial version with tests
* [Johann du Toit](http://johanndutoit.net) from [Passmarked](http://passmarked.com) - Updated to support just passing data and helped publish to NPMJS
## License
*Licensed under the [GPL](https://github.com/AliasIO/Wappalyzer/blob/master/LICENSE).*
## Donations
Donate Bitcoin: 16gb4uGDAjaeRJwKVmKr2EXa8x2fmvT8EQ - *Thanks!*
![QR Code](https://wappalyzer.com/sites/default/themes/wappalyzer/images/bitcoinqrcode.png)

@ -4,26 +4,65 @@ var request = require('request');
var fs = require('fs');
var path = require('path');
//TODO
exports.detectFromHTML = function(options) {};
/**
* Does the actual detection with information passed
**/
exports.detect = function(options, data, cb) {
// run the wrapper function that will
// trigger the actual library to run
runWrappalyer(options, data, cb);
};
/**
* Wraps the detect method, just kept to reuse old method names
* and not break anything. Although this was just stubbed out.
**/
exports.detectFromHTML = function(options, data, cb) {
// run the detect method
exports.detect(options, data, cb);
};
/**
* Do a actual request for the body & headers, then
* run through detection
**/
exports.detectFromUrl = function(options, cb) {
var url = options.url;
// ensure options and url were
if(!options || !options.url) {
if (options.debug) {
console.log('Fetching the page');
}
// send back a error ...
cb(new Error("\"url\" is a required option to run"
+ " wappalyzer and get the page content"))
getHTMLFromUrl(url, function(err, data) {
if (err || data === null) {
cb(err, null);
} else {
runWrappalyer(options, data, function(err, detected, appInfo) {
cb(null, detected, appInfo);
});
}
});
} else {
// local variables to
var url = options.url;
// get the body content from the url
getHTMLFromUrl(url, function(err, data) {
// check for error or if we got no data back
if (err || data === null) {
// handle the error and don't do anything else ..
cb(err, null);
} else {
// run actual detection
exports.detect(options, data, cb);
}
});
}
};
function getHTMLFromUrl(url, cb) {
@ -42,7 +81,20 @@ function getHTMLFromUrl(url, cb) {
}
function getAppsJson(cb) {
fs.readFile(path.resolve(__dirname, 'apps.json'), 'utf8', function(err, data) {
// depending on evironment select a direction to the path
var appsFileStr = path.resolve(__dirname, './apps.json');
// handle the environment variable if it's there
if(process.env.NODE_ENV == 'testing') {
// set the apps.json to testing stage
appsFileStr = path.resolve(__dirname, '../../apps.json');
}
// read in the file
fs.readFile(appsFileStr, 'utf8', function(err, data) {
if (err) throw err;
return cb(null, JSON.parse(data));
});
@ -51,7 +103,20 @@ function getAppsJson(cb) {
function runWrappalyer(options, data, cb) {
var debug = options.debug || false;
var wappalyzer = require('./wappalyzer').wappalyzer;
// according to environment check it
var wappalyzer = null;
// change depending on the environment
if( process.env.NODE_ENV == 'testing' ) {
wappalyzer = require('../../wappalyzer').wappalyzer;
} else {
wappalyzer = require('./wappalyzer').wappalyzer;
}
getAppsJson(function(err, apps) {
var w = wappalyzer;
w.driver = {

@ -1,19 +1,30 @@
{
"name": "wappalyzer",
"version": "2.0.2",
"version": "2.0.3",
"description": "NPM Module that uncovers the technologies used on websites",
"main": "index.js",
"scripts": {
"test": "mocha -t 15000"
"test": "NODE_ENV=testing mocha -t 15000"
},
"repository": {
"type": "git",
"url": "https://github.com/AliasIO/Wappalyzer"
},
"keywords": [
"wappalyzer"
"wappalyzer",
"detect",
"stack",
"technologies"
],
"author": "Pasindu De Silva",
"contributors": [
{
"name": "Pasindu De Silva"
},
{
"name": "Johann du Toit"
}
],
"author": "Elbert Alias",
"license": "GPLv3",
"bugs": {
"url": "https://github.com/AliasIO/Wappalyzer/issues"

@ -0,0 +1,20 @@
{
"Date":"Fri, 17 Jul 2015 11:05:08 GMT",
"Content-Encoding":"gzip",
"Age":"0",
"X-Cache":"MISS",
"Connection":"keep-alive",
"Content-Length":"1940",
"Via":"1.1 varnish",
"X-Served-By":"cache-lcy1122-LCY",
"Last-Modified":"Thu, 16 Apr 2015 14:24:18 GMT",
"Server":"GitHub.com",
"X-Timer":"S1437131108.300792,VS0,VE84",
"Vary":"Accept-Encoding",
"Content-Type":"text/html; charset=utf-8",
"Access-Control-Allow-Origin":"*",
"Expires":"Fri, 17 Jul 2015 11:10:54 GMT",
"Cache-Control":"max-age=600",
"Accept-Ranges":"bytes",
"X-Cache-Hits":"0"
}

@ -0,0 +1,149 @@
<!DOCTYPE html>
<html lang="en" ng-app="presen" >
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Preso Engines | CodeLanka</title>
<!-- Bootstrap CSS -->
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script src="//code.jquery.com/jquery.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<link href='//fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css'>
<link href="css/style.css" rel="stylesheet">
<script type="text/javascript">
$(function () {
"use strict";
var $bgobj = $(".ha-bg-parallax"); // assigning the object
$(window).on("scroll", function () {
var yPos = -($(window).scrollTop() / $bgobj.data('speed'));
// Put together our final background position
var coords = '100% ' + yPos + 'px';
// Move the background
$bgobj.css({ backgroundPosition: coords });
});
$('div.product-chooser').not('.disabled').find('div.product-chooser-item').on('click', function(){
$(this).parent().parent().find('div.product-chooser-item').removeClass('selected');
$(this).addClass('selected');
$(this).find('input[type="radio"]').prop("checked", true);
});
});
</script>
</head>
<body>
<div class="container-fluid">
<div>
<div class="ha-bg-parallax text-center block-marginb-none" data-type="background" data-speed="20">
<div class="ha-parallax-body">
<div class="ha-content ha-content-whitecolor">
<h1 id="headernav">Preso Engines</h1>
"Presentation Engines"
</div>
<div class="ha-parallax-divider-wrapper">
<span class="ha-diamond-divider-md img-responsive"></span>
</div>
<div class="ha-heading-parallax">By | CodeLanka</div>
</div>
</div>
<div class="container" ng-controller="presentationController">
<h2></h2>
<div class="row form-group product-chooser">
<div class="col-xs-12 col-sm-12 col-md-4 col-lg-4"
ng-repeat="presentation in presentations">
<div class="product-chooser-item">
<div class="col-xs-8 col-sm-8 col-md-12 col-lg-12">
<hr/>
<span class="title">
{{presentation.name}}
</span>
<span class="website">
<a href="{{presentation.website}}">{{presentation.website}}</a>
</span>
<span class="description">
{{presentation.description}}</span>
<input type="radio" name="product" value="mobile_desktop"
checked="checked">
<hr/>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4 text-center">
<i class="fa fa-star"></i>
<h2>{{presentation.stargazers_count}}</h2>
</div>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4 text-center">
<i class="fa fa-users"></i>
<h2>{{presentation.watchers_count}}</h2>
</div>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4 text-center">
<i class="fa fa-bug"></i>
<h2>{{presentation.open_issues_count}}</h2>
</div>
<div class="clear"></div>
<hr>
<p>Github -
<a href="http://github.com/{{presentation.github}}">{{presentation.github}}</a>
</p>
<p>Demo -
<a href="{{presentation.demo}}">{{presentation.demo}}</a>
</p>
<p>License - {{presentation.license}} </p>
<p>Language - {{presentation.language}} </p>
<hr/>
</div>
<div class="clear"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- jQuery -->
<!-- Bootstrap JavaScript -->
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script>
var phonecatApp = angular.module('presen', []);
phonecatApp.controller('presentationController', function ($scope,$http) {
var github = "https://api.github.com/repos/";
$http.get('data.json').
success(function(data, status, headers, config) {
$scope.presentations=data.engines;
for (var i = data.engines.length - 1; i >= 0; i--) {
$scope.presentations[i].stargazers_count=0;
$scope.presentations[i].watchers_count=0;
$scope.presentations[i].open_issues_count=0;
(function(no){
var githuburl = github+data.engines[no].github;
$http.get(githuburl)
.success(function(data, status, headers, config) {
$scope.presentations[no].stargazers_count=data.stargazers_count;
$scope.presentations[no].watchers_count=data.watchers_count;
$scope.presentations[no].open_issues_count=data.open_issues_count;
})
.error(function(data, status, headers, config) {});
}(i));
};
}).
error(function(data, status, headers, config) {});
});
</script>
</body>
</html>

@ -1,4 +1,5 @@
var assert = require("assert")
var assert = require("assert")
var fs = require('fs')
describe('wappalyzer', function(){
describe('detectFromUrl', function(){
@ -24,4 +25,41 @@ describe('wappalyzer', function(){
})
})
describe('detectFromHTML', function(){
it('should have the expected apps detected when passed raw info', function(done){
var wappalyzer = require("../index");
var expect = ['AngularJS','Font Awesome','Google Font API','Twitter Bootstrap','jQuery'];
var options={
url : "http://codelanka.github.io/Presentation-Engines",
hostname:"codelanka.github.io",
debug:false
}
var data = {
url: options.url,
headers: require('./sample.headers.json'),
html: fs.readFileSync('./test/sample.html').toString(),
headers: {
headers: {}
}
};
wappalyzer.detectFromHTML(options, data, function (err,apps) {
assert.equal(expect[0], apps[0]);
assert.equal(expect[1], apps[1]);
assert.equal(expect[2], apps[2]);
assert.equal(expect[3], apps[3]);
done();
})
})
})
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -506,8 +506,6 @@ var wappalyzer = (function() {
}
}
}
//w.log({ hostname: hostname, ping: w.ping.hostnames[hostname] });
}
if ( Object.keys(w.ping.hostnames).length >= 20 ) {

Loading…
Cancel
Save