[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