🐛 Fix corrupt zip and remove project download on server

This commit is contained in:
brunosimon
2017-12-25 17:49:53 +01:00
parent 3d93205750
commit 2620b00ffe
23 changed files with 148 additions and 60 deletions
+5 -5
View File
@@ -2,7 +2,7 @@
const slug = require('slug') const slug = require('slug')
const Files = require('./files.js') const Files = require('./files.js')
const Chat = require('./chat.js') const Chat = require('./chat.js')
const AdmZip = require('adm-zip') const JSZip = require('jszip')
const glob = require('glob') const glob = require('glob')
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
@@ -72,8 +72,8 @@ class Project
// Search files with glob // Search files with glob
const files = glob.sync(this.path + '/**', { dot: true }) const files = glob.sync(this.path + '/**', { dot: true })
// Create a zip file // // Create a zip file
const zip = new AdmZip() const zip = new JSZip()
// Add files to zip // Add files to zip
for(const _file of files) for(const _file of files)
@@ -85,12 +85,12 @@ class Project
{ {
const basename = path.basename(_file) const basename = path.basename(_file)
const relativePath = _file.replace(basename, '').replace(this.path, '') const relativePath = _file.replace(basename, '').replace(this.path, '')
zip.addLocalFile(_file, relativePath) zip.file(`${relativePath}${basename}`, fs.readFileSync(_file))
} }
} }
// Create and return zip buffer // Create and return zip buffer
this.zipBuffer = zip.toBuffer() this.zipBuffer = zip.generateNodeStream({ type: 'nodebuffer', streamFiles: true })
this.zipNeedsUpdate = false this.zipNeedsUpdate = false
// Debug // Debug
+4
View File
@@ -18,6 +18,10 @@ class Projects
// Connection event // Connection event
this.projectsSocket.on('connection', (socket) => this.projectsSocket.on('connection', (socket) =>
{ {
// // Send the config to the new socket
socket.emit('config', { domain: this.config.domain, server: this.config.server })
// Send the projects update to all users
this.projectsSocket.emit('update_projects', this.describe()) this.projectsSocket.emit('update_projects', this.describe())
if(this.config.debug >= 1) if(this.config.debug >= 1)
+10 -7
View File
@@ -109,13 +109,16 @@ class Site
// Get zip buffer // Get zip buffer
const zipBuffer = _project.getZipBuffer() const zipBuffer = _project.getZipBuffer()
// Send // Set finename
response.writeHead(200, { const date = new Date()
'Content-Type': 'application/zip', const hours = `${date.getHours() < 10 ? '0' : ''}${date.getHours()}`
'Content-Length': zipBuffer.length const minutes = `${date.getMinutes() < 10 ? '0' : ''}${date.getMinutes()}`
}) const seconds = `${date.getSeconds() < 10 ? '0' : ''}${date.getSeconds()}`
response.write(zipBuffer, 'binary') const name = `${_project.slug}_${hours}-${minutes}-${seconds}.zip`
response.end(null, 'binary')
response.setHeader('Content-disposition', `attachment; filename=${name}`)
zipBuffer.pipe(response)
}) })
this.express.use('/' + _project.slug + '/files', express.static(_project.path)) this.express.use('/' + _project.slug + '/files', express.static(_project.path))
+60 -5
View File
@@ -58,11 +58,6 @@
} }
} }
}, },
"adm-zip": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz",
"integrity": "sha1-hgbCy/HEJs6MjsABdER/1Jtur8E="
},
"after": { "after": {
"version": "0.8.2", "version": "0.8.2",
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
@@ -2435,6 +2430,11 @@
"is-symbol": "1.0.1" "is-symbol": "1.0.1"
} }
}, },
"es6-promise": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
"integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y="
},
"escape-html": { "escape-html": {
"version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
@@ -4236,6 +4236,11 @@
"integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=",
"dev": true "dev": true
}, },
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
},
"imurmurhash": { "imurmurhash": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -4675,6 +4680,48 @@
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
"dev": true "dev": true
}, },
"jszip": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz",
"integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==",
"requires": {
"core-js": "2.3.0",
"es6-promise": "3.0.2",
"lie": "3.1.1",
"pako": "1.0.6",
"readable-stream": "2.0.6"
},
"dependencies": {
"core-js": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
"integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU="
},
"pako": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
"integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg=="
},
"readable-stream": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "0.10.31",
"util-deprecate": "1.0.2"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -4716,6 +4763,14 @@
"type-check": "0.3.2" "type-check": "0.3.2"
} }
}, },
"lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
"requires": {
"immediate": "3.0.6"
}
},
"load-json-file": { "load-json-file": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+2 -2
View File
@@ -23,14 +23,15 @@
}, },
"homepage": "https://github.com/brunosimon/keppler", "homepage": "https://github.com/brunosimon/keppler",
"dependencies": { "dependencies": {
"adm-zip": "^0.4.7",
"chokidar": "^1.7.0", "chokidar": "^1.7.0",
"colors": "^1.1.2", "colors": "^1.1.2",
"diff": "^3.3.0", "diff": "^3.3.0",
"express": "^4.15.3", "express": "^4.15.3",
"glob": "^7.1.2", "glob": "^7.1.2",
"helmet": "^3.8.1", "helmet": "^3.8.1",
"html-entities": "^1.2.1",
"ip": "^1.1.5", "ip": "^1.1.5",
"jszip": "^3.1.5",
"mime": "^1.3.6", "mime": "^1.3.6",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"node-notifier": "^5.1.2", "node-notifier": "^5.1.2",
@@ -40,7 +41,6 @@
"socket.io-client": "^2.0.3", "socket.io-client": "^2.0.3",
"vue": "^2.3.3", "vue": "^2.3.3",
"vuex": "^2.3.1", "vuex": "^2.3.1",
"html-entities": "^1.2.1",
"yargs": "^8.0.2" "yargs": "^8.0.2"
}, },
"devDependencies": { "devDependencies": {
+1 -1
View File
@@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><title>Keppler</title><meta name=viewport content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><link class=favicon rel=icon type=image/png href=""><link href=/static/css/app.d379c533b0023617002453dec20e90b9.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.740d3494c804055a5113.js></script><script type=text/javascript src=/static/js/app.6410af1d45da75742280.js></script></body></html> <!DOCTYPE html><html><head><meta charset=utf-8><title>Keppler</title><meta name=viewport content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><link class=favicon rel=icon type=image/png href=""><link href=/static/css/app.d379c533b0023617002453dec20e90b9.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.dccd405c2f8ce5d06dc2.js></script><script type=text/javascript src=/static/js/app.03226a35957b0c5066f6.js></script></body></html>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,i){for(var u,a,f,s=0,l=[];s<t.length;s++)a=t[s],o[a]&&l.push(o[a][0]),o[a]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,i);l.length;)l.shift()();if(i)for(s=0;s<i.length;s++)f=n(n.s=i[s]);return f};var t={},o={1:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var i=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute("nonce",n.nc),u.src=n.p+"static/js/"+e+"."+{0:"6410af1d45da75742280"}[e]+".js";var a=setTimeout(r,12e4);return u.onerror=u.onload=r,i.appendChild(u),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="/",n.oe=function(e){throw console.error(e),e}}([]); !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,i){for(var u,a,f,s=0,l=[];s<t.length;s++)a=t[s],o[a]&&l.push(o[a][0]),o[a]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,i);l.length;)l.shift()();if(i)for(s=0;s<i.length;s++)f=n(n.s=i[s]);return f};var t={},o={1:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var i=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute("nonce",n.nc),u.src=n.p+"static/js/"+e+"."+{0:"03226a35957b0c5066f6"}[e]+".js";var a=setTimeout(r,12e4);return u.onerror=u.onload=r,i.appendChild(u),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="/",n.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.740d3494c804055a5113.js.map //# sourceMappingURL=manifest.dccd405c2f8ce5d06dc2.js.map
File diff suppressed because one or more lines are too long
@@ -19,6 +19,11 @@ export default
computed: computed:
{ {
serverConfig()
{
return this.$store.state.serverConfig
},
project() project()
{ {
return this.$store.state.projects.current return this.$store.state.projects.current
+18 -14
View File
@@ -5,21 +5,25 @@
<!-- Favicon --> <!-- Favicon -->
<favicon></favicon> <favicon></favicon>
<!-- Header --> <div v-if="serverConfig">
<a class="application-header" href="#" @click.prevent="onHeaderClick">
<img class="element background" src="../../../static/svg/header-background.svg" alt="">
<span class="element robot-container">
<img class="element robot" src="../../../static/svg/header-robot.svg" alt="">
</span>
<img class="element title" src="../../../static/svg/keppler-title.svg" alt="">
</a>
<!-- Popin --> <!-- Header -->
<popin></popin> <a class="application-header" href="#" @click.prevent="onHeaderClick">
<img class="element background" src="../../../static/svg/header-background.svg" alt="">
<span class="element robot-container">
<img class="element robot" src="../../../static/svg/header-robot.svg" alt="">
</span>
<img class="element title" src="../../../static/svg/keppler-title.svg" alt="">
</a>
<!-- Projects --> <!-- Popin -->
<projects-hub></projects-hub> <popin></popin>
<!-- Project --> <!-- Projects -->
<project v-if="project"></project> <projects-hub></projects-hub>
<!-- Project -->
<project v-if="project"></project>
</div>
</div> </div>
+6 -2
View File
@@ -40,14 +40,18 @@ export default
const projectsUrl = `${process.env.NODE_ENV === 'production' ? '' : 'http://localhost:1571'}/projects` const projectsUrl = `${process.env.NODE_ENV === 'production' ? '' : 'http://localhost:1571'}/projects`
this.projectsSocket = socketIoClient(projectsUrl) this.projectsSocket = socketIoClient(projectsUrl)
this.projectsSocket.on('connect', () => this.projectsSocket.on('connect', (data) =>
{ {
// console.log('projects connected') // console.log('projects connected')
}) })
this.projectsSocket.on('config', (data) =>
{
this.$store.commit('updateServerConfig', data)
})
this.projectsSocket.on('update_projects', (data) => this.projectsSocket.on('update_projects', (data) =>
{ {
this.$store.commit('updateUrl', data.domain)
this.$store.commit('updateProjects', data.all) this.$store.commit('updateProjects', data.all)
}) })
}, },
+1 -1
View File
@@ -20,7 +20,7 @@ export default
{ {
downloadUrl() downloadUrl()
{ {
return `${this.$store.state.url}/${this.$store.state.projects.current.slug}/files/${this.content.path.full}` return `${this.$store.state.serverConfig.domain}/${this.$store.state.projects.current.slug}/files/${this.content.path.full}`
}, },
downloadDataUri() downloadDataUri()
+1 -1
View File
@@ -30,7 +30,7 @@ export default
quote: () => quotes[Math.floor(quotes.length * Math.random())], quote: () => quotes[Math.floor(quotes.length * Math.random())],
url() url()
{ {
return this.$store.state.url return this.$store.state.serverConfig.domain
} }
}, },
+1 -1
View File
@@ -21,7 +21,7 @@ export default
{ {
downloadUrl() downloadUrl()
{ {
return `${this.$store.state.url}/${this.project.slug}/download` return `${this.$store.state.serverConfig.domain}/${this.project.slug}/download`
}, },
project() project()
+6 -1
View File
@@ -11,6 +11,11 @@ export default
computed: computed:
{ {
serverConfig()
{
return this.$store.state.serverConfig
},
projects() projects()
{ {
return this.$store.state.projects.all return this.$store.state.projects.all
@@ -34,7 +39,7 @@ export default
return '' return ''
} }
return `${this.$store.state.url}/${this.currentProject.slug}/download` return `${this.$store.state.serverConfig.domain}/${this.currentProject.slug}/download`
} }
}, },
@@ -18,7 +18,7 @@
</div> </div>
</div> </div>
<a class="download" :href="downloadUrl" download> <a v-if="!serverConfig.server" class="download" :href="downloadUrl" download="test.zip">
<img class="icon default" src="../../../static/svg/download.svg" alt=""> <img class="icon default" src="../../../static/svg/download.svg" alt="">
<img class="icon hover" src="../../../static/svg/download-hover.svg" alt=""> <img class="icon hover" src="../../../static/svg/download-hover.svg" alt="">
<tooltip position="right">Download the whole project</tooltip> <tooltip position="right">Download the whole project</tooltip>
+3 -3
View File
@@ -17,15 +17,15 @@ export default new Vuex.Store({
state: state:
{ {
url: '', serverConfig: null,
scrollbarWidth: 0 scrollbarWidth: 0
}, },
mutations: mutations:
{ {
updateUrl(state, data) updateServerConfig(state, data)
{ {
state.url = data state.serverConfig = data
}, },
updateScrollbarWidth(state, data) updateScrollbarWidth(state, data)
@@ -0,0 +1,8 @@
body {
margin:0;
padding:0;
}
.toto .tata > span {
background:url('kikoo.png') top left repeat-x;
}

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB