├── docroot └── index.html ├── .gitignore ├── templates ├── moved.html ├── error.html └── error500.html ├── bin ├── chameleon-server.js └── chameleon-add-file.js ├── package.json ├── data ├── CERTIFICATE_REQUEST.PEM ├── CERTIFICATE.PEM ├── PRIVATE_KEY.PEM └── server_signatures.txt ├── config.js └── lib ├── cipher.js ├── lib.js └── server.js /docroot/index.html: -------------------------------------------------------------------------------- 1 | tere -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /templates/moved.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 301 Moved Permanently 4 | 5 |

Moved Permanently

6 | The document has moved here.

7 | -------------------------------------------------------------------------------- /templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ code }} {{ title }} 4 | 5 |

{{ title }}

6 |

{{ message }}

7 |
8 |
{{ server_signature }} Server at {{ hostname }} Port {{ public_port }}
9 | -------------------------------------------------------------------------------- /bin/chameleon-server.js: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/node 2 | 3 | var config = require("./../config"), 4 | server = require("./../lib/server"), 5 | lib = require("./../lib/lib"); 6 | 7 | lib.prettyPrint(["Welcome to CHAMELEON/"+config.server_version,"~~~"]); 8 | 9 | server.readPasswords(function(err){ 10 | if(err){ 11 | throw err; 12 | } 13 | server.start(server.staticRouter); 14 | }); -------------------------------------------------------------------------------- /templates/error500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 500 Internal Server Error 4 | 5 |

Internal Server Error

6 |

The server encountered an internal error or 7 | misconfiguration and was unable to complete 8 | your request.

9 |

Please contact the server administrator, 10 | {{ email }} and inform them of the time the error occurred, 11 | and anything you might have done that may have 12 | caused the error.

13 |

More information about this error may be available 14 | in the server error log.

15 |

Additionally, a 500 Internal Server Error 16 | error was encountered while trying to use an ErrorDocument to handle the request.

