-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.coffee
171 lines (151 loc) · 5.78 KB
/
server.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
coffeecup = require 'coffeecup'
coffeemiddleware = require 'coffee-middleware'
express = require 'express'
morgan = require 'morgan'
servestatic = require 'serve-static'
fs = require 'fs'
path = require 'path'
http = require 'http'
https = require 'https'
busboy = require 'connect-busboy'
#subdomains = require 'express-subdomains'
storage = require 'node-persist'
edt = require 'express-directory-traversal'
cluster = require 'cluster'
os = require 'os'
numCPUs = os.cpus().length
if cluster.isMaster
console.log "Jarvis initialized"
for i in [1..numCPUs]
cluster.fork()
console.log "Process #{i} started"
cluster.on "exit", (worker, code, signal) -> cluster.fork()
else
storage.initSync()
#subdomains.use 'u'
#need updated certificate for subdomain
`
var compile = function (fmt) {
fmt = fmt.replace(/"/g, '\\"');
var js = ' return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){
return '"\n + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "';
}) + '";'
return new Function('tokens, req, res', js);
};
`
morgan.format 'dev++', (tokens, req, res) ->
color = 32
status = res.statusCode
if status >= 500 then color = 31
else if status >= 400 then color = 33
else if status >= 300 then color = 36
fn = compile "\x1b[90m:remote-addr \x1b[32m:method \x1b[35m:url \x1b[" + color + "m:status \x1b[97m:response-time ms\x1b[0m"
fn tokens, req, res
app = express()
app.set 'views', "#{__dirname}/webroot"
app.set 'view engine', 'coffee'
app.engine 'coffee', coffeecup.__express
app.use morgan stream: {write: (str) -> fs.appendFileSync "#{__dirname}/log/long.log", str}
app.use morgan format: "dev++", stream: {write: (str) -> fs.appendFileSync "#{__dirname}/log/short.log", str}
#app.use subdomains.middleware
app.use edt "Yo dawg, I heard you liked paths so I put paths in your paths so you can traverse paths while you're traversing paths.\n"
app.use coffeemiddleware src: "#{__dirname}/webroot"
app.use busboy limits: {fileSize: 20 * 1024 * 1024}
app.use servestatic "#{__dirname}/webroot"
helpers = {}
helpers["_#{f.slice 0, -7}"] = require "./include/#{f}" for f in fs.readdirSync('./include') when f.slice(-7) is ".coffee"
app.get '/', (req, res) ->
res.render 'index', empty: '', hardcode: helpers
app.get '/u', (req, res) ->
storage.values (links) ->
console.log links
res.writeHead 200, "Content-Type": "text/html"
res.write "<html><body>"
res.write "<p>Usage:<br>
https://jarvispa.info/u/short/long -- makes a new link<br>
https://jarvispa.info/u/short -- accesses a link<br></p>"
res.write "<p>Existing links:</p>"
res.write "<style>table,table td,table th{border:1px solid black}</style>"
res.write "<table><tablebody>"
res.write "<tr><th>Short</th><th>Long</th></tr>"
res.write "<tr><td>#{link.short}</td><td>#{link.long}</td></tr>" for link in links
res.write "</tablebody></table>"
res.write "</body></html>"
res.end()
app.get '/u/:short', (req, res) ->
if storage.getItem(req.params.short)?
res.redirect storage.getItem(req.params.short).long
else
res.end 'No url here :-('
app.get '/u/:short/:long', (req, res) ->
storage.setItem req.params.short, short: req.params.short, long: "http://" + decodeURIComponent req.params.long
res.end "https://jarvispa.info/u/#{req.params.short} -> #{decodeURIComponent req.params.long}"
app.get '/resources/userMusic', (req, res) ->
fs.readdir "#{__dirname}/webroot/resources/userMusic", (err, files) ->
if err
res.writeHead 500, "Content-Type": "text/plain"
res.write "Internal error fetching music list"
res.end()
console.log err.message
else
res.writeHead 200, "Content-Type": "text/plain"
res.write "#{file}\n" for file in files
res.end()
app.post '/upload', (req, res) ->
req.pipe req.busboy
req.busboy.on 'file', (fieldname, file, filename) ->
filename = filename.replace(RegExp(' ', 'g'), '_').replace(/[^A-Z0-9._-]/ig, '').toLowerCase()
filepath = "#{__dirname}/webroot/resources/userMusic/#{filename}"
if filepath isnt path.join '/', filepath
res.writeHead 403, "Content-Type": "text/plain"
res.write "The directory traversal is strong in this one."
res.end()
else
fstream = fs.createWriteStream filepath
file.pipe fstream
fstream.on 'close', ->
#fs.chownSync filepath, 33, 33
#fs.chmodSync filepath, 700
res.writeHead 200
res.write "File uploaded successfuly"
res.end()
app.get '*', (req, res) ->
relpath = "#{req.url.substr(1)}index"
filepath = "#{__dirname}/webroot#{req.url}index.coffee"
if filepath isnt path.join '/', filepath
res.writeHead 403, "Content-Type": "text/plain"
res.write "The directory traversal is strong in this one."
res.end()
else
fs.exists filepath, (fileExists) ->
if fileExists
res.render relpath, empty: '', hardcode: helpers
else
res.status 404
if req.accepts 'html'
res.render '404', empty: '', hardcode: helpers
else
res.write '404 not found'
res.end()
#from http://www.benjiegillam.com/2012/06/node-dot-js-ssl-certificate-chain/
ca = []
chain = fs.readFileSync "#{__dirname}/certs/chain/ca-certs.crt", 'utf8'
chain = chain.split "\n"
cert = []
for line in chain when line.length isnt 0
cert.push line
if line.match /-END CERTIFICATE-/
ca.push cert.join "\n"
cert = []
options =
ca: ca
key: fs.readFileSync "#{__dirname}/certs/server.key"
cert: fs.readFileSync "#{__dirname}/certs/server.crt"
wwwdata = -> process.setuid "www-data"
localhost = "0.0.0.0"
httpServer = http.createServer (req, res) ->
res.writeHead 301, "Content-Type": "text/plain", "Location": "https://#{req.headers.host + req.url}"
res.end()
httpsServer = https.createServer options, app
httpServer.listen 80, localhost, wwwdata
httpsServer.listen 443, localhost, wwwdata