parent
14c537fbc0
commit
9e9555ecdc
@ -1,19 +1,9 @@
|
||||
.vagrant
|
||||
|
||||
build/*
|
||||
|
||||
drivers/npm/node_modules
|
||||
drivers/npm/npm-debug.log
|
||||
|
||||
src/icons/converted/*
|
||||
|
||||
package.json
|
||||
node_modules/
|
||||
node_modules
|
||||
npm-debug.log
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
|
||||
!.gitkeep
|
||||
|
@ -1,4 +0,0 @@
|
||||
apps.json
|
||||
images/icons/*.png
|
||||
images/icons/*.svg
|
||||
js/wappalyzer.js
|
Before Width: | Height: | Size: 9.5 KiB |
@ -1,30 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Wappalyzer</title>
|
||||
|
||||
<link rel="icon" type="image/png" href="images/icon.png"/>
|
||||
|
||||
<script type="text/javascript" src="js/wappalyzer.js"></script>
|
||||
<script type="text/javascript" src="js/driver.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family: Verdana, Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#apps {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
#apps img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="apps"></div>
|
||||
</body>
|
||||
</html>
|
@ -1,67 +0,0 @@
|
||||
(function() {
|
||||
if ( wappalyzer == null ) { return };
|
||||
|
||||
var w = wappalyzer;
|
||||
|
||||
w.driver = {
|
||||
/**
|
||||
* Log messages to console
|
||||
*/
|
||||
log: function(args) {
|
||||
if ( console != null ) { console[args.type](args.message) };
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
init: function() {
|
||||
// Load apps.json
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open('GET', 'apps.json', true);
|
||||
|
||||
xhr.overrideMimeType('application/json');
|
||||
|
||||
xhr.onload = function() {
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
|
||||
w.categories = json.categories;
|
||||
w.apps = json.apps;
|
||||
|
||||
window.document.addEventListener('DOMContentLoaded', function() {
|
||||
w.analyze('google.com', 'http://google.com', {
|
||||
html: '<script src="jquery.js"><meta name="generator" content="WordPress"/>',
|
||||
headers: { 'Server': 'Apache' },
|
||||
env: [ 'Mootools' ]
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
xhr.send(null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Display apps
|
||||
*/
|
||||
displayApps: function() {
|
||||
var
|
||||
app,
|
||||
url = Object.keys(w.detected)[0];
|
||||
|
||||
document.getElementById('apps').innerHTML = '';
|
||||
|
||||
for ( app in w.detected[url] ) {
|
||||
document.getElementById('apps').innerHTML += '<img src="images/icons/' + w.apps[app].icon + '" width="16" height="16"/> ' + app + '<br/>';
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Go to URL
|
||||
*/
|
||||
goToURL: function(args) {
|
||||
window.open(args.url);
|
||||
}
|
||||
};
|
||||
|
||||
w.init();
|
||||
})();
|
@ -1,14 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{js,py}]
|
||||
charset = utf-8
|
||||
|
||||
[*.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
@ -1,3 +0,0 @@
|
||||
wappalyzer.js
|
||||
apps.json
|
||||
node_modules/
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"node" : true,
|
||||
"browser" : "false",
|
||||
"predef": []
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
# Wappalyzer
|
||||
|
||||
## 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
|
||||
technologies used on websites. It detects
|
||||
[content management systems](https://wappalyzer.com/categories/cms),
|
||||
[eCommerce platforms](https://wappalyzer.com/categories/ecommerce),
|
||||
[web servers](https://wappalyzer.com/categories/web-servers),
|
||||
[JavaScript frameworks](https://wappalyzer.com/categories/javascript-frameworks),
|
||||
[analytics tools](https://wappalyzer.com/categories/analytics) and
|
||||
[many more](https://wappalyzer.com/applications).
|
||||
|
||||
Refer to the [wiki](https://github.com/AliasIO/Wappalyzer/wiki) for
|
||||
[screenshots](https://github.com/AliasIO/Wappalyzer/wiki/Screenshots), information on how to
|
||||
[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)
|
@ -1,11 +0,0 @@
|
||||
var wappalyzer = require("./index");
|
||||
|
||||
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);
|
||||
})
|
@ -1,151 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var request = require('request');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
// ensure options and url were
|
||||
if(!options || !options.url) {
|
||||
|
||||
// send back a error ...
|
||||
cb(new Error("\"url\" is a required option to run"
|
||||
+ " wappalyzer and get the page content"))
|
||||
|
||||
} 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) {
|
||||
request(url, function(error, response, body) {
|
||||
if (!error && response.statusCode == 200) {
|
||||
var data = {
|
||||
html: body,
|
||||
url: url,
|
||||
headers: response.headers
|
||||
};
|
||||
cb(null, data);
|
||||
} else {
|
||||
cb(error, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getAppsJson(cb) {
|
||||
|
||||
// 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));
|
||||
});
|
||||
}
|
||||
|
||||
function runWrappalyer(options, data, cb) {
|
||||
var debug = options.debug || false;
|
||||
|
||||
// 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 = {
|
||||
log: function(args) {
|
||||
if (debug) {
|
||||
console.log(args.message);
|
||||
}
|
||||
},
|
||||
|
||||
init: function() {
|
||||
w.categories = apps.categories;
|
||||
w.apps = apps.apps;
|
||||
},
|
||||
displayApps: function() {
|
||||
var app, url = Object.keys(w.detected)[0];
|
||||
var detectedApps = [];
|
||||
|
||||
for (app in w.detected[url]) {
|
||||
detectedApps.push(app);
|
||||
|
||||
if (debug) {
|
||||
console.log(app);
|
||||
}
|
||||
}
|
||||
cb(null, detectedApps, w.detected[url]);
|
||||
}
|
||||
};
|
||||
w.init();
|
||||
w.detected = [];
|
||||
w.analyze(options.hostname, options.url, data);
|
||||
});
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "wappalyzer",
|
||||
"version": "2.0.3",
|
||||
"description": "NPM Module that uncovers the technologies used on websites",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "NODE_ENV=testing mocha -t 15000"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AliasIO/Wappalyzer"
|
||||
},
|
||||
"keywords": [
|
||||
"wappalyzer",
|
||||
"detect",
|
||||
"stack",
|
||||
"technologies"
|
||||
],
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Pasindu De Silva"
|
||||
},
|
||||
{
|
||||
"name": "Johann du Toit"
|
||||
}
|
||||
],
|
||||
"author": "Elbert Alias",
|
||||
"license": "GPLv3",
|
||||
"bugs": {
|
||||
"url": "https://github.com/AliasIO/Wappalyzer/issues"
|
||||
},
|
||||
"homepage": "https://github.com/AliasIO/Wappalyzer",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"dependencies": {
|
||||
"request": "^2.51.0"
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
|
||||
<!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,65 +0,0 @@
|
||||
var assert = require("assert")
|
||||
var fs = require('fs')
|
||||
|
||||
describe('wappalyzer', function(){
|
||||
describe('detectFromUrl', function(){
|
||||
it('should have the expected apps detected', 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
|
||||
}
|
||||
|
||||
wappalyzer.detectFromUrl(options,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();
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
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();
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
})
|
@ -1,30 +1,31 @@
|
||||
FROM phusion/baseimage
|
||||
FROM ubuntu:latest
|
||||
|
||||
MAINTAINER Elbert Alias <elbert@alias.io>
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
RUN sed -i 's/archive\.ubuntu\.com/au.archive.ubuntu.com/g' /etc/apt/sources.list
|
||||
|
||||
RUN \
|
||||
apt-get update && apt-get install -y \
|
||||
bzip2 \
|
||||
libfreetype6 \
|
||||
libfontconfig \
|
||||
nodejs \
|
||||
npm \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
WORKDIR /usr/local
|
||||
RUN ln -s $(which nodejs) /usr/bin/node
|
||||
|
||||
# PhantomJS
|
||||
RUN \
|
||||
mkdir phantomjs && \
|
||||
curl -L https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.8-linux-x86_64.tar.bz2 | tar xvjC phantomjs --strip 1
|
||||
RUN mkdir /usr/local/wappalyzer
|
||||
|
||||
# Wappalyzer
|
||||
RUN \
|
||||
mkdir wappalyzer && \
|
||||
curl -sSL https://github.com/AliasIO/Wappalyzer/archive/master.tar.gz | tar xzC wappalyzer --strip 1
|
||||
WORKDIR /usr/local/wappalyzer
|
||||
|
||||
RUN wappalyzer/bin/wappalyzer-links wappalyzer
|
||||
ADD apps.json .
|
||||
ADD driver.js .
|
||||
ADD index.js .
|
||||
ADD package.json .
|
||||
ADD wappalyzer.js .
|
||||
|
||||
WORKDIR wappalyzer/src/drivers/phantomjs
|
||||
RUN npm i
|
||||
|
||||
ENTRYPOINT ["/usr/local/phantomjs/bin/phantomjs", "--load-images=false", "--ignore-ssl-errors=yes", "--ssl-protocol=any", "driver.js"]
|
||||
ENTRYPOINT ["node", "index.js"]
|
||||
|
@ -0,0 +1,57 @@
|
||||
# Wappalyzer
|
||||
|
||||
[Wappalyzer](https://wappalyzer.com/) is a
|
||||
[cross-platform](https://github.com/AliasIO/Wappalyzer/wiki/Drivers) utility that uncovers the
|
||||
technologies used on websites. It detects
|
||||
[content management systems](https://wappalyzer.com/categories/cms),
|
||||
[eCommerce platforms](https://wappalyzer.com/categories/ecommerce),
|
||||
[web servers](https://wappalyzer.com/categories/web-servers),
|
||||
[JavaScript frameworks](https://wappalyzer.com/categories/javascript-frameworks),
|
||||
[analytics tools](https://wappalyzer.com/categories/analytics) and
|
||||
[many more](https://wappalyzer.com/applications).
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
$ npm i wappalyzer
|
||||
```
|
||||
|
||||
|
||||
## Run from the command line
|
||||
|
||||
```shell
|
||||
$ node index.js https://wappalyzer.com --quiet
|
||||
```
|
||||
|
||||
|
||||
## Run from a script
|
||||
|
||||
```javascript
|
||||
const wappalyzer = require('@wappalyzer/wappalyzer');
|
||||
|
||||
wappalyzer.run(['https://wappalyzer.com', '--quiet'], function(stdout, stderr) {
|
||||
if ( stdout ) {
|
||||
process.stdout.write(stdout);
|
||||
}
|
||||
|
||||
if ( stderr ) {
|
||||
process.stderr.write(stderr);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Arguments
|
||||
|
||||
**-v, --verbose**
|
||||
|
||||
Display debug output.
|
||||
|
||||
**-q, --quiet**
|
||||
|
||||
Suppress errors.
|
||||
|
||||
**--resource-timeout=ms**
|
||||
|
||||
Abort the connection after 'ms' milliseconds.
|
@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
const
|
||||
path = require('path'),
|
||||
spawn = require('child_process').spawn,
|
||||
phantomjs = require('phantomjs-prebuilt');
|
||||
|
||||
exports.run = function(args, callback) {
|
||||
args.push.apply(['--web-security=no', '--load-images=false', '--ignore-ssl-errors=yes', '--ssl-protocol=any']);
|
||||
|
||||
var driver = phantomjs.exec('driver.js', args);
|
||||
|
||||
driver.stdout.on('data', (data) => {
|
||||
callback(`${data}`, null);
|
||||
});
|
||||
|
||||
driver.stderr.on('data', (data) => {
|
||||
callback(null, `${data}`);
|
||||
});
|
||||
}
|
||||
|
||||
if ( !module.parent ) {
|
||||
exports.run(process.argv.slice(2), function(stdout, stderr) {
|
||||
if ( stdout ) {
|
||||
process.stdout.write(stdout);
|
||||
}
|
||||
|
||||
if ( stderr ) {
|
||||
process.stderr.write(stderr);
|
||||
}
|
||||
});
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "wappalyzer",
|
||||
"description": "Uncovers the technologies used on websites",
|
||||
"homepage": "https://github.com/AliasIO/Wappalyzer",
|
||||
"version": "3.0.3",
|
||||
"author": "Elbert Alias",
|
||||
"license": "GPL-3.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AliasIO/Wappalyzer"
|
||||
},
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"apps.json",
|
||||
"driver.js",
|
||||
"wappalyzer.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"phantomjs-prebuilt": "*"
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
js/wappalyzer.js
|
||||
apps.json
|
@ -1,193 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Wappalyzer
|
||||
{
|
||||
public
|
||||
$debug = false,
|
||||
$curlUserAgent = 'Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1',
|
||||
$curlFollowLocation = true,
|
||||
$curlTimeout = 5,
|
||||
$curlMaxRedirects = 3
|
||||
;
|
||||
|
||||
protected
|
||||
$v8,
|
||||
$apps,
|
||||
$categories
|
||||
;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($url)
|
||||
{
|
||||
chdir(dirname(__FILE__));
|
||||
|
||||
$this->v8 = new V8Js();
|
||||
|
||||
$this->url = $url;
|
||||
|
||||
$json = json_decode(file_get_contents('apps.json'));
|
||||
|
||||
$this->apps = $json->apps;
|
||||
$this->categories = $json->categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze a website
|
||||
* @param string $url
|
||||
*/
|
||||
public function analyze()
|
||||
{
|
||||
try {
|
||||
$this->load(array('wappalyzer.js', 'driver.js'));
|
||||
|
||||
$result = $this->curl($this->url);
|
||||
|
||||
//$env = $this->executeScripts($result);
|
||||
|
||||
$json = json_encode(array(
|
||||
'host' => $result->host,
|
||||
'url' => $result->url,
|
||||
'html' => $result->html,
|
||||
'headers' => $result->headers,
|
||||
//'env' => $env
|
||||
));
|
||||
|
||||
$result = $this->v8->executeString('
|
||||
w.apps = ' . json_encode($this->apps) . ';
|
||||
w.categories = ' . json_encode($this->categories) . ';
|
||||
w.driver.debug = ' . ( $this->debug ? 'true' : 'false' ) . ';
|
||||
w.driver.data = ' . $json . ';
|
||||
|
||||
w.driver.init();
|
||||
');
|
||||
|
||||
return json_decode($result);
|
||||
} catch ( V8JsException $e ) {
|
||||
throw new WappalyzerException('JavaScript error: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and execute one or more JavaScript files
|
||||
* @param mixed $files
|
||||
*/
|
||||
protected function load($files)
|
||||
{
|
||||
if ( !is_array($files) ) {
|
||||
$files = array($files);
|
||||
}
|
||||
|
||||
foreach ( $files as $file ) {
|
||||
$this->v8->executeString(file_get_contents('js/' . $file), $file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a cURL request
|
||||
* @param string $url
|
||||
*/
|
||||
protected function curl($url)
|
||||
{
|
||||
if ( $this->debug ) {
|
||||
echo 'cURL request: ' . $url . "\n";
|
||||
}
|
||||
|
||||
$ch = curl_init($url);
|
||||
|
||||
curl_setopt_array($ch, array(
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_HEADER => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_FOLLOWLOCATION => $this->curlFollowLocation,
|
||||
CURLOPT_MAXREDIRS => $this->curlMaxRedirects,
|
||||
CURLOPT_TIMEOUT => $this->curlTimeout,
|
||||
CURLOPT_USERAGENT => $this->curlUserAgent
|
||||
));
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ( curl_errno($ch) !== 0 ) {
|
||||
throw new WappalyzerException('cURL error: ' . curl_error($ch));
|
||||
}
|
||||
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
if ( $httpCode != 200 ) {
|
||||
throw new WappalyzerException('cURL request returned HTTP code ' . $httpCode);
|
||||
}
|
||||
|
||||
$result = new stdClass();
|
||||
|
||||
$result->url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
|
||||
|
||||
$result->host = parse_url($result->url, PHP_URL_HOST);
|
||||
|
||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
|
||||
$result->html = substr($response, $headerSize);
|
||||
|
||||
$result->html = mb_check_encoding($result->html, 'UTF-8') ? $result->html : utf8_encode($result->html);
|
||||
|
||||
$headers = trim(substr($response, 0, $headerSize));
|
||||
$headers = preg_split('/^\s*$/m', $headers);
|
||||
$headers = end($headers);
|
||||
$lines = array_slice(explode("\n", $headers), 1);
|
||||
|
||||
foreach ( $lines as $line ) {
|
||||
if ( strpos(trim($line), ': ') !== false ) {
|
||||
list($key, $value) = explode(': ', trim($line, "\r"));
|
||||
|
||||
$result->headers[strtolower($key)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected function executeScripts($page)
|
||||
{
|
||||
preg_match_all('/<script[^>]+src=("|\')(.+?)\1/i', $page->html, $matches);
|
||||
|
||||
if ( $urls = $matches[2] ) {
|
||||
foreach ( $urls as $url ) {
|
||||
if ( !preg_match('/^https?:\/\//', $url) ) {
|
||||
$url = $page->url . '/' . $url;
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->curl($url);
|
||||
} catch ( WappalyzerException $e ) {
|
||||
if ( $this->debug ) echo $e->getMessage() . "\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$v8 = new V8Js();
|
||||
|
||||
try {
|
||||
$v8->executeString('
|
||||
var
|
||||
document = {},
|
||||
window = { document: document }
|
||||
;
|
||||
');
|
||||
|
||||
$v8->executeString($result->html, $url);
|
||||
|
||||
$result = $v8->executeString('Object.keys(window);');
|
||||
|
||||
var_dump($result);
|
||||
} catch ( V8JsException $e ) {
|
||||
if ( $this->debug ) echo "\n", print_r($e->getJsTrace()), "\n\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
class WappalyzerException extends Exception
|
||||
{ }
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
require('WappalyzerException.php');
|
||||
require('Wappalyzer.php');
|
||||
|
||||
try {
|
||||
if ( php_sapi_name() !== 'cli' ) {
|
||||
exit('Run me from the command line');
|
||||
}
|
||||
|
||||
$url = !empty($argv[1]) ? $argv[1] : '';
|
||||
|
||||
if ( !$url ) {
|
||||
echo "Usage: php {$argv[0]} <url>\n";
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$wappalyzer = new Wappalyzer($url);
|
||||
|
||||
$detectedApps = $wappalyzer->analyze();
|
||||
|
||||
if ( $detectedApps ) {
|
||||
foreach ( $detectedApps as $detectedApp => $data ) {
|
||||
echo $detectedApp . ', ' . $data->version . ', ', $data->confidence . '%, ', implode(', ', $data->categories) . "\n";
|
||||
}
|
||||
} else {
|
||||
echo "No applications detected\n";
|
||||
}
|
||||
|
||||
exit(0);
|
||||
} catch ( Exception $e ) {
|
||||
echo $e->getMessage() . "\n";
|
||||
|
||||
exit(1);
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
var w = wappalyzer;
|
||||
|
||||
w.driver = {
|
||||
debug: false,
|
||||
data: {},
|
||||
timeout: 5000,
|
||||
|
||||
/**
|
||||
* Log messages to console
|
||||
*/
|
||||
log: function(args) {
|
||||
if ( w.driver.debug ) { print(args.type + ': ' + args.message + "\n"); }
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
init: function() {
|
||||
var app, apps = {};
|
||||
|
||||
w.analyze(w.driver.data.host, w.driver.data.url, {
|
||||
html: w.driver.data.html,
|
||||
headers: w.driver.data.headers
|
||||
});
|
||||
|
||||
for ( app in w.detected[w.driver.data.url] ) {
|
||||
apps[app] = {
|
||||
categories: [],
|
||||
confidence: w.detected[w.driver.data.url][app].confidenceTotal,
|
||||
version: w.detected[w.driver.data.url][app].version
|
||||
};
|
||||
|
||||
w.apps[app].cats.forEach(function(cat) {
|
||||
apps[app].categories.push(w.categories[cat]);
|
||||
});
|
||||
};
|
||||
|
||||
return JSON.stringify(apps);
|
||||
},
|
||||
|
||||
/**
|
||||
* Dummy
|
||||
*/
|
||||
displayApps: function() {
|
||||
}
|
||||
};
|
@ -1,2 +0,0 @@
|
||||
js/wappalyzer.js
|
||||
apps.json
|
@ -1,59 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import PyV8
|
||||
import requests
|
||||
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
from urlparse import urlparse
|
||||
|
||||
try:
|
||||
import json
|
||||
except ImportError:
|
||||
import simplejson as json
|
||||
|
||||
|
||||
class Wappalyzer(object):
|
||||
|
||||
def __init__(self, url):
|
||||
self.file_dir = os.path.dirname(__file__)
|
||||
|
||||
f = open(os.path.join(self.file_dir, 'apps.json'))
|
||||
data = json.loads(f.read())
|
||||
f.close()
|
||||
|
||||
self.categories = data['categories']
|
||||
self.apps = data['apps']
|
||||
self.url = url
|
||||
|
||||
def analyze(self):
|
||||
ctxt = PyV8.JSContext()
|
||||
ctxt.enter()
|
||||
|
||||
f1 = open(os.path.join(self.file_dir, 'js/wappalyzer.js'))
|
||||
f2 = open(os.path.join(self.file_dir, '../php/js/driver.js'))
|
||||
ctxt.eval(f1.read())
|
||||
ctxt.eval(f2.read())
|
||||
f1.close()
|
||||
f2.close()
|
||||
|
||||
host = urlparse(self.url).hostname
|
||||
response = requests.get(self.url, verify=False)
|
||||
html = response.text
|
||||
headers = dict(response.headers)
|
||||
|
||||
data = {'host': host, 'url': self.url, 'html': html, 'headers': headers}
|
||||
apps = json.dumps(self.apps)
|
||||
categories = json.dumps(self.categories)
|
||||
return ctxt.eval("w.apps = %s; w.categories = %s; w.driver.data = %s; w.driver.init();" % (apps, categories, json.dumps(data)))
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
w = Wappalyzer(sys.argv[1])
|
||||
print w.analyze()
|
||||
except IndexError:
|
||||
print ('Usage: python %s <url>' % sys.argv[0])
|
@ -1,2 +0,0 @@
|
||||
js/wappalyzer.js
|
||||
apps.json
|
@ -1,46 +0,0 @@
|
||||
var w = wappalyzer;
|
||||
|
||||
w.driver = {
|
||||
debug: false,
|
||||
data: {},
|
||||
timeout: 5000,
|
||||
|
||||
/**
|
||||
* Log messages to console
|
||||
*/
|
||||
log: function(args) {
|
||||
if ( w.driver.debug ) { print(args.type + ': ' + args.message + "\n"); }
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
init: function() {
|
||||
var app, apps = {};
|
||||
|
||||
w.analyze(w.driver.data.host, w.driver.data.url, {
|
||||
html: w.driver.data.html,
|
||||
headers: w.driver.data.headers
|
||||
});
|
||||
|
||||
for ( app in w.detected[w.driver.data.url] ) {
|
||||
apps[app] = {
|
||||
categories: [],
|
||||
confidence: w.detected[w.driver.data.url][app].confidenceTotal,
|
||||
version: w.detected[w.driver.data.url][app].version
|
||||
};
|
||||
|
||||
w.apps[app].cats.forEach(function(cat) {
|
||||
apps[app].categories.push(w.categories[cat]);
|
||||
});
|
||||
};
|
||||
|
||||
return JSON.stringify(apps);
|
||||
},
|
||||
|
||||
/**
|
||||
* Dummy
|
||||
*/
|
||||
displayApps: function() {
|
||||
}
|
||||
};
|
@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'net/http'
|
||||
require 'v8'
|
||||
require 'json'
|
||||
require 'openssl'
|
||||
|
||||
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
|
||||
Encoding.default_external = Encoding::UTF_8
|
||||
|
||||
class Wappalyzer
|
||||
def initialize
|
||||
@realdir = File.dirname(File.realpath(__FILE__))
|
||||
file = File.join(@realdir, 'apps.json')
|
||||
@json = JSON.parse(IO.read(file))
|
||||
@categories, @apps = @json['categories'], @json['apps']
|
||||
end
|
||||
|
||||
def analyze(url)
|
||||
uri, body, headers = URI(url), nil, {}
|
||||
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', :open_timeout => 5) do |http|
|
||||
resp = http.get(uri.request_uri)
|
||||
resp.each_header{|k,v| headers[k.downcase] = v}
|
||||
body = resp.body.encode('UTF-8', :invalid => :replace, :undef => :replace)
|
||||
end
|
||||
|
||||
cxt = V8::Context.new
|
||||
cxt.load File.join(@realdir, 'js', 'wappalyzer.js')
|
||||
cxt.load File.join(@realdir, 'js', 'driver.js')
|
||||
data = {'host' => uri.hostname, 'url' => url, 'html' => body, 'headers' => headers}
|
||||
output = cxt.eval("w.apps = #{@apps.to_json}; w.categories = #{@categories.to_json}; w.driver.data = #{data.to_json}; w.driver.init();")
|
||||
JSON.load(output)
|
||||
end
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
url = ARGV[0]
|
||||
if url
|
||||
puts JSON.pretty_generate(Wappalyzer.new.analyze(ARGV[0]))
|
||||
else
|
||||
puts "Usage: #{__FILE__} http://example.com"
|
||||
end
|
||||
end
|
Reference in new issue