Skip to content

Commit

Permalink
add readFileSync method (returns a buffer)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dane Springmeyer committed Jan 20, 2011
1 parent d397a7d commit e0dd997
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 19 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@

Install libzip:

Debian:
$ sudo apt-get install libzip-dev libzip1
Or from source:

$ hg clone http://hg.nih.at/libzip
$ cd libzip
$ cmake .
$ make
$ sudo make install
Debian:

$ sudo apt-get install libzip-dev libzip1

Or from source:

$ hg clone http://hg.nih.at/libzip
$ cd libzip
$ cmake .
$ make
$ sudo make install

Install node-zipfile:

Expand Down
76 changes: 73 additions & 3 deletions src/node_zipfile.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#include "node_zipfile.hpp"

#include <sstream>
#include <vector>

#include <node_buffer.h>
#include <node_version.h>

#define TOSTR(obj) (*String::Utf8Value((obj)->ToString()))

Expand All @@ -14,15 +18,19 @@ void ZipFile::Initialize(Handle<Object> target) {
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("ZipFile"));

// functions
NODE_SET_PROTOTYPE_METHOD(constructor, "readFileSync", readFileSync);

// properties
constructor->InstanceTemplate()->SetAccessor(String::NewSymbol("count"), get_prop);
constructor->InstanceTemplate()->SetAccessor(String::NewSymbol("names"), get_prop);

target->Set(String::NewSymbol("ZipFile"),constructor->GetFunction());
}

ZipFile::ZipFile() :
ZipFile::ZipFile(std::string const& file_name) :
ObjectWrap(),
file_name_(file_name),
archive_() {}

ZipFile::~ZipFile() {
Expand Down Expand Up @@ -52,7 +60,7 @@ Handle<Value> ZipFile::New(const Arguments& args)
String::New(s.str().c_str())));
}

ZipFile* zf = new ZipFile();
ZipFile* zf = new ZipFile(input_file);
zf->archive_ = za;
zf->Wrap(args.This());
return args.This();
Expand Down Expand Up @@ -81,4 +89,66 @@ Handle<Value> ZipFile::get_prop(Local<String> property,
return scope.Close(a);
}
return Undefined();
}
}

Handle<Value> ZipFile::readFileSync(const Arguments& args)
{
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")));

std::string input_file = TOSTR(args[0]);

// TODO - enforce valid index
ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This());

struct zip_file *zf_ptr;

int idx = -1;
int num = zip_get_num_files(zf->archive_);
int i = 0;
for (i=0; i<num; i++) {
struct zip_stat st;
zip_stat_index(zf->archive_, i, 0, &st);
if (st.name == input_file) {
idx = i;
}
}

if (idx == -1) {
std::stringstream s;
s << "No file found by the name of: '" << input_file << "\n";
return ThrowException(Exception::Error(String::New(s.str().c_str())));
}

if ((zf_ptr=zip_fopen_index(zf->archive_, idx, 0)) == NULL) {
zip_fclose(zf_ptr);
std::stringstream s;
s << "cannot open file #" << idx << " in " << input_file << ": archive error: " << zip_strerror(zf->archive_) << "\n";
return ThrowException(Exception::Error(String::New(s.str().c_str())));
}

struct zip_stat st;
zip_stat_index(zf->archive_, idx, 0, &st);

std::vector<unsigned char> data;
data.clear();
data.resize( st.size );

int result = 0;
result = (int)zip_fread( zf_ptr, reinterpret_cast<void*> (&data[0]), data.size() );

if (result < 0) {
zip_fclose(zf_ptr);
std::stringstream s;
s << "error reading file #" << idx << " in " << input_file << ": archive error: " << zip_file_strerror(zf_ptr) << "\n";
return ThrowException(Exception::Error(String::New(s.str().c_str())));
}

node::Buffer *retbuf = Buffer::New((char *)&data[0],data.size());

zip_fclose(zf_ptr);
return scope.Close(retbuf->handle_);
}
5 changes: 4 additions & 1 deletion src/node_zipfile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ class ZipFile: public node::ObjectWrap {
static Handle<Value> get_prop(Local<String> property,
const AccessorInfo& info);

ZipFile();
static Handle<Value> readFileSync(const Arguments& args);

ZipFile(std::string const& file_name);

private:
~ZipFile();
std::string const& file_name_;
struct zip *archive_;
};

Expand Down
50 changes: 46 additions & 4 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,63 @@

var zipfile = require('zipfile');
var assert = require('assert');
//var path = require('path');
var path = require('path');
var fs = require('fs');

// node 0.2 <-> 0.3 compatibility
var constants = {};
if (!process.EEXIST >= 1)
constants = require('constants');
else
constants.EEXIST = process.EEXIST;

// created with:
// $ zip -9vr test.zip *txt -c "a comment" -z "zipfile comment"
var zf = new zipfile.ZipFile('./data/test.zip');
console.log(zf)
//console.log(zf)
assert.equal(zf.count,2)
assert.deepEqual(zf.names,['one.txt','two.txt'])

// created with /System/Library/CoreServices/Archive Utility.app
var zf = new zipfile.ZipFile('./data/Archive.zip');
console.log(zf)
//console.log(zf)
assert.equal(zf.count,2)
assert.deepEqual(zf.names,['one.txt','two.txt'])

console.log('All tests pass...');

function mkdirP (p, mode, f) {
var cb = f || function () {};
// if relative
if (p.charAt(0) != '/') {
// if >= node 0.3.0 use path.resolve()
p = path.join(__dirname,p);
}
var ps = path.normalize(p).split('/');
path.exists(p, function (exists) {
if (exists) cb(null);
else mkdirP(ps.slice(0,-1).join('/'), mode, function (err) {
if (err && err.errno != constants.EEXIST) cb(err)
else fs.mkdir(p, mode, cb);
});
});
};


var zf = new zipfile.ZipFile('./data/test.zip');
//var zf = new zipfile.ZipFile('./data/folder.zip');

zf.names.forEach(function(name) {
var uncompressed = path.join('/tmp/',name);
var dirname = path.dirname(uncompressed);
mkdirP(dirname, 0755 , function(err) {
if (err && err.errno != constants.EEXIST) throw err;
if (path.extname(name)) {
var buffer = zf.readFileSync(name);
fd = fs.openSync(uncompressed,'w');
fs.writeSync(fd, buffer, 0, buffer.length, null);
fs.closeSync(fd);
}
})
})

//console.log('All tests pass...');

0 comments on commit e0dd997

Please sign in to comment.