[Pkg-javascript-commits] [node-zipfile] 06/34: New upstream version 0.5.11+ds
Jérémy Lal
kapouer at moszumanska.debian.org
Wed Dec 21 00:22:48 UTC 2016
This is an automated email from the git hooks/post-receive script.
kapouer pushed a commit to branch master
in repository node-zipfile.
commit 4691529723a3debde821e04cf591f484e8cbf088
Author: Jérémy Lal <kapouer at melix.org>
Date: Tue Dec 20 16:13:22 2016 +0100
New upstream version 0.5.11+ds
---
.gitignore | 3 +-
.npmignore | 13 ++
.travis.yml | 117 +++++++---
CHANGELOG.md | 48 ++++
Makefile | 67 ++++--
README.md | 59 ++++-
appveyor.yml | 72 ++++++
bench/largefile.js | 76 ++++++
binding.gyp | 32 ++-
deps/common-libzip.gypi | 57 ++++-
deps/solaris-include/config.h | 198 ++++++++++++++++
deps/solaris-include/zipconf.h | 47 ++++
package.json | 24 +-
scripts/install_node.sh | 9 +
scripts/package_osx.sh | 25 --
scripts/validate_tag.sh | 24 ++
src/node_zipfile.cpp | 465 +++++++++++++++++++++++--------------
src/node_zipfile.hpp | 43 ++--
src/unicode_conversion_helpers.hpp | 68 ++++++
test/data/World_mercator.zip | Bin 0 -> 346592 bytes
test/exceptions.test.js | 12 +
test/write.test.js | 78 ++++---
22 files changed, 1191 insertions(+), 346 deletions(-)
diff --git a/.gitignore b/.gitignore
index 40aa8ac..bf0b73f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,5 @@ build
deps/libzip-0.10
lib/binding
node_modules
-test/tmp
\ No newline at end of file
+test/tmp
+npm-debug.log
\ No newline at end of file
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..a2bbe42
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,13 @@
+.gitignore
+.npmignore
+node_modules
+lib/binding
+build
+test
+benchmark
+configure
+Makefile
+scripts
+.travis.yml
+examples
+npm-debug.log
diff --git a/.travis.yml b/.travis.yml
index 7f44cb0..a0b3471 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,54 +1,95 @@
language: cpp
-compiler:
- - gcc
- - clang
+addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.5
+ packages:
+ - clang-3.5
+
+matrix:
+ include:
+ # Coverage
+ - os: osx
+ compiler: clang
+ env: NODE_VERSION="4" COVERAGE=true # node abi 46
+ # Linux
+ - os: linux
+ compiler: clang
+ env: NODE_VERSION="7" # node abi 48
+ - os: linux
+ compiler: clang
+ env: NODE_VERSION="6" # node abi 48
+ - os: linux
+ compiler: clang
+ env: NODE_VERSION="4" # node abi 46
+ - os: linux
+ compiler: clang
+ env: NODE_VERSION="0.10" # node abi 11
+ # OS X
+ - os: osx
+ compiler: clang
+ env: NODE_VERSION="7" # node abi 47
+ - os: osx
+ compiler: clang
+ env: NODE_VERSION="6" # node abi 47
+ - os: osx
+ compiler: clang
+ env: NODE_VERSION="4" # node abi 46
+ - os: osx
+ compiler: clang
+ env: NODE_VERSION="0.10" # node abi 11
env:
- matrix:
- - NODE_NVM_VERSION="0.10"
- - NODE_NVM_VERSION="0.8"
global:
+ - JOBS: "8"
- secure: hBUfRqVPovL7PVOJONI8sakIUtggpM74qMPdi5zaMpJhuV/QWfROOVc05ULEr1P0Fra2WpQ62mp8lfa1NbB6sQfT/8Y6u0lucf9SsIUBJzDrSmfXv2NDgpJn9RQmfsZgLfDuTwRLVROkNSTowUq3tnhDIzX/NyB7uOp1TZNEJ8A=
- secure: xWyq1Ys9lpMUVCh73q5YDDfC4nLeeydqIS4S+lJ/t/jUCNHDwe1x5XrxRIALi74qNmHg6eTcOeEW5iot/sf1oUJIA1oPt9iMIMolg9iYWJKWN4E6gWcIigYu9ZDl3GJsHyiNs/dVlZjzY1YKzyvgZ2MRfy4l0rPShCxROoCiCIM=
before_install:
- - COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n')
- # here we set up the node version on the fly based on the matrix value.
- # This is done manually so that it is easy to flip the 'language' to
- # objective-c in another branch (to run the same travis.yml on OS X)
- - git clone https://github.com/creationix/nvm.git ../.nvm
- - source ../.nvm/nvm.sh
- - nvm install $NODE_NVM_VERSION
- - nvm use $NODE_NVM_VERSION
- - node --version
- - npm --version
- - sudo apt-get -qq update
- - npm install mocha
- - npm install aws-sdk
+ - scripts/validate_tag.sh
+ - export COVERAGE=${COVERAGE:-false}
+ - if [[ $(uname -s) == 'Linux' ]]; then
+ export CXX="clang++-3.5";
+ export CC="clang-3.5";
+ export PYTHONPATH=$(pwd)/mason_packages/.link/lib/python2.7/site-packages;
+ else
+ export PYTHONPATH=$(pwd)/mason_packages/.link/lib/python/site-packages;
+ fi;
+ - source ./scripts/install_node.sh ${NODE_VERSION}
+ - export PATH=./node_modules/.bin/:$PATH
install:
- # test building from source
- - npm install --build-from-source
- - npm test
+ - COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n')
+ - if [[ ${COVERAGE} == true ]]; then
+ if [[ $(uname -s) == 'Linux' ]]; then
+ PYTHONUSERBASE=$(pwd)/mason_packages/.link pip install --user cpp-coveralls;
+ else
+ PYTHONUSERBASE=$(pwd)/mason_packages/.link easy_install --user cpp-coveralls;
+ fi;
+ export CXXFLAGS="--coverage";
+ export LDFLAGS="--coverage";
+ npm install --build-from-source --clang=1 --debug;
+ else
+ npm install --build-from-source --clang=1;
+ fi
- node-pre-gyp package testpackage
- - npm test
+ - if [[ $(uname -s) == 'Linux' ]]; then
+ ldd ./lib/*/*/*node;
+ else
+ otool -L ./lib/*/*/*node;
+ fi
before_script:
- # test publishing and installing from remote if
- # [publish binary] is present in commit message
- - PUBLISH_BINARY=false
- - if [[ ${CXX} == "g++" ]] && test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then echo yes;PUBLISH_BINARY=true; fi;
- - if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp publish info; rm -rf {build,lib/binding}; npm install --fallback-to-build=false; npm test; fi
- - node-pre-gyp clean
-
-script:
- # test building with against shared libzip
- - make clean
- - sudo apt-get -qq install libzip-dev
- - npm install --build-from-source --shared_libzip
- npm test
+ - if [[ ${CXX} =~ "clang" ]] && [[ ${COVERAGE} == false ]]; then
+ if [[ ${COMMIT_MESSAGE} =~ "[publish binary]" ]]; then
+ node-pre-gyp publish;
+ elif [[ ${COMMIT_MESSAGE} =~ "[republish binary]" ]]; then
+ node-pre-gyp unpublish publish;
+ fi
+ fi
-after_success:
- # if success then query and display all published binaries
- - node-pre-gyp info
+script:
+ - if [[ ${COVERAGE} == true ]]; then ./mason_packages/.link/bin/cpp-coveralls --exclude node_modules --exclude tests --build-root build --gcov-options '\-lp' --exclude tools --exclude docs --exclude sdk --exclude build/Release/obj/gen --exclude src/node_zipfile.hpp --exclude deps > /dev/null; fi;
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 513129d..b5824f8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,53 @@
# changelog
+## v0.5.11
+
+ - Republished with `mkdirp` inside node_modules/node-pre-gyp/node_modules/
+
+## v0.5.10
+
+ - Added support for node v6, v7
+ - Upgraded to nan at 2.4.x
+ - Fixed resource leak (#69)
+
+## v0.5.9
+
+ - Upgraded to zlib 1.2.8
+
+## v0.5.8
+
+ - Updated to work with NAN 2 and Node.js 4/5 (@elaberge)
+
+## v0.5.7
+
+ - Updated node-pre-gyp to v0.6.2
+ - Support for io.js v1.0.2
+
+## v0.5.6
+
+ - Support for building against io.js v1.0.1
+
+## v0.5.5
+
+ - Added copyFile method for efficient handling of large zip archive members.
+
+## v0.5.4
+
+ - Now supporting node v.11.14 and Visual Studio 2014 (--toolset=v140)
+
+## v0.5.3
+
+ - Now supporting node v.11.x
+
+## v0.5.2
+
+ - Fixed bundling of node-pre-gyp
+
+## v0.5.1
+
+ - Fixed Solaris build
+ - Fixed potential segfault when an invalid filename is requested from `zipfile.ReadFile` (#46)
+
## v0.5.0
- Now supporting binary deploy through node-pre-gyp (#42). Run `npm install --build-from-source` now to build from source instead of installing from a binary.
diff --git a/Makefile b/Makefile
index 3d06606..60ef931 100755
--- a/Makefile
+++ b/Makefile
@@ -1,34 +1,57 @@
-all: zipfile.node
+#http://www.gnu.org/prep/standards/html_node/Standard-Targets.html#Standard-Targets
-zipfile.node:
- PATH=`npm explore npm -g -- pwd`/bin/node-gyp-bin:./node_modules/.bin:$${PATH} && ./node_modules/.bin/node-pre-gyp build
+all: build-all
+
+./node_modules/node-pre-gyp:
+ npm install node-pre-gyp
+
+./node_modules: ./node_modules/node-pre-gyp
+ npm install `node -e "console.log(Object.keys(require('./package.json').dependencies).join(' '))"` \
+ `node -e "console.log(Object.keys(require('./package.json').devDependencies).join(' '))"` --clang=1
+
+./build:
+ ./node_modules/.bin/node-pre-gyp configure --loglevel=error --clang=1
+
+build-all: ./node_modules ./build
+ ./node_modules/.bin/node-pre-gyp build --loglevel=error --clang=1
+
+debug: ./node_modules ./build
+ ./node_modules/.bin/node-pre-gyp build --debug --clang=1
+
+coverage: ./node_modules ./build
+ ./node_modules/.bin/node-pre-gyp build --debug --clang=1 --coverage=true
+
+verbose: ./node_modules
+ ./node_modules/.bin/node-pre-gyp build --loglevel=verbose --clang=1
clean:
@rm -rf ./build
- rm -rf lib/bindings/
- rm -f test/tmp/*
- rm -rf ./deps/libzip-0.10/
- rm -rf ./build
- rm -rf ./out
+ rm -rf lib/binding/
+ rm -rf ./test/tmp/*
+ rm -rf ./node_modules/
+ rm -f ./*tgz
+
+grind:
+ valgrind --leak-check=full node node_modules/.bin/_mocha
+
+testpack:
+ rm -f ./*tgz
+ npm pack
+ tar -ztvf *tgz
+ rm -f ./*tgz
rebuild:
@make clean
- @./configure
@make
+ifndef only
test:
- @PATH=./node_modules/mocha/bin:${PATH} && NODE_PATH=./lib:$NODE_PATH mocha -R spec
-
-fix:
- @fixjsstyle lib/*js bin/*js test/*js
-
-fixc:
- @tools/fix_cpp_style.sh
-
-lint:
- @./node_modules/.bin/jshint lib/*js bin/*js test/*js
+ @PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec
+else
+test:
+ @PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec test/${only}.test.js
+endif
-lintc:
- @cpplint.py --verbose=3 --filter=-legal,-build/namespaces,-whitespace/line_length src/*.* include/zipfile/*.*
+check: test
-.PHONY: test lint fix lintc fixc
\ No newline at end of file
+.PHONY: test clean build
diff --git a/README.md b/README.md
index 2684f73..d787ce0 100644
--- a/README.md
+++ b/README.md
@@ -3,21 +3,50 @@
Bindings to [libzip](http://nih.at/libzip/libzip.html) for handling zipfile archives in [node](http://nodejs.org).
[![Build Status](https://secure.travis-ci.org/mapbox/node-zipfile.png)](http://travis-ci.org/mapbox/node-zipfile)
+[![Build status](https://ci.appveyor.com/api/projects/status/fb8n98fc1smsjmum)](https://ci.appveyor.com/project/Mapbox/node-zipfile)
+[![Dependencies](https://david-dm.org/mapbox/node-zipfile.png)](https://david-dm.org/mapbox/node-zipfile)
+[![Coverage Status](https://coveralls.io/repos/mapbox/node-zipfile/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapbox/node-zipfile?branch=master)
## Example
- var zipfile = require('zipfile');
- var zf = new zipfile.ZipFile('./test/data/world_merc.zip');
- zf
- { names: [ 'world_merc.dbf', 'world_merc.prj', 'world_merc.shp', 'world_merc.shx' ],
- count: 4 }
- var buffer = zf.readFileSync('world_merc.prj');
- buffer.toString()
- 'PROJCS["Google Maps Global Mercator",GEOGCS .... '
+```js
+var zipfile = require('zipfile');
+
+// Creating a zipfile object
+var zf = new zipfile.ZipFile('./test/data/world_merc.zip');
+
+// the zipfile has a list of names:
+// zf.names[0] === 'world_merc.prj'
+
+// the zipfile also has a count property that is the number of files contained
+// zf.count == 2
+
+// finally it has a readFile method that uncompresses a single file
+// into a Buffer object
+zf.readFile('world_merc.prj', function(err, buffer) {
+ if (err) throw err;
+ console.log(buffer.toString());
+});
+```
+
+### Large files
+
+To handle large zipfiles and avoid the overhead of passing data from C++ to JS use the `copyFile` interface:
+
+```js
+var zipfile = require('zipfile');
+var zf = new zipfile.ZipFile('./test/data/world_merc.zip');
+var zip_entry_name = 'world_merc.shp';
+var output_file = 'out/world_merc.shp';
+zf.copyFile(zip_entry_name,output_file, function(err) {
+ if (err) throw err;
+ console.log('Successfully wrote ' + output_file);
+});
+```
## Depends
- - Node v0.10.x or v0.8.x
+ - Node v0.10.x, v4.x, v5.x, or v6.x
## Installation
@@ -50,8 +79,16 @@ Then configure node-zipfile with the --shared_libzip option:
If you installed libzip in a custom location then configure like:
- npm install --build-from-source --shared_libzip --shared_libzip_includes=/opt/local/include --shared_libzip_libpath=/opt/local/lib
+ npm install --build-from-source --shared_libzip \
+ --shared_libzip_includes=/opt/local/include \
+ --shared_libzip_libpath=/opt/local/lib
+
+If you installed libzip with homebrew do:
+
+ npm install --build-from-source --shared_libzip \
+ --shared_libzip_includes=`brew --prefix`/include \
+ --shared_libzip_libpath=`brew --prefix`/lib
## License
- BSD, see LICENSE.txt
\ No newline at end of file
+ BSD, see LICENSE.txt
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..7bba2fc
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,72 @@
+os: Visual Studio 2015
+
+environment:
+ node_pre_gyp_accessKeyId:
+ secure: 7DrSVc5eIGtmMcki5H+iRft+Tk3MJTwDBQEUuJHWaQ4=
+ node_pre_gyp_secretAccessKey:
+ secure: 1amwJJw9fu0j6dXnc5KsAQbSYf7Cjw/dapT6OZWABa6nc52grkKeLQ+DGaOfQz8i
+ matrix:
+ - nodejs_version: 0.10
+ platform: x86
+ msvs_toolset: 12
+ - nodejs_version: 0.10
+ platform: x64
+ msvs_toolset: 12
+ - nodejs_version: 4
+ platform: x86
+ msvs_toolset: 12
+ - nodejs_version: 4
+ platform: x64
+ msvs_toolset: 12
+ - nodejs_version: 6
+ platform: x86
+ msvs_toolset: 12
+ - nodejs_version: 6
+ platform: x64
+ msvs_toolset: 12
+ - nodejs_version: 7
+ platform: x86
+ msvs_toolset: 12
+ - nodejs_version: 7
+ platform: x64
+ msvs_toolset: 12
+
+install:
+ # add local node to path (since we install it for msvs_toolset == 14)
+ - SET PATH=%CD%;%PATH%;
+ # add local node-pre-gyp dir to path
+ - SET PATH=node_modules\.bin;%PATH%
+ # use 64 bit python if platform is 64 bit
+ - if "%PLATFORM%" == "x64" set PATH=C:\Python27-x64;%PATH%
+ - SET ARCHPATH=
+ - if %platform% == x64 (SET ARCHPATH=x64/)
+ # install node version per visual studio toolset
+ - if "%msvs_toolset%" == "12" powershell Install-Product node $env:nodejs_version $env:Platform
+ - if "%msvs_toolset%" == "14" powershell Write-Output "fetching https://mapbox.s3.amazonaws.com/node-cpp11/v$env:nodejs_version/${env:ARCHPATH}node.exe"
+ - if "%msvs_toolset%" == "14" powershell Start-FileDownload "https://mapbox.s3.amazonaws.com/node-cpp11/v$env:nodejs_version/${env:ARCHPATH}node.exe"
+ - node -v
+ - node -e "console.log(process.argv,process.execPath)"
+ - SET PATH=C:\Program Files (x86)\MSBuild\%msvs_toolset%.0\bin;%PATH%
+ - SET PATH=C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\bin;%PATH%
+ - if %platform% == x64 CALL "C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\vcvarsall.bat" amd64
+ - if %platform% == x86 CALL "C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\vcvarsall.bat" amd64_x86
+ - npm install --build-from-source --msvs_version=2013 %TOOLSET_ARGS% --loglevel=http
+ - node_modules\.bin\node-pre-gyp reveal module --silent > module.txt
+ - SET /p MODULE=<module.txt
+ - del module.txt
+ - node -e "console.log(process.execPath)" > node_path.txt
+ - SET /p NODE_EXE_PATH=<node_path.txt
+ - del node_path.txt
+ # should display MSVCP140.dll if build with visual studio 2014 and /MD
+ - dumpbin /DEPENDENTS "%NODE_EXE_PATH%"
+ - dumpbin /DEPENDENTS "%MODULE%"
+ - npm test
+ - node-pre-gyp package %TOOLSET_ARGS%
+ # make commit message env var shorter
+ - SET CM=%APPVEYOR_REPO_COMMIT_MESSAGE%
+ - if not "%CM%" == "%CM:[publish binary]=%" node-pre-gyp --msvs_version=2013 publish %TOOLSET_ARGS%
+ - if not "%CM%" == "%CM:[republish binary]=%" node-pre-gyp --msvs_version=2013 unpublish publish %TOOLSET_ARGS%
+
+build: OFF
+test: OFF
+deploy: OFF
diff --git a/bench/largefile.js b/bench/largefile.js
new file mode 100644
index 0000000..8c071d9
--- /dev/null
+++ b/bench/largefile.js
@@ -0,0 +1,76 @@
+var path = require('path');
+var fs = require('fs');
+var os = require('os');
+var zipfile = require('../lib');
+var assert = require('assert');
+var crypto = require('crypto');
+var shasum = crypto.createHash('md5');
+var queue = require('queue-async');
+
+/*
+
+Setup:
+
+wget http://mapbox.s3.amazonaws.com/tmp/too-large.zip
+
+Usage:
+
+ node bench/largefile.js /path/to/file.zip
+
+*/
+
+if (process.argv.length < 3) {
+ console.log("please provide path to zip archive")
+ process.exit(1)
+}
+
+var filepath = process.argv[2];
+
+if (!fs.existsSync(filepath)) {
+ console.log('file not downloaded '+ filepath);
+ process.exit(1);
+}
+
+function copy(zf,name,cb) {
+ zf.copyFile(name,name,function(err) {
+ cb(err,name);
+ });
+}
+
+function unzip(err) {
+ if (err) throw err;
+ console.log('Unzipping...');
+ console.time('opening');
+ var zf = new zipfile.ZipFile(filepath);
+ console.timeEnd('opening');
+ console.time('copying');
+ var q = queue(10);
+ zf.names.forEach(function(name) {
+ q.defer(copy,zf,name);
+ })
+ q.awaitAll(function(err, results) {
+ console.timeEnd('copying');
+ if (err) throw err;
+ assert.equal(results.length,zf.names.length);
+ if (results.indexOf('US_OG_022014.dbf') > -1) {
+ validate('US_OG_022014.dbf','e0da2edc680bf10dd11decdcec1e521a');
+ }
+ });
+}
+
+function validate(filename,expected_md5) {
+ var s = fs.ReadStream(filename);
+ console.time('validating')
+ s.on('data', function(d) {
+ shasum.update(d);
+ });
+
+ s.on('end', function() {
+ var d = shasum.digest('hex');
+ console.log(d + ' ' + filename);
+ assert.equal(d,expected_md5);
+ console.timeEnd('validating')
+ });
+}
+
+unzip()
\ No newline at end of file
diff --git a/binding.gyp b/binding.gyp
index 8e0a1c5..7eec9a0 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -8,6 +8,30 @@
'targets': [
{
'target_name': '<(module_name)',
+ "include_dirs" : [
+ "<!(node -e \"require('nan')\")"
+ ],
+ 'defines': [
+ 'MODULE_NAME=<(module_name)'
+ ],
+ 'sources': [
+ 'src/node_zipfile.cpp'
+ ],
+ 'ldflags': [
+ '-Wl,-z,now',
+ ],
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS':[
+ '-Wl,-bind_at_load'
+ ],
+ 'GCC_ENABLE_CPP_RTTI': 'YES',
+ 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
+ 'MACOSX_DEPLOYMENT_TARGET':'10.8',
+ 'CLANG_CXX_LIBRARY': 'libc++',
+ 'CLANG_CXX_LANGUAGE_STANDARD':'c++11',
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0'
+ },
+ 'cflags_cc!': ['-fno-exceptions'],
'conditions': [
['shared_libzip == "false"', {
'dependencies': [
@@ -25,13 +49,7 @@
]
}
]
- ],
- 'defines': [
- 'MODULE_NAME=<(module_name)'
- ],
- 'sources': [
- 'src/node_zipfile.cpp'
- ],
+ ]
},
{
'target_name': 'action_after_build',
diff --git a/deps/common-libzip.gypi b/deps/common-libzip.gypi
index 4eaf7b1..9c2c767 100644
--- a/deps/common-libzip.gypi
+++ b/deps/common-libzip.gypi
@@ -1,5 +1,60 @@
{
'variables': {
- 'libzip_version%':'0.11.1'
+ 'libzip_version%':'0.11.1',
+ "toolset%":'',
+ },
+ 'target_defaults': {
+ 'default_configuration': 'Release',
+ 'msbuild_toolset':'<(toolset)',
+ 'cflags_cc' : [
+ '-std=c++11',
+ ],
+ 'cflags_cc!': ['-std=gnu++0x','-fno-rtti', '-fno-exceptions'],
+ 'configurations': {
+ 'Debug': {
+ 'defines!': [
+ 'NDEBUG'
+ ],
+ 'cflags_cc!': [
+ '-O3',
+ '-Os',
+ '-DNDEBUG'
+ ],
+ 'xcode_settings': {
+ 'OTHER_CPLUSPLUSFLAGS!': [
+ '-O3',
+ '-Os',
+ '-DDEBUG'
+ ],
+ 'GCC_OPTIMIZATION_LEVEL': '0',
+ 'GCC_GENERATE_DEBUGGING_SYMBOLS': 'YES'
+ },
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'ExceptionHandling': 1, # /EHsc
+ }
+ }
+ },
+ 'Release': {
+ 'defines': [
+ 'NDEBUG'
+ ],
+ 'xcode_settings': {
+ 'OTHER_CPLUSPLUSFLAGS!': [
+ '-Os',
+ '-O2'
+ ],
+ 'GCC_OPTIMIZATION_LEVEL': '3',
+ 'GCC_GENERATE_DEBUGGING_SYMBOLS': 'NO',
+ 'DEAD_CODE_STRIPPING': 'YES',
+ 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES'
+ },
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'ExceptionHandling': 1, # /EHsc
+ }
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/deps/solaris-include/config.h b/deps/solaris-include/config.h
new file mode 100644
index 0000000..358c9f7
--- /dev/null
+++ b/deps/solaris-include/config.h
@@ -0,0 +1,198 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't.
+ */
+/* #undef HAVE_DECL_TZNAME */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `fseeko' function. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `ftello' function. */
+#define HAVE_FTELLO 1
+
+/* Define to 1 if you have the `getopt' function. */
+#define HAVE_GETOPT 1
+
+/* Define to 1 if the system has the type `int16_t'. */
+#define HAVE_INT16_T 1
+
+/* Define to 1 if the system has the type `int32_t'. */
+#define HAVE_INT32_T 1
+
+/* Define to 1 if the system has the type `int64_t'. */
+#define HAVE_INT64_T 1
+
+/* Define to 1 if the system has the type `int8_t'. */
+#define HAVE_INT8_T 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `z' library (-lz). */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `MoveFileExA' function. */
+/* #undef HAVE_MOVEFILEEXA */
+
+/* Define to 1 if you have the `open' function. */
+#define HAVE_OPEN 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#define HAVE_SSIZE_T 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if `tm_zone' is a member of `struct tm'. */
+// https://github.com/mapbox/node-zipfile/issues/43#issuecomment-37463945
+//#define HAVE_STRUCT_TM_TM_ZONE 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
+ `HAVE_STRUCT_TM_TM_ZONE' instead. */
+#define HAVE_TM_ZONE 0
+
+/* Define to 1 if you don't have `tm_zone' but do have the external array
+ `tzname'. */
+/* #undef HAVE_TZNAME */
+
+/* Define to 1 if the system has the type `uint16_t'. */
+#define HAVE_UINT16_T 1
+
+/* Define to 1 if the system has the type `uint32_t'. */
+#define HAVE_UINT32_T 1
+
+/* Define to 1 if the system has the type `uint64_t'. */
+#define HAVE_UINT64_T 1
+
+/* Define to 1 if the system has the type `uint8_t'. */
+#define HAVE_UINT8_T 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `_close' function. */
+/* #undef HAVE__CLOSE */
+
+/* Define to 1 if you have the `_dup' function. */
+/* #undef HAVE__DUP */
+
+/* Define to 1 if you have the `_fdopen' function. */
+/* #undef HAVE__FDOPEN */
+
+/* Define to 1 if you have the `_fileno' function. */
+/* #undef HAVE__FILENO */
+
+/* Define to 1 if you have the `_open' function. */
+/* #undef HAVE__OPEN */
+
+/* Define to 1 if you have the `_snprintf' function. */
+/* #undef HAVE__SNPRINTF */
+
+/* Define to 1 if you have the `_strdup' function. */
+/* #undef HAVE__STRDUP */
+
+/* Define to 1 if you have the `_stricmp' function. */
+/* #undef HAVE__STRICMP */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "libzip"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "libzip at nih.at"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libzip"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libzip 0.11.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libzip"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.11.1"
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `long long', as computed by sizeof. */
+#define SIZEOF_LONG_LONG 8
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Version number of package */
+#define VERSION "0.11.1"
+
+
+#ifndef HAVE_SSIZE_T
+# if SIZEOF_SIZE_T == SIZEOF_INT
+typedef int ssize_t;
+# elif SIZEOF_SIZE_T == SIZEOF_LONG
+typedef long ssize_t;
+# elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+typedef long long ssize_t;
+# else
+#error no suitable type for ssize_t found
+# endif
+#endif
+
diff --git a/deps/solaris-include/zipconf.h b/deps/solaris-include/zipconf.h
new file mode 100644
index 0000000..f223c6b
--- /dev/null
+++ b/deps/solaris-include/zipconf.h
@@ -0,0 +1,47 @@
+#ifndef _HAD_ZIPCONF_H
+#define _HAD_ZIPCONF_H
+
+/*
+ zipconf.h -- platform specific include file
+
+ This file was generated automatically by ./make_zipconf.sh
+ based on ../config.h.
+ */
+
+#define LIBZIP_VERSION "0.11.1"
+#define LIBZIP_VERSION_MAJOR 0
+#define LIBZIP_VERSION_MINOR 11
+#define LIBZIP_VERSION_MICRO 0
+
+#include <inttypes.h>
+
+typedef int8_t zip_int8_t;
+#define ZIP_INT8_MIN INT8_MIN
+#define ZIP_INT8_MAX INT8_MAX
+
+typedef uint8_t zip_uint8_t;
+#define ZIP_UINT8_MAX UINT8_MAX
+
+typedef int16_t zip_int16_t;
+#define ZIP_INT16_MIN INT16_MIN
+#define ZIP_INT16_MAX INT16_MAX
+
+typedef uint16_t zip_uint16_t;
+#define ZIP_UINT16_MAX UINT16_MAX
+
+typedef int32_t zip_int32_t;
+#define ZIP_INT32_MIN INT32_MIN
+#define ZIP_INT32_MAX INT32_MAX
+
+typedef uint32_t zip_uint32_t;
+#define ZIP_UINT32_MAX UINT32_MAX
+
+typedef int64_t zip_int64_t;
+#define ZIP_INT64_MIN INT64_MIN
+#define ZIP_INT64_MAX INT64_MAX
+
+typedef uint64_t zip_uint64_t;
+#define ZIP_UINT64_MAX UINT64_MAX
+
+
+#endif /* zipconf.h */
diff --git a/package.json b/package.json
index 9b8af6d..c5c488f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name" : "zipfile",
- "version" : "0.5.0",
+ "version" : "0.5.11",
"main" : "./lib/index.js",
"description" : "C++ library for handling zipfiles in node",
"keywords" : ["zipfile", "uncompress", "unzip", "zlib"],
@@ -13,27 +13,31 @@
"contributors" : [],
"licenses" : ["BSD"],
"dependencies" : {
- "node-pre-gyp": "0.5.x"
+ "nan": "~2.4.0",
+ "node-pre-gyp": "~0.6.30"
},
- "bundledDependencies":["node-pre-gyp"],
"devDependencies": {
- "mocha": "*",
- "mkdirp": "~0.3.0",
- "jshint" : "~0.5.x"
+ "mocha": "~2.3.3",
+ "mkdirp": "~0.5.1",
+ "aws-sdk": "2.x",
+ "queue-async":"~1.2.1"
},
- "bin" : {
+ "bundledDependencies": [
+ "node-pre-gyp"
+ ],
+ "bin" : {
"unzip.js" : "./bin/unzip.js"
},
- "engines" : { "node": ">= 0.6.13 < 0.11.0" },
"scripts" : {
+ "prepublish": "npm ls",
"test" : "mocha -R spec",
"install" : "node-pre-gyp install --fallback-to-build"
},
"binary": {
"module_name" : "zipfile",
- "module_path" : "./lib/binding/",
+ "module_path" : "./lib/binding/{node_abi}-{platform}-{arch}",
"host" : "https://mapbox-node-binary.s3.amazonaws.com",
- "remote_path" : "./{module_name}/v{version}",
+ "remote_path" : "./{name}/v{version}/{toolset}/",
"package_name": "{node_abi}-{platform}-{arch}.tar.gz"
}
}
diff --git a/scripts/install_node.sh b/scripts/install_node.sh
new file mode 100755
index 0000000..1ae9fe1
--- /dev/null
+++ b/scripts/install_node.sh
@@ -0,0 +1,9 @@
+# here we set up the node version on the fly based on the matrix value.
+# This is done manually so that the build works the same on OS X
+rm -rf ~/.nvm/ && git clone --depth 1 https://github.com/creationix/nvm.git ~/.nvm
+source ~/.nvm/nvm.sh
+nvm install $1
+nvm use $1
+node --version
+npm --version
+which node
diff --git a/scripts/package_osx.sh b/scripts/package_osx.sh
deleted file mode 100755
index 293c7ef..0000000
--- a/scripts/package_osx.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-
-CURRENT_DIR="$( cd "$( dirname $BASH_SOURCE )" && pwd )"
-cd $CURRENT_DIR/../
-source ~/.nvm/nvm.sh
-nvm use 0.10
-
-set -u -e
-
-npm install node-gyp
-npm install aws-sdk
-export PATH=`pwd`/node_modules/.bin:$PATH
-
-function doit {
- rm -rf build
- node-pre-gyp clean build package testpackage "$@"
- npm test
- ./node_modules/.bin/node-pre-gyp publish info "$@"
- npm install --fallback-to-build=false
- npm test
-}
-
-doit
-nvm use 0.8
-doit --target=0.8.26
\ No newline at end of file
diff --git a/scripts/validate_tag.sh b/scripts/validate_tag.sh
new file mode 100755
index 0000000..67d039b
--- /dev/null
+++ b/scripts/validate_tag.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -u
+
+# let's catch the case where we tag but
+# forget to increment the package.json version
+
+# check if we are on a tag
+if [ `git describe --tags --always HEAD` ]; then
+ echo 'looks like we are on a tag'
+ if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]]; then
+ echo 'git reports the same tag as travis'
+ # now check to make sure package.json `version` matches
+ MODULE_VERSION=$(node -e "console.log(require('./package.json').version)")
+ if [[ $MODULE_VERSION != $TRAVIS_BRANCH ]] && [[ v$MODULE_VERSION != $TRAVIS_BRANCH ]]; then
+ echo "package.json version ($MODULE_VERSION) does not match tag ($TRAVIS_BRANCH)"
+ exit 1
+ else
+ echo "Validation success: package.json ($MODULE_VERSION) matches tag ($TRAVIS_BRANCH)"
+ fi
+ else
+ echo "warning: travis thinks the tag ($TRAVIS_BRANCH) differs from git (`git describe --tags --always HEAD`)"
+ fi
+fi
diff --git a/src/node_zipfile.cpp b/src/node_zipfile.cpp
index 1792d1c..f5f6297 100644
--- a/src/node_zipfile.cpp
+++ b/src/node_zipfile.cpp
@@ -1,105 +1,49 @@
#include "node_zipfile.hpp"
#include <node_version.h>
-#include <node_buffer.h>
+
+// libzip
+extern "C" {
+ #include <zlib.h>
+ #include <errno.h>
+ #include <zip.h>
+}
#ifdef _WINDOWS
-#include <Windows.h>
+#include "unicode_conversion_helpers.hpp"
#endif
// std
#include <sstream>
#include <iostream>
-#include <vector>
-#include <string>
#include <algorithm>
+#include <fstream>
+#include <stdexcept>
#define TOSTR(obj) (*String::Utf8Value((obj)->ToString()))
-#ifdef _WINDOWS
-std::string wstring2string(const std::wstring& s)
-{
- DWORD size = WideCharToMultiByte(CP_UTF8,
- 0,
- s.c_str(),
- -1,
- NULL,
- 0,
- NULL,
- NULL);
- if (size == 0) {
- // This should never happen.
- fprintf(stderr, "Could not convert arguments to utf8.");
- }
- char * buf_ptr = new char [size];
- DWORD result = WideCharToMultiByte(CP_ACP,
- 0,
- s.c_str(),
- -1,
- buf_ptr,
- size,
- NULL,
- NULL);
- if (result == 0) {
- // This should never happen.
- fprintf(stderr, "Could not convert arguments to utf8.");
- }
- std::string r(buf_ptr);
- delete buf_ptr;
- return r;
-}
+using namespace v8;
-std::wstring utf8ToWide( std::string const& s )
-{
- int ws_len, r;
- WCHAR* ws;
- ws_len = MultiByteToWideChar(CP_UTF8,
- 0,
- s.c_str(),
- -1,
- NULL,
- 0);
- ws = new wchar_t [ws_len * sizeof(WCHAR)];
- if (ws == NULL) {
- // This should never happen.
- fprintf(stderr, "Could not convert arguments from utf8.");
- exit(1);
- }
- r = MultiByteToWideChar(CP_UTF8,
- 0,
- s.c_str(),
- -1,
- ws,
- ws_len);
- if (r != ws_len) {
- // This should never happen.
- fprintf(stderr, "Could not do anything useful.");
- exit(1);
- }
- std::wstring rt(ws);
- delete ws;
- return rt;
-}
+Nan::Persistent<FunctionTemplate> ZipFile::constructor;
-#endif
-
-Persistent<FunctionTemplate> ZipFile::constructor;
-
-void ZipFile::Initialize(Handle<Object> target) {
- HandleScope scope;
- constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(ZipFile::New));
- constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(String::NewSymbol("ZipFile"));
+void ZipFile::Initialize(Local<Object> target) {
+ Nan::HandleScope scope;
+ Local<FunctionTemplate> lcons = Nan::New<FunctionTemplate>(ZipFile::New);
+ lcons->InstanceTemplate()->SetInternalFieldCount(1);
+ lcons->SetClassName(Nan::New("Zipfile").ToLocalChecked());
// functions
- NODE_SET_PROTOTYPE_METHOD(constructor, "readFileSync", readFileSync);
- NODE_SET_PROTOTYPE_METHOD(constructor, "readFile", readFile);
+ Nan::SetPrototypeMethod(lcons, "readFileSync", readFileSync);
+ Nan::SetPrototypeMethod(lcons, "readFile", readFile);
+ Nan::SetPrototypeMethod(lcons, "copyFileSync", copyFileSync);
+ Nan::SetPrototypeMethod(lcons, "copyFile", copyFile);
// properties
- constructor->InstanceTemplate()->SetAccessor(String::NewSymbol("count"), get_prop);
- constructor->InstanceTemplate()->SetAccessor(String::NewSymbol("names"), get_prop);
+ Nan::SetAccessor(lcons->InstanceTemplate(), Nan::New("count").ToLocalChecked(), get_prop);
+ Nan::SetAccessor(lcons->InstanceTemplate(), Nan::New("names").ToLocalChecked(), get_prop);
- target->Set(String::NewSymbol("ZipFile"), constructor->GetFunction());
+ target->Set(Nan::New("ZipFile").ToLocalChecked(),lcons->GetFunction());
+ constructor.Reset(lcons);
}
ZipFile::ZipFile(std::string const& file_name)
@@ -107,15 +51,21 @@ ZipFile::ZipFile(std::string const& file_name)
file_name_(file_name),
names_() {}
-Handle<Value> ZipFile::New(const Arguments& args) {
- HandleScope scope;
+void ZipFile::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
+{
+ Nan::HandleScope scope;
if (!args.IsConstructCall())
- return ThrowException(String::New("Cannot call constructor as function, you need to use 'new' keyword"));
+ {
+ Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword");
+ args.GetReturnValue().SetUndefined(); return;
+ }
if (args.Length() != 1 || !args[0]->IsString())
- return ThrowException(Exception::TypeError(
- String::New("first argument must be a path to a zipfile")));
+ {
+ Nan::ThrowError("first argument must be a path to a zipfile");
+ args.GetReturnValue().SetUndefined(); return;
+ }
std::string input_file = TOSTR(args[0]);
#ifdef _WINDOWS
@@ -123,14 +73,14 @@ Handle<Value> ZipFile::New(const Arguments& args) {
#endif
int err;
char errstr[1024];
- struct zip *za;
+ struct zip *za = NULL;
if ((za=zip_open(input_file.c_str(), ZIP_CHECKCONS, &err)) == NULL) {
zip_error_to_str(errstr, sizeof(errstr), err, errno);
std::stringstream s;
s << "cannot open file: " << input_file << " error: " << errstr << "\n";
- zip_close(za);
- return ThrowException(Exception::Error(
- String::New(s.str().c_str())));
+ if (za) zip_close(za);
+ Nan::ThrowError(s.str().c_str());
+ args.GetReturnValue().SetUndefined(); return;
}
ZipFile* zf = new ZipFile(input_file);
@@ -144,81 +94,243 @@ Handle<Value> ZipFile::New(const Arguments& args) {
std::string name = st.name;
zf->names_.push_back(name);
}
- zip_close(za);
+ if (za) zip_close(za);
zf->Wrap(args.This());
- return args.This();
+ args.GetReturnValue().Set(args.This());
}
-Handle<Value> ZipFile::get_prop(Local<String> property,
- const AccessorInfo& info) {
- HandleScope scope;
- ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(info.This());
+void ZipFile::get_prop(v8::Local<v8::String> property, const Nan::PropertyCallbackInfo<v8::Value>& args)
+{
+ ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.Holder());
std::string a = TOSTR(property);
if (a == "count") {
- return scope.Close(Integer::New(zf->names_.size()));
- }
- if (a == "names") {
+ args.GetReturnValue().Set(Nan::New<Integer>(static_cast<uint32_t>(zf->names_.size())));
+ } else if (a == "names") {
unsigned num = zf->names_.size();
- Local<Array> a = Array::New(num);
+ Local<Array> a = Nan::New<Array>(num);
for (unsigned i = 0; i < num; ++i) {
- a->Set(i, String::New(zf->names_[i].c_str()));
+ a->Set(i, Nan::New(zf->names_[i].c_str()).ToLocalChecked());
}
+ args.GetReturnValue().Set(a);
+ } else {
+ args.GetReturnValue().SetUndefined();
+ }
+}
+
+void _copyFile(std::string const& from, std::string const& to, ZipFile* zf)
+{
+ int idx = -1;
+ std::vector<std::string> const& names = zf->names();
+ std::vector<std::string>::const_iterator it = std::find(names.begin(), names.end(), from);
+ if (it != names.end()) {
+ idx = distance(names.begin(), it);
+ }
- return scope.Close(a);
+ if (idx == -1) {
+ std::stringstream s;
+ s << "No file found by the name of: '" << from << "\n";
+ throw std::runtime_error(s.str().c_str());
}
- return Undefined();
+
+ int err;
+ char errstr[1024];
+ struct zip *za = NULL;
+ std::string const& zip_filename = zf->file_name();
+ if ((za=zip_open(zip_filename.c_str(), ZIP_CHECKCONS, &err)) == NULL) {
+ zip_error_to_str(errstr, sizeof(errstr), err, errno);
+ std::stringstream s;
+ s << "cannot open file: " << zip_filename << " error: " << errstr << "\n";
+ if (za) zip_close(za);
+ throw std::runtime_error(s.str().c_str());
+ }
+
+ FILE * fo = fopen(to.c_str(), "wb");
+ if (!fo) {
+ std::stringstream s;
+ s << "Could not open for writing: '" << to << "\n";
+ throw std::runtime_error(s.str().c_str());
+ }
+
+ struct zip_file *zf_ptr = NULL;
+
+ if ((zf_ptr=zip_fopen_index(za, idx, 0)) == NULL) {
+ std::stringstream s;
+ s << "cannot open file #" << idx << " in " << from << ": archive error: " << zip_strerror(za) << "\n";
+ if (zf_ptr) zip_fclose(zf_ptr);
+ if (za) zip_close(za);
+ fclose(fo);
+ throw std::runtime_error(s.str().c_str());
+ }
+
+ struct zip_stat st;
+ zip_stat_index(za, idx, 0, &st);
+
+ std::size_t buf_len = 1000000; // 1 MB chunk
+ char * buf = new char[buf_len];
+ zip_int64_t result = 0;
+
+ while ((result=zip_fread(zf_ptr, buf, buf_len)) > 0) {
+ fwrite(buf,1,result,fo);
+ }
+
+ delete [] buf;
+
+ fclose(fo);
+
+ if (result < 0) {
+ std::stringstream s;
+ s << "error reading file #" << idx << " in " << from << ": archive error: " << zip_file_strerror(zf_ptr) << "\n";
+ if (zf_ptr) zip_fclose(zf_ptr);
+ if (za) zip_close(za);
+ throw std::runtime_error(s.str().c_str());
+ }
+ if (zf_ptr) zip_fclose(zf_ptr);
+ if (za) zip_close(za);
}
-Handle<Value> ZipFile::readFileSync(const Arguments& args) {
- HandleScope scope;
+void ZipFile::copyFileSync(const Nan::FunctionCallbackInfo<v8::Value>& args)
+{
+ Nan::HandleScope scope;
- if (args.Length() != 1 || !args[0]->IsString())
- return ThrowException(Exception::TypeError(
- String::New("first argument must be a file name inside the zip")));
+ if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsString())
+ {
+ Nan::ThrowError("requires two args: first argument must be a filename inside the zip and second must be a filename to write to.");
+ args.GetReturnValue().SetUndefined(); return;
+ }
- std::string name = TOSTR(args[0]);
+ std::string from = TOSTR(args[0]);
+ std::string to = TOSTR(args[1]);
+ ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This());
+ try {
+ _copyFile(from,to,zf);
+ } catch (std::exception const& ex) {
+ Nan::ThrowError(ex.what());
+ }
+ args.GetReturnValue().SetUndefined();
+}
+
+struct copy_file_baton {
+ uv_work_t request;
+ ZipFile* zf;
+ std::string from;
+ std::string to;
+ std::string error_name;
+ Nan::Persistent<Function> cb;
+};
+
+void ZipFile::copyFile(const Nan::FunctionCallbackInfo<v8::Value>& args)
+{
+ Nan::HandleScope scope;
+ if (args.Length() < 3)
+ {
+ Nan::ThrowError("requires three arguments: filename inside the zip, a filename to write to, and a callback");
+ args.GetReturnValue().SetUndefined(); return;
+ }
+
+ if (!args[0]->IsString() || !args[1]->IsString())
+ {
+ Nan::ThrowError("first argument must be a filename inside the zip and second must be a filename to write to.");
+ args.GetReturnValue().SetUndefined(); return;
+ }
+ // ensure function callback
+ Local<Value> callback = args[args.Length() - 1];
+ if (!callback->IsFunction()) {
+ Nan::ThrowTypeError("last argument must be a callback function");
+ args.GetReturnValue().SetUndefined(); return;
+ }
+ std::string from = TOSTR(args[0]);
+ std::string to = TOSTR(args[1]);
ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This());
+ copy_file_baton *closure = new copy_file_baton();
+ closure->request.data = closure;
+ closure->zf = zf;
+ closure->from = from;
+ closure->to = to;
+ closure->cb.Reset(callback.As<Function>());
+ uv_queue_work(uv_default_loop(), &closure->request, Work_CopyFile, (uv_after_work_cb)Work_AfterCopyFile);
+ zf->Ref();
+ args.GetReturnValue().SetUndefined();
+}
- int idx = -1;
- std::vector<std::string>::iterator it = std::find(zf->names_.begin(), zf->names_.end(), name);
- if (it != zf->names_.end()) {
- idx = distance(zf->names_.begin(), it);
+void ZipFile::Work_CopyFile(uv_work_t* req) {
+ copy_file_baton * closure = static_cast<copy_file_baton *>(req->data);
+ try {
+ _copyFile(closure->from,closure->to,closure->zf);
+ } catch (std::exception const& ex) {
+ closure->error_name = ex.what();
+ }
+}
+
+void ZipFile::Work_AfterCopyFile(uv_work_t* req) {
+ Nan::HandleScope scope;
+ copy_file_baton *closure = static_cast<copy_file_baton *>(req->data);
+ if (!closure->error_name.empty()) {
+ Local<Value> argv[1] = { Nan::Error(closure->error_name.c_str()) };
+ Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 1, argv);
+ } else {
+ Local<Value> argv[1] = { Nan::Null() };
+ Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 1, argv);
+ }
+ closure->zf->Unref();
+ closure->cb.Reset();
+ delete closure;
+}
+
+void ZipFile::readFileSync(const Nan::FunctionCallbackInfo<v8::Value>& args)
+{
+ Nan::HandleScope scope;
+
+ if (args.Length() != 1 || !args[0]->IsString())
+ {
+ Nan::ThrowError("first argument must be a file name inside the zip");
+ args.GetReturnValue().SetUndefined(); return;
+ }
+
+ std::string name = TOSTR(args[0]);
+ ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This());
+ int idx = -1;
+ std::vector<std::string> const& names = zf->names();
+ std::vector<std::string>::const_iterator it = std::find(names.begin(), names.end(), name);
+ if (it != names.end()) {
+ idx = distance(names.begin(), it);
}
if (idx == -1) {
std::stringstream s;
s << "No file found by the name of: '" << name << "\n";
- return ThrowException(Exception::Error(String::New(s.str().c_str())));
+ Nan::ThrowError(s.str().c_str());
+ args.GetReturnValue().SetUndefined(); return;
}
int err;
char errstr[1024];
- struct zip *za;
+ struct zip *za = NULL;
if ((za=zip_open(zf->file_name_.c_str(), ZIP_CHECKCONS, &err)) == NULL) {
zip_error_to_str(errstr, sizeof(errstr), err, errno);
std::stringstream s;
s << "cannot open file: " << zf->file_name_ << " error: " << errstr << "\n";
- zip_close(za);
- return ThrowException(Exception::Error(
- String::New(s.str().c_str())));
+ if (za) zip_close(za);
+ Nan::ThrowError(s.str().c_str());
+ args.GetReturnValue().SetUndefined(); return;
}
- struct zip_file *zf_ptr;
+ struct zip_file *zf_ptr = NULL;
if ((zf_ptr=zip_fopen_index(za, idx, 0)) == NULL) {
if (zf_ptr) zip_fclose(zf_ptr);
+ if (za) zip_close(za);
std::stringstream s;
s << "cannot open file #" << idx << " in " << name << ": archive error: " << zip_strerror(za) << "\n";
- zip_close(za);
- return ThrowException(Exception::Error(String::New(s.str().c_str())));
+ Nan::ThrowError(s.str().c_str());
+ args.GetReturnValue().SetUndefined(); return;
}
struct zip_stat st;
zip_stat_index(za, idx, 0, &st);
-
+
std::vector<unsigned char> data;
data.clear();
data.resize(st.size);
@@ -229,15 +341,15 @@ Handle<Value> ZipFile::readFileSync(const Arguments& args) {
if (result < 0) {
std::stringstream s;
s << "error reading file #" << idx << " in " << name << ": archive error: " << zip_file_strerror(zf_ptr) << "\n";
- zip_fclose(zf_ptr);
- zip_close(za);
- return ThrowException(Exception::Error(String::New(s.str().c_str())));
+ if (zf_ptr) zip_fclose(zf_ptr);
+ if (za) zip_close(za);
+ Nan::ThrowError(s.str().c_str());
+ args.GetReturnValue().SetUndefined(); return;
}
-
- node::Buffer *retbuf = Buffer::New(reinterpret_cast<char *>(&data[0]), data.size());
- zip_fclose(zf_ptr);
- zip_close(za);
- return scope.Close(retbuf->handle_);
+ Local<Object> retbuf = Nan::CopyBuffer(reinterpret_cast<char *>(&data[0]), data.size()).ToLocalChecked();
+ if (zf_ptr) zip_fclose(zf_ptr);
+ if (za) zip_close(za);
+ args.GetReturnValue().Set(retbuf);
}
typedef struct {
@@ -248,33 +360,38 @@ typedef struct {
bool error;
std::string error_name;
std::vector<unsigned char> data;
- Persistent<Function> cb;
+ Nan::Persistent<Function> cb;
} closure_t;
-Handle<Value> ZipFile::readFile(const Arguments& args) {
- HandleScope scope;
-
+void ZipFile::readFile(const Nan::FunctionCallbackInfo<v8::Value>& args)
+{
+ Nan::HandleScope scope;
if (args.Length() < 2)
- return ThrowException(Exception::TypeError(
- String::New("requires two arguments, the name of a file and a callback")));
+ {
+ Nan::ThrowError("requires two arguments, the name of a file and a callback");
+ args.GetReturnValue().SetUndefined(); return;
+ }
// first arg must be name
if (!args[0]->IsString())
- return ThrowException(Exception::TypeError(
- String::New("first argument must be a file name inside the zip")));
+ {
+ Nan::ThrowError("first argument must be a file name inside the zip");
+ args.GetReturnValue().SetUndefined(); return;
+ }
- // last arg must be function callback
- if (!args[args.Length()-1]->IsFunction())
- return ThrowException(Exception::TypeError(
- String::New("last argument must be a callback function")));
+ // ensure function callback
+ Local<Value> callback = args[args.Length() - 1];
+ if (!callback->IsFunction()) {
+ Nan::ThrowTypeError("last argument must be a callback function");
+ args.GetReturnValue().SetUndefined(); return;
+ }
std::string name = TOSTR(args[0]);
-
ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This());
-
closure_t *closure = new closure_t();
closure->request.data = closure;
+ closure->za = NULL;
// libzip is not threadsafe so we open a new zip archive for each thread
int err;
@@ -283,35 +400,33 @@ Handle<Value> ZipFile::readFile(const Arguments& args) {
zip_error_to_str(errstr, sizeof(errstr), err, errno);
std::stringstream s;
s << "cannot open file: " << zf->file_name_ << " error: " << errstr << "\n";
- zip_close(closure->za);
- closure->cb.Dispose();
+ if (closure->za) zip_close(closure->za);
+ closure->cb.Reset();
delete closure;
- return ThrowException(Exception::Error(
- String::New(s.str().c_str())));
+ Nan::ThrowError(s.str().c_str());
+ args.GetReturnValue().SetUndefined(); return;
}
closure->zf = zf;
closure->error = false;
closure->name = name;
- closure->cb = Persistent<Function>::New(Handle<Function>::Cast(args[args.Length()-1]));
+ closure->cb.Reset(callback.As<Function>());
uv_queue_work(uv_default_loop(), &closure->request, Work_ReadFile, (uv_after_work_cb)Work_AfterReadFile);
zf->Ref();
- return Undefined();
+ args.GetReturnValue().SetUndefined();
}
void ZipFile::Work_ReadFile(uv_work_t* req) {
closure_t *closure = static_cast<closure_t *>(req->data);
-
struct zip_file *zf_ptr = NULL;
-
int idx = -1;
-
- std::vector<std::string>::iterator it = std::find(closure->zf->names_.begin(),
- closure->zf->names_.end(),
+ std::vector<std::string> const& names = closure->zf->names();
+ std::vector<std::string>::const_iterator it = std::find(names.begin(),
+ names.end(),
closure->name);
- if (it != closure->zf->names_.end()) {
- idx = distance(closure->zf->names_.begin(), it);
+ if (it != names.end()) {
+ idx = distance(names.begin(), it);
}
if (idx == -1) {
@@ -343,49 +458,43 @@ void ZipFile::Work_ReadFile(uv_work_t* req) {
closure->error_name = s.str();
}
}
+ if (zf_ptr) zip_fclose(zf_ptr);
}
- zip_fclose(zf_ptr);
}
void ZipFile::Work_AfterReadFile(uv_work_t* req) {
- HandleScope scope;
+ Nan::HandleScope scope;
closure_t *closure = static_cast<closure_t *>(req->data);
- TryCatch try_catch;
-
if (closure->error) {
- Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
- closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
+ Local<Value> argv[1] = { Nan::Error(closure->error_name.c_str()) };
+ Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 1, argv);
} else {
- node::Buffer *retbuf = Buffer::New(reinterpret_cast<char *>(&closure->data[0]), closure->data.size());
- Local<Value> argv[2] = { Local<Value>::New(Null()), Local<Value>::New(retbuf->handle_) };
- closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
+ Local<Object> retbuf = Nan::CopyBuffer(reinterpret_cast<char *>(&closure->data[0]), closure->data.size()).ToLocalChecked();
+ Local<Value> argv[2] = { Nan::Null(), retbuf };
+ Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 2, argv);
}
- if (try_catch.HasCaught()) {
- FatalException(try_catch);
- }
- zip_close(closure->za);
+ if (closure->za) zip_close(closure->za);
closure->zf->Unref();
- closure->cb.Dispose();
+ closure->cb.Reset();
delete closure;
}
extern "C" {
- static void init(Handle<Object> target) {
+ static void init(Local<Object> target) {
ZipFile::Initialize(target);
// node-zipfile version
- target->Set(String::NewSymbol("version"), String::New("0.3.1"));
+ target->Set(Nan::New("version").ToLocalChecked(), Nan::New("0.5.8").ToLocalChecked());
// versions of deps
- Local<Object> versions = Object::New();
- versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
- versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
- target->Set(String::NewSymbol("versions"), versions);
+ Local<Object> versions = Nan::New<Object>();
+ versions->Set(Nan::New("node").ToLocalChecked(), Nan::New(NODE_VERSION+1).ToLocalChecked());
+ versions->Set(Nan::New("v8").ToLocalChecked(), Nan::New(V8::GetVersion()).ToLocalChecked());
+ target->Set(Nan::New("versions").ToLocalChecked(), versions);
}
#define MAKE_MODULE(_modname) NODE_MODULE( _modname, init)
MAKE_MODULE(MODULE_NAME)
}
-
diff --git a/src/node_zipfile.hpp b/src/node_zipfile.hpp
index e68e981..020a282 100644
--- a/src/node_zipfile.hpp
+++ b/src/node_zipfile.hpp
@@ -1,44 +1,35 @@
#ifndef INCLUDE_ZIPFILE_NODE_ZIPFILE_H_
#define INCLUDE_ZIPFILE_NODE_ZIPFILE_H_
-// libzip
-extern "C" {
-#include <zlib.h>
-#include <errno.h>
-#include <zip.h>
-}
-
+// v8
#include <v8.h>
+
+// node
#include <node.h>
+#include <nan.h>
#include <node_object_wrap.h>
// stl
#include <string>
#include <vector>
-
-using namespace v8;
-using namespace node;
-
class ZipFile: public node::ObjectWrap {
public:
- static Persistent<FunctionTemplate> constructor;
- static void Initialize(Handle<Object> target);
- static Handle<Value> New(const Arguments &args);
-
- static Handle<Value> get_prop(Local<String> property,
- const AccessorInfo& info);
-
- // Sync
- static Handle<Value> readFileSync(const Arguments& args);
-
- // Async
- static Handle<Value> readFile(const Arguments& args);
+ static Nan::Persistent<v8::FunctionTemplate> constructor;
+ static void Initialize(v8::Local<v8::Object> target);
+ static void New(const Nan::FunctionCallbackInfo<v8::Value>& args);
+ static void get_prop(v8::Local<v8::String> property, const Nan::PropertyCallbackInfo<v8::Value>& args);
+ static void copyFile(const Nan::FunctionCallbackInfo<v8::Value>& args);
+ static void Work_CopyFile(uv_work_t* req);
+ static void Work_AfterCopyFile(uv_work_t* req);
+ static void copyFileSync(const Nan::FunctionCallbackInfo<v8::Value>& args);
+ static void readFileSync(const Nan::FunctionCallbackInfo<v8::Value>& args);
+ static void readFile(const Nan::FunctionCallbackInfo<v8::Value>& args);
static void Work_ReadFile(uv_work_t* req);
static void Work_AfterReadFile(uv_work_t* req);
-
- explicit ZipFile(std::string const& file_name);
-
+ ZipFile(std::string const& file_name);
+ std::vector<std::string> const& names() const { return names_; }
+ std::string const& file_name() const { return file_name_; }
private:
std::string file_name_;
std::vector<std::string> names_;
diff --git a/src/unicode_conversion_helpers.hpp b/src/unicode_conversion_helpers.hpp
new file mode 100644
index 0000000..17f3cc4
--- /dev/null
+++ b/src/unicode_conversion_helpers.hpp
@@ -0,0 +1,68 @@
+
+#include <Windows.h>
+#include <string>
+#include <cstdio>
+
+std::string wstring2string(const std::wstring& s)
+{
+ DWORD size = WideCharToMultiByte(CP_UTF8,
+ 0,
+ s.c_str(),
+ -1,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (size == 0) {
+ // This should never happen.
+ fprintf(stderr, "Could not convert arguments to utf8.");
+ }
+ char * buf_ptr = new char [size];
+ DWORD result = WideCharToMultiByte(CP_ACP,
+ 0,
+ s.c_str(),
+ -1,
+ buf_ptr,
+ size,
+ NULL,
+ NULL);
+ if (result == 0) {
+ // This should never happen.
+ fprintf(stderr, "Could not convert arguments to utf8.");
+ }
+ std::string r(buf_ptr);
+ delete buf_ptr;
+ return r;
+}
+
+std::wstring utf8ToWide( std::string const& s )
+{
+ int ws_len, r;
+ WCHAR* ws;
+ ws_len = MultiByteToWideChar(CP_UTF8,
+ 0,
+ s.c_str(),
+ -1,
+ NULL,
+ 0);
+ ws = new wchar_t [ws_len * sizeof(WCHAR)];
+ if (ws == NULL) {
+ // This should never happen.
+ fprintf(stderr, "Could not convert arguments from utf8.");
+ exit(1);
+ }
+ r = MultiByteToWideChar(CP_UTF8,
+ 0,
+ s.c_str(),
+ -1,
+ ws,
+ ws_len);
+ if (r != ws_len) {
+ // This should never happen.
+ fprintf(stderr, "Could not do anything useful.");
+ exit(1);
+ }
+ std::wstring rt(ws);
+ delete ws;
+ return rt;
+}
\ No newline at end of file
diff --git a/test/data/World_mercator.zip b/test/data/World_mercator.zip
new file mode 100644
index 0000000..40c77cb
Binary files /dev/null and b/test/data/World_mercator.zip differ
diff --git a/test/exceptions.test.js b/test/exceptions.test.js
index 90c8f41..07a6a0e 100644
--- a/test/exceptions.test.js
+++ b/test/exceptions.test.js
@@ -16,4 +16,16 @@ describe('Exceptions', function(){
assert.throws(function() { zf.readFileSync('foo'); });
});
+ it('should not crash if we read invalid filename', function(done){
+ var zf = new zipfile.ZipFile('./test/data/World_mercator.zip');
+ var remaining = zf.names.length;
+ zf.names.forEach(function(name) {
+ zf.readFile(name.toLowerCase(),function(err, buffer) {
+ assert.equal(err.message.indexOf('No file found'),0);
+ remaining--;
+ if (remaining <= 0) done();
+ });
+ });
+ });
+
});
\ No newline at end of file
diff --git a/test/write.test.js b/test/write.test.js
index f1ffb68..13511f8 100644
--- a/test/write.test.js
+++ b/test/write.test.js
@@ -5,55 +5,79 @@ var fs = require('fs');
var constants = require('constants');
var mkdirp = require('mkdirp');
var existsSync = require('fs').existsSync || require('path').existsSync;
+var crypto = require('crypto');
+
+describe('Writes', function(){
+
+var meta = {
+ 'world_merc.dbf': {size: 24641, md5: '7d087de3e8c9ed2aee0e81615ff91e13'},
+ 'world_merc.prj': {size: 384, md5: '1fac28f31277bfbbf8a1b0050cc8fb85'},
+ 'world_merc.shp': {size: 428328, md5: '9042bca3485687bef43a18ef8edc6469'},
+ 'world_merc.shx': {size: 2060, md5: 'b51caf61d1b821025bb8994151cfc0cc'},
+};
describe('Async Writes', function(){
var zf = new zipfile.ZipFile('./test/data/world_merc.zip');
zf.names.forEach(function(name) {
it('async write '+ name, function(done){
- var dest = path.join(__dirname,'tmp', name);
- mkdirp(path.dirname(dest), 0755 , function(err) {
+ var dest = path.join(__dirname, 'tmp', 'aync',name);
+ var dest2 = path.join(__dirname,'tmp', 'aync-copy',name);
+ mkdirp.sync(path.dirname(dest));
+ mkdirp.sync(path.dirname(dest2));
+ mkdirp(path.dirname(dest), function(err) {
if (err) throw err;
if (path.extname(name)) {
zf.readFile(name, function(err, buffer) {
if (err) throw err;
- fs.open(dest, 'w', 0644, function(err, fd) {
+ assert.equal(meta[name].size,buffer.length);
+ var shasum = crypto.createHash('md5');
+ shasum.update(buffer);
+ var md5 = shasum.digest('hex');
+ assert.equal(meta[name].md5,md5);
+ zf.copyFile(name,dest2,function(err) {
if (err) throw err;
- fs.write(fd, buffer, 0, buffer.length, null, function(err,written) {
- if (err) throw err;
- // written is number of bytes written
- assert.ok(written > 0);
- fs.close(fd, function(err) {
- if (err) throw err;
- done();
- });
- });
+ assert.ok(existsSync(dest2));
+ var buffer2 = fs.readFileSync(dest2);
+ assert.equal(meta[name].size,buffer2.length)
+ var shasum2 = crypto.createHash('md5');
+ shasum2.update(buffer2);
+ var md52 = shasum2.digest('hex');
+ assert.equal(meta[name].md5,md52);
+ done();
});
});
}
});
});
});
-
});
+
describe('Sync Writes', function(){
var zf = new zipfile.ZipFile('./test/data/world_merc.zip');
zf.names.forEach(function(name) {
- var uncompressed = path.join('/tmp/sync', name);
- var dirname = path.dirname(uncompressed);
- mkdirp(dirname, 0755 , function(err) {
- it('sync write '+ name, function(done){
- if (err && !err.message.match(/^EEXIST/)) throw err;
- if (path.extname(name)) {
- var buffer = zf.readFileSync(name);
- var fd = fs.openSync(uncompressed, 'w');
- fs.writeSync(fd, buffer, 0, buffer.length, null);
- fs.closeSync(fd);
- assert.ok(existsSync(uncompressed));
- done();
- }
- });
+ var dest = path.join(__dirname,'tmp', 'sync',name);
+ var dest2 = path.join(__dirname,'tmp', 'sync-copy',name);
+ mkdirp.sync(path.dirname(dest));
+ mkdirp.sync(path.dirname(dest2));
+ it('sync write '+ name, function(done){
+ if (path.extname(name)) {
+ var buffer = zf.readFileSync(name);
+ assert.equal(meta[name].size,buffer.length)
+ var shasum = crypto.createHash('md5');
+ shasum.update(buffer);
+ var md5 = shasum.digest('hex');
+ assert.equal(meta[name].md5,md5);
+ fs.writeFileSync(dest,buffer);
+ assert.ok(existsSync(dest));
+ zf.copyFileSync(name,dest2);
+ assert.ok(existsSync(dest2));
+ assert.equal(meta[name].size,fs.readFileSync(dest2).length)
+ done();
+ }
});
});
+});
+
});
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/node-zipfile.git
More information about the Pkg-javascript-commits
mailing list