Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. var fs = require('fs')
  2. var path = require('path')
  3. var yauzl = require('yauzl')
  4. var mkdirp = require('mkdirp')
  5. var concat = require('concat-stream')
  6. var debug = require('debug')('extract-zip')
  7. module.exports = function (zipPath, opts, cb) {
  8. debug('creating target directory', opts.dir)
  9. if (path.isAbsolute(opts.dir) === false) {
  10. return cb(new Error('Target directory is expected to be absolute'))
  11. }
  12. mkdirp(opts.dir, function (err) {
  13. if (err) return cb(err)
  14. fs.realpath(opts.dir, function (err, canonicalDir) {
  15. if (err) return cb(err)
  16. opts.dir = canonicalDir
  17. openZip(opts)
  18. })
  19. })
  20. function openZip () {
  21. debug('opening', zipPath, 'with opts', opts)
  22. yauzl.open(zipPath, {lazyEntries: true}, function (err, zipfile) {
  23. if (err) return cb(err)
  24. var cancelled = false
  25. zipfile.on('error', function (err) {
  26. if (err) {
  27. cancelled = true
  28. return cb(err)
  29. }
  30. })
  31. zipfile.readEntry()
  32. zipfile.on('close', function () {
  33. if (!cancelled) {
  34. debug('zip extraction complete')
  35. cb()
  36. }
  37. })
  38. zipfile.on('entry', function (entry) {
  39. if (cancelled) {
  40. debug('skipping entry', entry.fileName, {cancelled: cancelled})
  41. return
  42. }
  43. debug('zipfile entry', entry.fileName)
  44. if (/^__MACOSX\//.test(entry.fileName)) {
  45. // dir name starts with __MACOSX/
  46. zipfile.readEntry()
  47. return
  48. }
  49. var destDir = path.dirname(path.join(opts.dir, entry.fileName))
  50. mkdirp(destDir, function (err) {
  51. if (err) {
  52. cancelled = true
  53. zipfile.close()
  54. return cb(err)
  55. }
  56. fs.realpath(destDir, function (err, canonicalDestDir) {
  57. if (err) {
  58. cancelled = true
  59. zipfile.close()
  60. return cb(err)
  61. }
  62. var relativeDestDir = path.relative(opts.dir, canonicalDestDir)
  63. if (relativeDestDir.split(path.sep).indexOf('..') !== -1) {
  64. cancelled = true
  65. zipfile.close()
  66. return cb(new Error('Out of bound path "' + canonicalDestDir + '" found while processing file ' + entry.fileName))
  67. }
  68. extractEntry(entry, function (err) {
  69. // if any extraction fails then abort everything
  70. if (err) {
  71. cancelled = true
  72. zipfile.close()
  73. return cb(err)
  74. }
  75. debug('finished processing', entry.fileName)
  76. zipfile.readEntry()
  77. })
  78. })
  79. })
  80. })
  81. function extractEntry (entry, done) {
  82. if (cancelled) {
  83. debug('skipping entry extraction', entry.fileName, {cancelled: cancelled})
  84. return setImmediate(done)
  85. }
  86. if (opts.onEntry) {
  87. opts.onEntry(entry, zipfile)
  88. }
  89. var dest = path.join(opts.dir, entry.fileName)
  90. // convert external file attr int into a fs stat mode int
  91. var mode = (entry.externalFileAttributes >> 16) & 0xFFFF
  92. // check if it's a symlink or dir (using stat mode constants)
  93. var IFMT = 61440
  94. var IFDIR = 16384
  95. var IFLNK = 40960
  96. var symlink = (mode & IFMT) === IFLNK
  97. var isDir = (mode & IFMT) === IFDIR
  98. // Failsafe, borrowed from jsZip
  99. if (!isDir && entry.fileName.slice(-1) === '/') {
  100. isDir = true
  101. }
  102. // check for windows weird way of specifying a directory
  103. // https://github.com/maxogden/extract-zip/issues/13#issuecomment-154494566
  104. var madeBy = entry.versionMadeBy >> 8
  105. if (!isDir) isDir = (madeBy === 0 && entry.externalFileAttributes === 16)
  106. // if no mode then default to default modes
  107. if (mode === 0) {
  108. if (isDir) {
  109. if (opts.defaultDirMode) mode = parseInt(opts.defaultDirMode, 10)
  110. if (!mode) mode = 493 // Default to 0755
  111. } else {
  112. if (opts.defaultFileMode) mode = parseInt(opts.defaultFileMode, 10)
  113. if (!mode) mode = 420 // Default to 0644
  114. }
  115. }
  116. debug('extracting entry', { filename: entry.fileName, isDir: isDir, isSymlink: symlink })
  117. // reverse umask first (~)
  118. var umask = ~process.umask()
  119. // & with processes umask to override invalid perms
  120. var procMode = mode & umask
  121. // always ensure folders are created
  122. var destDir = dest
  123. if (!isDir) destDir = path.dirname(dest)
  124. debug('mkdirp', {dir: destDir})
  125. mkdirp(destDir, function (err) {
  126. if (err) {
  127. debug('mkdirp error', destDir, {error: err})
  128. cancelled = true
  129. return done(err)
  130. }
  131. if (isDir) return done()
  132. debug('opening read stream', dest)
  133. zipfile.openReadStream(entry, function (err, readStream) {
  134. if (err) {
  135. debug('openReadStream error', err)
  136. cancelled = true
  137. return done(err)
  138. }
  139. readStream.on('error', function (err) {
  140. console.log('read err', err)
  141. })
  142. if (symlink) writeSymlink()
  143. else writeStream()
  144. function writeStream () {
  145. var writeStream = fs.createWriteStream(dest, {mode: procMode})
  146. readStream.pipe(writeStream)
  147. writeStream.on('finish', function () {
  148. done()
  149. })
  150. writeStream.on('error', function (err) {
  151. debug('write error', {error: err})
  152. cancelled = true
  153. return done(err)
  154. })
  155. }
  156. // AFAICT the content of the symlink file itself is the symlink target filename string
  157. function writeSymlink () {
  158. readStream.pipe(concat(function (data) {
  159. var link = data.toString()
  160. debug('creating symlink', link, dest)
  161. fs.symlink(link, dest, function (err) {
  162. if (err) cancelled = true
  163. done(err)
  164. })
  165. }))
  166. }
  167. })
  168. })
  169. }
  170. })
  171. }
  172. }