17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chameleon", 3 | "description": "Static server", 4 | "version": "0.1.2", 5 | "author" : "Andris Reinman", 6 | "maintainers":[ 7 | { 8 | "name":"andris", 9 | "email":"andris@node.ee" 10 | } 11 | ], 12 | "repository" : { 13 | "type" : "git", 14 | "url" : "http://github.com/andris9/chameleon.git" 15 | }, 16 | "bin":{ 17 | "chameleon-server": "./bin/chameleon-server.js", 18 | "chameleon-add-file": "./bin/chameleon-add-file.js" 19 | }, 20 | "main" : "./lib/server", 21 | "licenses" : [ 22 | { 23 | "type": "MIT", 24 | "url": "http://github.com/andris9/chameleon/blob/master/LICENSE" 25 | } 26 | ], 27 | "dependencies": { 28 | "mimelib-noiconv":"*", 29 | "commander": "*", 30 | "swig": "*", 31 | "optimist": "*", 32 | "fetch": "*", 33 | "mimelib-noiconv": "*" 34 | }, 35 | "engine": [ "node >=0.6.0" ], 36 | "keywords": ["http"] 37 | } -------------------------------------------------------------------------------- /data/CERTIFICATE_REQUEST.PEM: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICsTCCAZkCAQAwbDELMAkGA1UEBhMCWFgxCzAJBgNVBAgTAlhYMQswCQYDVQQH 3 | EwJYWDELMAkGA1UEChMCWFgxCzAJBgNVBAsTAlhYMRAwDgYDVQQDFAcqLm9uaW9u 4 | MRcwFQYJKoZIhvcNAQkBFgh4eEB4eC54eDCCASIwDQYJKoZIhvcNAQEBBQADggEP 5 | ADCCAQoCggEBAN0ToiG7H3I2tvmb9hrbbocVluuXkTaHdSFyjJ6Q53iGUdR9uiOL 6 | OzLRlnZSQ5wvw26tAG8CwXtYNCOEsP/yA9bhpmP+BCGEE6K3rRR16B7sE4T+Mn/i 7 | A9bZR9JW/ZGUulB9SXfbmpEjrAg4Y9pchBgWCCL7k+k/hQbG5gNZZu3f/6K9RGOG 8 | dGvef4VUd7hgXp1QYb+ovSKKDYVsKhTB0x1HWAiP+OKR5Eh8sIBdwC9+KYhzvc0G 9 | 5L8WSlKVzt8jG8+WZknnWSi1i2iHs5pT/iuctVjDRhRTYuYxWgwNdFt1//T9ZJM9 10 | 1Wyrs7IrR8dD3uaQlm+dxj74HZSdRB4AUK0CAwEAAaAAMA0GCSqGSIb3DQEBBAUA 11 | A4IBAQAmE82YMY/dFKyaDaS/O/32ym8kiOv8nbioMXBehxuZAtYbRrzGnHO9qzx9 12 | H4iWwdhMfLkZhog9rLamRylTLtAnM/HgU8stLVBJxK8sV4zxcunMpJ5LJKj2sI/v 13 | /QVZQRxvim1iovn+6EXUv4ue5xW4QIo5yniAIz7YyE6+R88Pf94v56lWyOHF5msf 14 | gMXqgiG1JL41+gTSRXH8TootxWAhrQHLTZDOBVSpw80f8f7mcGMkq8cuFzWw6b0B 15 | bw08l/xTrTVvJk2X43kczMqEzHsa+ZEuNYDOKQoGaisC47wUSpQs6OYWCRj/T9Jv 16 | 49iPlp4vqPb+I5fGFrCQNSAr4iru 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /data/CERTIFICATE.PEM: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDVDCCAjwCCQD5yrvwMczoaTANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJY 3 | WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQKEwJYWDELMAkGA1UE 4 | CxMCWFgxEDAOBgNVBAMUByoub25pb24xFzAVBgkqhkiG9w0BCQEWCHh4QHh4Lnh4 5 | MB4XDTExMTIyODEzNTgyM1oXDTEyMTIyNzEzNTgyM1owbDELMAkGA1UEBhMCWFgx 6 | CzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UEChMCWFgxCzAJBgNVBAsT 7 | AlhYMRAwDgYDVQQDFAcqLm9uaW9uMRcwFQYJKoZIhvcNAQkBFgh4eEB4eC54eDCC 8 | ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN0ToiG7H3I2tvmb9hrbbocV 9 | luuXkTaHdSFyjJ6Q53iGUdR9uiOLOzLRlnZSQ5wvw26tAG8CwXtYNCOEsP/yA9bh 10 | pmP+BCGEE6K3rRR16B7sE4T+Mn/iA9bZR9JW/ZGUulB9SXfbmpEjrAg4Y9pchBgW 11 | CCL7k+k/hQbG5gNZZu3f/6K9RGOGdGvef4VUd7hgXp1QYb+ovSKKDYVsKhTB0x1H 12 | WAiP+OKR5Eh8sIBdwC9+KYhzvc0G5L8WSlKVzt8jG8+WZknnWSi1i2iHs5pT/iuc 13 | tVjDRhRTYuYxWgwNdFt1//T9ZJM91Wyrs7IrR8dD3uaQlm+dxj74HZSdRB4AUK0C 14 | AwEAATANBgkqhkiG9w0BAQUFAAOCAQEAiYvgQHd7vB6VNLzQ0O7WocFnz9OM+KBi 15 | uFMWNx3seoCeCoz7nhh1vbKwWIcnkt+R3GGy0qOICm2tywEFfOk5VuS/rxsBA/nW 16 | nJCB6zwJ7PPTnTdxSLQOfcCYrYJDdBnC14zaHPQEzinT3gyjpRi7jBWpb6Xmozud 17 | jluP4dd6EufintEjUE2J9Jx7f9no2JBxJ5hvO6ij+OmRM9nTPF7M2Yr7xT4yeUcR 18 | 3GhXrB8RuNQfRH1q3eCBz2Y9P9xHz+4fpnPUrOr9ppOX1AXy1jS5bwebrF1A7xe1 19 | DyiNGOIOnxrENjeyZ9EVl8+MjXmtBW+Gzp5Cxb4XJitoXbDMr+j4cQ== 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /bin/chameleon-add-file.js: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/node 2 | 3 | var config = require("./../config"), 4 | server = require("./../lib/server"), 5 | lib = require("./../lib/lib"), 6 | argv = require("optimist").argv, 7 | fs = require("fs"), 8 | cryptoStream = require("./../lib/cipher"); 9 | 10 | server.readPasswords(function(err){ 11 | if(err){ 12 | throw err; 13 | } 14 | 15 | if(!argv.source){ 16 | throw new Error("Source file missing, usage: --source=path/to/file [--destination=/path/in/docroot/]"); 17 | } 18 | 19 | var docroot = config.docroot+ (config.docroot.substr(-1)!="/"?"/":""), 20 | target = argv.destination || argv.source.split("/").pop(); 21 | 22 | dest_url = lib.resolvePath(target, docroot); 23 | if(dest_url.substr(-1)=="/"){ 24 | dest_url += target; 25 | } 26 | 27 | if(dest_url.substr(0, docroot.length) != docroot){ 28 | throw Error("Invalid target"); 29 | } 30 | 31 | var inp = fs.createReadStream(argv.source), 32 | out = fs.createWriteStream(dest_url+".cr"), 33 | cipher1 = new cryptoStream.CipherStream(config.passwords[0]), 34 | cipher2 = new cryptoStream.CipherStream(config.passwords[1], "cast5-cbc"); 35 | 36 | inp.pipe(cipher1).pipe(cipher2).pipe(out); 37 | 38 | }); -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | var lib = require("./lib/lib"), 2 | argv = require('optimist').argv, 3 | fs = require("fs"), 4 | overwrite = {}; 5 | 6 | if(argv.config){ 7 | overwrite = JSON.parse(fs.readFileSync(argv.config,"utf-8")); 8 | } 9 | 10 | module.exports = { 11 | server_key: argv.skey || overwrite.server_key || '26E!7=NE=79)6!9-Xrt=4F)1205x-$Va', 12 | server_version: "0.1.0", 13 | docroot: argv.docroot || overwrite.docroot || __dirname+"/docroot", 14 | ssl:{ 15 | key: fs.readFileSync(argv.key || (overwrite.ssl && overwrite.ssl.key) || __dirname+"/data/PRIVATE_KEY.PEM"), 16 | certificate: fs.readFileSync(argv.cert ||  (overwrite.ssl && overwrite.ssl.certificate) || __dirname+"/data/CERTIFICATE.PEM"), 17 | }, 18 | http:{ 19 | port: argv.http_port || (overwrite.http && overwrite.http.port) || 12345, 20 | ip: argv.http_ip || (overwrite.http && overwrite.http.ip) || "127.0.0.1" 21 | }, 22 | https:{ 23 | port: argv.https_port || (overwrite.https && overwrite.https.port) || 12346, 24 | ip: argv.https_ip || (overwrite.https && overwrite.https.ip) || "127.0.0.1" 25 | }, 26 | server_signature: argv.server_signature || overwrite.server_signature || lib.SERVER_SIGNATURE, 27 | user: { 28 | uid: argv.uid || (overwrite.user && overwrite.user.uid) || "nobody", 29 | gid: argv.gid || (overwrite.user && overwrite.user.gid) || "nogroup" 30 | }, 31 | passwords:[] 32 | } -------------------------------------------------------------------------------- /lib/cipher.js: -------------------------------------------------------------------------------- 1 | var Stream = require("stream").Stream, 2 | utillib = require("util"), 3 | crypto = require('crypto'); 4 | 5 | module.exports.CipherStream = CipherStream; 6 | module.exports.DecipherStream = DecipherStream; 7 | 8 | function CipherStream(password, algorithm){ 9 | Stream.call(this); 10 | 11 | algorithm = algorithm || "aes192"; 12 | 13 | this.writable = true; 14 | 15 | this.cipher = crypto.createCipher(algorithm, password); 16 | } 17 | utillib.inherits(CipherStream, Stream); 18 | 19 | CipherStream.prototype.write = function(chunk){ 20 | if(typeof chunk == "string"){ 21 | chunk = new Buffer(chunk, "utf-8"); 22 | } 23 | var data = this.cipher.update(chunk.toString("binary")) || ""; 24 | if(data)this.emit("data", new Buffer(data, "binary")); 25 | } 26 | 27 | CipherStream.prototype.end = function(){ 28 | var data = this.cipher.final() || ""; 29 | if(data)this.emit("data", new Buffer(data, "binary")); 30 | this.emit("end"); 31 | } 32 | 33 | function DecipherStream(password, algorithm){ 34 | Stream.call(this); 35 | 36 | algorithm = algorithm || "aes192"; 37 | 38 | this.writable = true; 39 | 40 | this.decipher = crypto.createDecipher(algorithm, password); 41 | } 42 | utillib.inherits(DecipherStream, Stream); 43 | 44 | DecipherStream.prototype.write = function(chunk){ 45 | var data = this.decipher.update(chunk.toString("binary")) || ""; 46 | if(data)this.emit("data", new Buffer(data, "binary")); 47 | } 48 | 49 | DecipherStream.prototype.end = function(){ 50 | var data = this.decipher.final("binary") || ""; 51 | if(data)this.emit("data", new Buffer(data, "binary")); 52 | this.emit("end"); 53 | } -------------------------------------------------------------------------------- /data/PRIVATE_KEY.PEM: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA3ROiIbsfcja2+Zv2GttuhxWW65eRNod1IXKMnpDneIZR1H26 3 | I4s7MtGWdlJDnC/Dbq0AbwLBe1g0I4Sw//ID1uGmY/4EIYQToretFHXoHuwThP4y 4 | f+ID1tlH0lb9kZS6UH1Jd9uakSOsCDhj2lyEGBYIIvuT6T+FBsbmA1lm7d//or1E 5 | Y4Z0a95/hVR3uGBenVBhv6i9IooNhWwqFMHTHUdYCI/44pHkSHywgF3AL34piHO9 6 | zQbkvxZKUpXO3yMbz5ZmSedZKLWLaIezmlP+K5y1WMNGFFNi5jFaDA10W3X/9P1k 7 | kz3VbKuzsitHx0Pe5pCWb53GPvgdlJ1EHgBQrQIDAQABAoIBAEjAkEdna/bLGLXV 8 | 5Ex8T8g2i57mFwyJ0Tr7llkMOJBKK52w7lOKGyYjIM+5TLSWZ0sBtbXSg1eS9D2I 9 | CjOAMlFBmt8nFbbt3wRaS6QDFSsv51CJ0paRC1Bl2qPWqsWA2ztnr4i5BQmkYpWl 10 | 8P5IGdRPU8gnYEqO87kCNWl+v0eiJW1lVhVL0i6Y8vmOekvLR3/Vqsb5dhJNvPVW 11 | OYlbt+SYiHoVUZwMN9ct6Kd1wZJEVVahWATGrZo7CnMocgGp3N60Xs3GZJXa8rZU 12 | 72lDj+nju76K3AfH3JEsSLqG/aVOEj6dqEtH5sPpeol4SA0z6TbqtDl7WrASI+Kh 13 | e1KIuUUCgYEA/rwtP/TzNCOstImVjuNTbzWDSLS+RTN4c8FvOnDJUbvdUKFx0u0Z 14 | 9bzLuw08aDvxck8+t+gMDDqc9KSuUeAqYBLJkzQgIz7yPCfnWywStTZRlNJWqvWj 15 | TZ/uZtJD9hWTcm6SyTvUzQNxTsTtnmkB/o2KjrST1rLIVrAeKbu2ndcCgYEA3iyr 16 | ZUuehZwQ9zFtpjn8brKmvRcRY77tJRIjSh5V3B9ylhix+AePdZ8T8dApjqXirs7e 17 | IIR07JEkuq29Q8gG6WH638KvmM+YW3OTlpdomKXdG8YZfEkyDin3GiA7/TUFZYbk 18 | dApoSNTo47wBnfSUS+1vWdVGx35D4pyYe01cTRsCgYEA6yAudDZYteun4gyMq5NQ 19 | 0/mE8HtElQNpTw9g54RrjrHlGiOquJJ5v8VAF6uj8mJB/sz+iyn41ODVN0s6TACp 20 | nHw661DVyTK0zKnYduM7cWBt9PwhWzPYRDI3D1lNubs4mgtOGcjMJ1/iGl7TJcCv 21 | QpLLLeWoACiNmtZ9QPAvI4kCgYAF6miR5OaOpi4pds51m5umEumvpTqYTlAgKZB4 22 | +7/LgabaakPq18CxIBA24xUIMFCN2QI/GWfHmMHCmresY1oTwsEcTiHAzt4+qSAn 23 | 5VYqolf10luBXK2RhPqIXo1aW5wOLP5OPKy0K78buTjNzOJZ9zN8z9n3m9wQ35yL 24 | w+6OOwKBgQD8YBsGZbSPyCS9cHx/rrPZdXCft+wtP64tkhP14h544X87P6JGYdC/ 25 | cbX9McQZ6w6H/9jpSxqgKV/rkVpUrsA98DWBet4ESB18/4KDFP7oaZd5HtafitJc 26 | lbnspwM2Jpdono5H5ijQeigW5eWUIuPIuODhNg4IvQSDd7zcJt7dvg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /lib/lib.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"), 2 | crypto = require("crypto"), 3 | mimelib = require("mimelib-noiconv"), 4 | lib = module.exports; 5 | 6 | module.exports.SERVER_SIGNATURE = generateServerSignature(); 7 | 8 | module.exports.hmac = function(data, key){ 9 | var hmac = crypto.createHmac("SHA256", key || require("../config").server_key); 10 | hmac.update(data); 11 | return hmac.digest("hex"); 12 | }; 13 | 14 | module.exports.prettyPrint = function(str){ 15 | if(!Array.isArray(str)){ 16 | str = [str.toString("utf-8").trim()]; 17 | } 18 | var max = 0; 19 | for(var i=0, len = str.length; i max){ 21 | max = str[i].length; 22 | } 23 | } 24 | 25 | console.log(Array(max+1 + 4).join("-")); 26 | console.log("|" + Array(max+1 + 2).join(" ") + "|") 27 | 28 | for(var i=0, len = str.length; i= 3 && str[i] == Array(str[i].length+1).join(str[i].substr(0,1))){ 30 | console.log("| "+Array(max+1).join(str[i].substr(0,1))+" |") 31 | }else{ 32 | console.log("| " + str[i] + (str[i].length