mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
108 lines
3 KiB
CoffeeScript
108 lines
3 KiB
CoffeeScript
child = require "child_process"
|
|
logger = require "logger-sharelatex"
|
|
metrics = require "metrics-sharelatex"
|
|
fs = require "fs"
|
|
Path = require "path"
|
|
_ = require("underscore")
|
|
|
|
ONE_MEG = 1024 * 1024
|
|
|
|
module.exports = ArchiveManager =
|
|
|
|
|
|
_isZipTooLarge: (source, callback = (err, isTooLarge)->)->
|
|
callback = _.once callback
|
|
|
|
unzip = child.spawn("unzip", ["-l", source])
|
|
|
|
output = ""
|
|
unzip.stdout.on "data", (d)->
|
|
output += d
|
|
|
|
error = null
|
|
unzip.stderr.on "data", (chunk) ->
|
|
error ||= ""
|
|
error += chunk
|
|
|
|
unzip.on "error", (err) ->
|
|
logger.error {err, source}, "unzip failed"
|
|
if err.code == "ENOENT"
|
|
logger.error "unzip command not found. Please check the unzip command is installed"
|
|
callback(err)
|
|
|
|
unzip.on "close", (exitCode) ->
|
|
if error?
|
|
error = new Error(error)
|
|
logger.warn err:error, source: source, "error checking zip size"
|
|
|
|
lines = output.split("\n")
|
|
lastLine = lines[lines.length - 2]?.trim()
|
|
totalSizeInBytes = lastLine?.split(" ")?[0]
|
|
|
|
totalSizeInBytesAsInt = parseInt(totalSizeInBytes)
|
|
|
|
if !totalSizeInBytesAsInt? or isNaN(totalSizeInBytesAsInt)
|
|
logger.err source:source, totalSizeInBytes:totalSizeInBytes, totalSizeInBytesAsInt:totalSizeInBytesAsInt, lastLine:lastLine, exitCode:exitCode, "error getting bytes of zip"
|
|
return callback(new Error("error getting bytes of zip"))
|
|
|
|
isTooLarge = totalSizeInBytes > (ONE_MEG * 300)
|
|
|
|
callback(error, isTooLarge)
|
|
|
|
|
|
|
|
extractZipArchive: (source, destination, _callback = (err) ->) ->
|
|
callback = (args...) ->
|
|
_callback(args...)
|
|
_callback = () ->
|
|
|
|
ArchiveManager._isZipTooLarge source, (err, isTooLarge)->
|
|
if err?
|
|
logger.err err:err, "error checking size of zip file"
|
|
return callback(err)
|
|
|
|
if isTooLarge
|
|
return callback(new Error("zip_too_large"))
|
|
|
|
|
|
timer = new metrics.Timer("unzipDirectory")
|
|
logger.log source: source, destination: destination, "unzipping file"
|
|
|
|
unzip = child.spawn("unzip", [source, "-d", destination])
|
|
|
|
# don't remove this line, some zips need
|
|
# us to listen on this for some unknow reason
|
|
unzip.stdout.on "data", (d)->
|
|
|
|
error = null
|
|
unzip.stderr.on "data", (chunk) ->
|
|
error ||= ""
|
|
error += chunk
|
|
|
|
unzip.on "error", (err) ->
|
|
logger.error {err, source, destination}, "unzip failed"
|
|
if err.code == "ENOENT"
|
|
logger.error "unzip command not found. Please check the unzip command is installed"
|
|
callback(err)
|
|
|
|
unzip.on "close", () ->
|
|
timer.done()
|
|
if error?
|
|
error = new Error(error)
|
|
logger.error err:error, source: source, destination: destination, "error unzipping file"
|
|
callback(error)
|
|
|
|
findTopLevelDirectory: (directory, callback = (error, topLevelDir) ->) ->
|
|
fs.readdir directory, (error, files) ->
|
|
return callback(error) if error?
|
|
if files.length == 1
|
|
childPath = Path.join(directory, files[0])
|
|
fs.stat childPath, (error, stat) ->
|
|
return callback(error) if error?
|
|
if stat.isDirectory()
|
|
return callback(null, childPath)
|
|
else
|
|
return callback(null, directory)
|
|
else
|
|
return callback(null, directory)
|
|
|