2014-02-12 05:23:40 -05:00
child = require " child_process "
logger = require " logger-sharelatex "
metrics = require " ../../infrastructure/Metrics "
2016-02-24 12:21:20 -05:00
fs = require " fs "
Path = require " path "
2016-03-12 10:43:16 -05:00
_ = require ( " underscore " )
2014-02-12 05:23:40 -05:00
2016-03-12 07:38:21 -05:00
ONE_MEG = 1024 * 1024
2014-02-12 05:23:40 -05:00
module.exports = ArchiveManager =
2016-03-12 10:43:16 -05:00
_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) ->
2016-03-21 09:15:57 -04:00
logger . error { err , source } , " unzip failed "
2016-03-12 10:43:16 -05:00
if err . code == " ENOENT "
logger . error " unzip command not found. Please check the unzip command is installed "
callback ( err )
2016-03-21 12:37:29 -04:00
unzip . on " close " , (exitCode) ->
2016-03-12 10:43:16 -05:00
if error ?
error = new Error ( error )
2016-03-21 09:15:57 -04:00
logger . error err : error , source: source , " error checking zip size "
2016-03-12 10:43:16 -05:00
lines = output . split ( " \n " )
lastLine = lines [ lines . length - 2 ] ? . trim ( )
totalSizeInBytes = lastLine ? . split ( " " ) ? [ 0 ]
2016-03-21 12:00:12 -04:00
totalSizeInBytesAsInt = parseInt ( totalSizeInBytes )
2016-03-12 10:43:16 -05:00
2016-03-21 12:00:12 -04:00
if ! totalSizeInBytesAsInt ? or isNaN ( totalSizeInBytesAsInt )
2016-03-21 12:37:29 -04:00
logger . err source : source , totalSizeInBytes : totalSizeInBytes , totalSizeInBytesAsInt : totalSizeInBytesAsInt , lastLine : lastLine , exitCode : exitCode , " error getting bytes of zip "
2016-03-21 12:00:12 -04:00
return callback ( new Error ( " error getting bytes of zip " ) )
2016-03-12 10:43:16 -05:00
isTooLarge = totalSizeInBytes > ( ONE_MEG * 300 )
callback ( error , isTooLarge )
2015-02-11 06:34:49 -05:00
extractZipArchive: ( source , destination , _callback = (err) -> ) ->
callback = (args...) ->
_callback ( args . . . )
_callback = () ->
2016-03-12 10:43:16 -05:00
ArchiveManager . _isZipTooLarge source , (err, isTooLarge)->
2016-03-12 07:38:21 -05:00
if err ?
logger . err err : err , " error checking size of zip file "
return callback ( err )
2016-03-12 10:43:16 -05:00
if isTooLarge
return callback ( new Error ( " zip_too_large " ) )
2016-03-12 07:38:21 -05:00
timer = new metrics . Timer ( " unzipDirectory " )
logger . log source: source , destination: destination , " unzipping file "
2014-02-12 05:23:40 -05:00
2016-03-12 07:38:21 -05:00
unzip = child . spawn ( " unzip " , [ source , " -d " , destination ] )
2014-02-12 05:23:40 -05:00
2016-03-12 07:38:21 -05:00
# don't remove this line, some zips need
# us to listen on this for some unknow reason
unzip . stdout . on " data " , (d)->
2014-06-18 13:18:49 -04:00
2016-03-12 07:38:21 -05:00
error = null
unzip . stderr . on " data " , (chunk) ->
error || = " "
error += chunk
2014-02-12 05:23:40 -05:00
2016-03-12 07:38:21 -05:00
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 )
2015-02-11 06:34:49 -05:00
2016-03-21 12:37:29 -04:00
unzip . on " close " , () ->
2016-03-12 07:38:21 -05:00
timer . done ( )
if error ?
error = new Error ( error )
logger . error err : error , source: source , destination: destination , " error unzipping file "
callback ( error )
2016-02-24 12:21:20 -05:00
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 )
2014-02-12 05:23:40 -05:00