Skip to content

Instantly share code, notes, and snippets.

@pilhokim
Forked from miklschmidt/server.coffee
Last active August 29, 2015 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pilhokim/c2da0ba13df44a415cd3 to your computer and use it in GitHub Desktop.
Save pilhokim/c2da0ba13df44a415cd3 to your computer and use it in GitHub Desktop.
fs = require('fs')
http = require('http')
https = require('https')
express = require('express')
path = require 'path'
_ = require('underscore')
sessionToken = "secretString"
secretUploadPass = "Change me"
secretPass = "Change me too"
port = 3000
mode = 'production'
unless fs.existsSync("./db.json")
content = "[]"
fs.writeFileSync "./db.json", content
versionInfo = JSON.parse fs.readFileSync("./db.json").toString()
if process.argv[2]? and process.argv[2] is '--dev'
mode = 'development'
options = {}
if mode is 'production'
options.key = fs.readFileSync('/etc/ssl/localcerts/node.key').toString()
options.cert = fs.readFileSync('/etc/ssl/localcerts/node.pem').toString()
server = express(options)
store = new express.session.MemoryStore;
server.use express.cookieParser()
server.use express.session {secret: sessionToken, store: store, httpOnly: no}
server.use require('connect').bodyParser()
allowedDownloads = []
server.get '/download', (req, res) ->
sid = req.sessionID
if not req.query.v? or not req.session? or not req.session.download?
res.writeHead(404)
res.end('Not found')
return
download = req.session.download
version = req.query.v
unless req.session.download.version is version
res.writeHead(403)
res.end('Access denied')
return
else
req.session.download = null
res.sendfile(download.path)
server.post '/upload', (req, res) ->
unless req.body? and req.body.secret? and req.body.secret is secretUploadPass
if req.files.win32? and req.files.win32.path? and fs.existsSync(req.files.win32.path)
fs.unlinkSync(req.files.win32.path)
if req.files.linux64? and req.files.linux64.path? and fs.existsSync(req.files.linux64.path)
fs.unlinkSync(req.files.linux64.path)
if req.files.linux32? and req.files.linux32.path? and fs.existsSync(req.files.linux32.path)
fs.unlinkSync(req.files.linux32.path)
return res.json 403, {result: 'error', msg: "Access denied"}
versionNumber = req.body.version
linux32 = req.files.linux32
linux64 = req.files.linux64
win32 = req.files.win32
unless versionNumber
if req.files.win32? and req.files.win32.path? and fs.existsSync(req.files.win32.path)
fs.unlinkSync(req.files.win32.path)
if req.files.linux64? and req.files.linux64.path? and fs.existsSync(req.files.linux64.path)
fs.unlinkSync(req.files.linux64.path)
if req.files.linux32? and req.files.linux32.path? and fs.existsSync(req.files.linux32.path)
fs.unlinkSync(req.files.linux32.path)
return res.json 403, {result: 'error', msg: "Missing version number"}
versionExists = false
for info in versionInfo when info.version is versionNumber
versionExists = true
break
if versionExists
if req.files.win32? and req.files.win32.path? and fs.existsSync(req.files.win32.path)
fs.unlinkSync(req.files.win32.path)
if req.files.linux64? and req.files.linux64.path? and fs.existsSync(req.files.linux64.path)
fs.unlinkSync(req.files.linux64.path)
if req.files.linux32? and req.files.linux32.path? and fs.existsSync(req.files.linux32.path)
fs.unlinkSync(req.files.linux32.path)
return res.json 403, {result: 'error', msg: "The version you're trying to publish allready exists"}
newVersion =
version: versionNumber
files: {}
linux32result = linux64result = win32result = false
if linux32?
data = fs.readFileSync linux32.path
linux32result = fs.writeFileSync (path.join __dirname, 'dist', linux32.name), data
newVersion.files["linux-ia32"] = linux32.name
if linux64?
data = fs.readFileSync linux64.path
linux64result = fs.writeFileSync (path.join __dirname, 'dist', linux64.name), data
newVersion.files["linux-x64"] = linux64.name
if win32?
data = fs.readFileSync win32.path
win32result = fs.writeFileSync (path.join __dirname, 'dist', win32.name), data
newVersion.files["win-ia32"] = win32.name
if linux32 or linux64 or win32
versionInfo.push newVersion
result = fs.writeFileSync "./db.json", JSON.stringify(versionInfo)
return res.json result: 'ok'
else
res.json 412, result: 'error', msg: 'missing file'
server.post '/check', (req, res) ->
unless req.body?
res.writeHead(403)
res.end "Access denied"
return
secret = req.body.secret
if secret isnt secretPass
res.writeHead(403)
res.end "Access denied"
return
clientVersion = req.query.v if req.query.v?
clientVersion = req.query.version unless clientVersion or not req.query.version?
clientPlatform = req.query.p if req.query.p?
clientPlatform = req.query.platform unless clientPlatform or not req.query.platform?
res.writeHead(412) unless clientVersion and clientPlatform
return res.end "No version/platform parameters to check against" unless clientVersion and clientPlatform
sid = req.sessionID
result = {}
latestVersionFound = false
currentVersionFound = false
#console.log "Looking for newer version than", clientVersion, "for platform", clientPlatform
for v, i in versionInfo
if v.files[clientPlatform]?
latestVersionFound = true
latestVersion = v
latestVersionIndex = i
for v, i in versionInfo
if v.version is clientVersion and v.files[clientPlatform]?
currentVersionFound = true
currentVersion = v
currentVersionIndex = i
break
#console.log currentVersionIndex, latestVersionIndex
if currentVersionFound is false or latestVersionFound is false
# console.log "Couldn't find current version:", currentVersion unless currentVersionFound
# console.log "Couldn't find latest version:", latestVersion unless latestVersionFound
result.result = "unknown version"
else if currentVersionIndex is latestVersionIndex
# console.log "Client is allready on latest version:", currentVersionIndex, latestVersionIndex, latestVersion.version
result.result = "noupdates"
else
result.result = "ok"
url = "/download?v=#{latestVersion.version}"
allowedDownload =
url: url
version: latestVersion.version
path: path.join(__dirname, 'dist', latestVersion.files[clientPlatform])
req.session.download = allowedDownload
result.update =
path: url
host: "yourhost.name"
port: 3000
protocol: if mode is 'production' then "https" else "http"
version: latestVersion.version
filename: latestVersion.files[clientPlatform]
changelog: 'Changelogs will be here soon'
res.json result
if mode is 'production'
https.createServer(options,server).listen port, () ->
console.log("Timetracker Update https server listening on port " + port)
else
server.listen port, () ->
console.log "Timetracker Update server listening on port " + port
admzip = require 'adm-zip'
http = require 'http'
https = require 'https'
fs = require 'fs'
path = require 'path'
request = require 'superagent'
ProgressBar = require('progress')
execFile = require('child_process').execFile
secretString = "secretstring configured in the server"
serverAddress = "your.update.server:3000"
applicationExecutable = "timetracker"
if process.platform.match(/^win/)
ds = "\\"
else
ds = "/"
pathfrags = process.execPath.split(ds)
__APPDIR = ''
len = pathfrags.length
# Get rid of filename
for frag, index in pathfrags when index < len-1
__APPDIR += frag + ds
__PARENTDIR = path.join(__APPDIR, "..#{ds}")
if process.platform.match(/^win/)
platform = 'win-ia32'
else if process.platform.match(/^darwin/)
platform = 'osx-ia32'
else if process.platform.match(/^linux/)
platform = 'linux-' + process.arch
infoFile = path.join(__PARENTDIR, "VERSION")
version = fs.readFileSync(infoFile).toString()
console.log "You are currently on version:", version
downloadUpdate = (download, callback) ->
fs.open download.filename, 'w', (err, destination) ->
if (err)
console.log "could not open " + download.filename + " for downloading " + download.filename + ": " + err.message
callback null, err
return
req = https.request
hostname: download.host
port: download.port
path: download.path
headers:
Cookie: download.cookie
method: 'GET'
req.on 'error', (err) ->
fs.closeSync destination
console.error "failed to get " + download.filename + " from " + download.host + ": " + err.message
callback null, err
req.on 'response', (res) ->
len = parseInt(res.headers['content-length'], 10)
totalDownloaded = 0
$('#description').text("Downloading " + download.filename + " 0%")
res.on 'data', (chunk) ->
if chunk.length
totalDownloaded += chunk.length
$('#description').text("Downloading " + download.filename + " " + Math.round((totalDownloaded/len)*100) + "%")
fs.writeSync(destination, chunk, 0, chunk.length, null)
res.on 'end', () ->
console.log()
fs.closeSync(destination)
callback(download.filename)
req.end()
checkUpdate = (callback) ->
url = "https://#{serverAddress}/check?v=#{version}&p=#{platform}"
request.post(url)
.type('json')
.send({secret: secretString})
.end (err, res) =>
if err?
console.log err
return callback null, err
if res.body.result? and res.body.result is 'ok'
toDownload = res.body.update
toDownload.cookie = res.header['set-cookie']
console.log "New version available! (v" + toDownload.version + ")"
console.log()
callback toDownload
else
callback false
console.log res
restartApp = () ->
if platform is 'win-ia32'
gui.Shell.openItem __PARENTDIR + applicationExecutable '.exe'
else
# Linux only so far
fs.chmodSync __PARENTDIR + applicationExecutable, '775'
execFile __PARENTDIR + applicationExecutable, [], {cwd: __PARENTDIR}
run = () ->
checkUpdate (download, err) ->
if err or not download
msg = 'No updates available.. Exiting..'
console.log msg
$('#description').text(msg)
console.log err if err
gui.Window.get().close(true)
return
$('#version').text(download.version)
downloadUpdate download, (filepath, err) ->
return console.log "Couldn't download update: ", err if err
msg = "Finished downloading files for version " + download.version
$('#description').text(msg)
zip = new admzip(filepath)
$('#description').text('Extracting...')
zip.extractAllTo __PARENTDIR, true
$('#description').text('All done, restarting timetracker')
restartApp()
# Exit the updater
gui.Window.get().close(true)
module.exports = run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment