zipruby 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of zipruby might be problematic. Click here for more details.

data/README.txt CHANGED
@@ -43,7 +43,24 @@ https://rubyforge.org/frs/?group_id=6124
43
43
 
44
44
  # Zip::Archive includes Enumerable
45
45
  entry_names = ar.map do |f|
46
- f.naem
46
+ f.name
47
+ end
48
+ end
49
+
50
+ # read huge entry
51
+ BUFSIZE = 8192
52
+
53
+ Zip::Archive.open('filename.zip') do |ar|
54
+ ar.each do |f|
55
+ buf = ''
56
+
57
+ while chunk = f.read(BUFSIZE)
58
+ buf << chunk
59
+ end
60
+ # or
61
+ # f.read do |chunk|
62
+ # buf << chunk
63
+ # end
47
64
  end
48
65
  end
49
66
 
@@ -62,6 +79,20 @@ https://rubyforge.org/frs/?group_id=6124
62
79
  # add file to zip archive from buffer
63
80
  ar.add_buffer('zoo.txt', 'Hello, world!')
64
81
  end
82
+
83
+ # include directory in zip archive
84
+ Zip::Archive.open('filename.zip') do |ar|
85
+ ar.add_file('dirname/foo.txt', 'foo.txt')
86
+ # args: <entry name>, <source>
87
+
88
+ open('bar.txt') do |f|
89
+ ar.add_filep('dirname/bar.txt', f)
90
+ # args: <entry name>, <source>
91
+ end
92
+
93
+ ar.add_buffer('dirname/zoo.txt', 'Hello, world!')
94
+ # args: <entry name>, <source>
95
+ end
65
96
 
66
97
  === modifying zip archives
67
98
 
@@ -83,13 +114,28 @@ https://rubyforge.org/frs/?group_id=6124
83
114
  ar.add_or_replace_file(3, 'foo.txt')
84
115
  end
85
116
 
86
- # ar1 imports ar2 entries
117
+ # append comment
118
+ Zip::Archive.open('filename.zip') do |ar|
119
+ ar.comment = <<-EOS
120
+ jugem jugem gokou no surikere
121
+ kaijari suigyo no
122
+ suigyoumatsu unraimatsu furaimatsu
123
+ EOS
124
+ end
125
+
126
+ # ar1 import ar2 entries
87
127
  Zip::Archive.open('ar1.zip') do |ar1|
88
128
  Zip::Archive.open('ar2.zip') do |ar2|
89
129
  ar1.update(ar2)
90
130
  end
91
131
  end
92
132
 
133
+ === decrypt zip archives
134
+
135
+ require 'zipruby'
136
+
137
+ Zip::Archive.decrypt('filename.zip', 'password')
138
+
93
139
  == License
94
140
  Copyright (c) 2008 SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
95
141
  All rights reserved.
data/ext/libzip.vcproj CHANGED
@@ -110,6 +110,10 @@
110
110
  RelativePath=".\zip_close.c"
111
111
  >
112
112
  </File>
113
+ <File
114
+ RelativePath=".\zip_crypt.c"
115
+ >
116
+ </File>
113
117
  <File
114
118
  RelativePath=".\zip_delete.c"
115
119
  >
data/ext/zip.h CHANGED
@@ -203,6 +203,9 @@ const char *zip_strerror(struct zip *);
203
203
  int zip_unchange(struct zip *, int);
204
204
  int zip_unchange_all(struct zip *);
205
205
  int zip_unchange_archive(struct zip *);
206
+
207
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
208
+ int zip_decrypt(const char *path, const char *pwd, int pwdlen, int *errorp, int *wrongpwd);
206
209
 
207
210
  #ifdef __cplusplus
208
211
  }
data/ext/zip_close.c CHANGED
@@ -58,10 +58,12 @@ static int add_data_comp(zip_source_callback, void *, struct zip_stat *,
58
58
  static int add_data_uncomp(zip_source_callback, void *, struct zip_stat *,
59
59
  FILE *, struct zip_error *);
60
60
  static void ch_set_error(struct zip_error *, zip_source_callback, void *);
61
- static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
62
- static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
61
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
62
+ //static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
63
+ //static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
63
64
  static int _zip_changed(struct zip *, int *);
64
- static char *_zip_create_temp_output(struct zip *, FILE **);
65
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
66
+ //static char *_zip_create_temp_output(struct zip *, FILE **);
65
67
 
66
68
 
67
69
 
@@ -451,7 +453,8 @@ ch_set_error(struct zip_error *error, zip_source_callback cb, void *ud)
451
453
 
452
454
 
453
455
 
454
- static int
456
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
457
+ /*static*/ int
455
458
  copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error)
456
459
  {
457
460
  char buf[BUFSIZE];
@@ -484,7 +487,8 @@ copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error)
484
487
 
485
488
 
486
489
 
487
- static int
490
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
491
+ /*static*/ int
488
492
  _zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src)
489
493
  {
490
494
  if (src->ch_comment_len != -1) {
@@ -533,7 +537,8 @@ _zip_changed(struct zip *za, int *survivorsp)
533
537
 
534
538
 
535
539
 
536
- static char *
540
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
541
+ /*static*/ char *
537
542
  _zip_create_temp_output(struct zip *za, FILE **outp)
538
543
  {
539
544
  char *temp;
data/ext/zip_crypt.c ADDED
@@ -0,0 +1,291 @@
1
+ /*
2
+ zip_crypt.c -- zip encryption support
3
+ Copyright (c) 2008 SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
4
+ based on zip_close.c
5
+ */
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+ #include <errno.h>
10
+ #include <sys/types.h>
11
+
12
+ #ifdef _WIN32
13
+ #include <windows.h>
14
+ #include <io.h>
15
+ #define close(f) _close(f)
16
+ #define rename(s, d) (MoveFileExA((s), (d), MOVEFILE_REPLACE_EXISTING) ? 0 : -1)
17
+ #endif
18
+
19
+ #include "zip.h"
20
+ #include "zipint.h"
21
+
22
+ #define ZIPENC_HEAD_LEN 12
23
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
24
+
25
+ static zipenc_crc32(uLong crc, char c) {
26
+ return crc32(crc ^ 0xffffffffL, &c, 1) ^ 0xffffffffL;
27
+ }
28
+
29
+ static void update_keys(uLong *keys, char c) {
30
+ keys[0] = zipenc_crc32(keys[0], c);
31
+ keys[1] = keys[1] + (keys[0] & 0xff);
32
+ keys[1] = keys[1] * 134775813L + 1;
33
+ c = (char) (keys[1] >> 24);
34
+ keys[2] = zipenc_crc32(keys[2], c);
35
+ }
36
+
37
+ static unsigned char decrypt_byte(uLong *keys) {
38
+ unsigned short temp;
39
+
40
+ temp = (unsigned short) (keys[2] | 2);
41
+ return (temp * (temp ^ 1)) >> 8;
42
+ }
43
+
44
+ static void init_keys(uLong *keys, const char *password, size_t len) {
45
+ int i;
46
+
47
+ keys[0] = 305419896L;
48
+ keys[1] = 591751049L;
49
+ keys[2] = 878082192L;
50
+
51
+ for (i = 0; i < len; i++) {
52
+ update_keys(keys, password[i]);
53
+ }
54
+ }
55
+
56
+ static int decrypt_header(unsigned long *keys, char *buffer, struct zip_dirent *de) {
57
+ int i;
58
+ char c;
59
+ unsigned short dostime, dosdate;
60
+
61
+ for (i = 0; i < ZIPENC_HEAD_LEN; i++) {
62
+ c = buffer[i] ^ decrypt_byte(keys);
63
+ update_keys(keys, c);
64
+ buffer[i] = c;
65
+ }
66
+
67
+ _zip_u2d_time(de->last_mod, &dostime, &dosdate);
68
+
69
+ if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
70
+ return ((c & 0xff) == (de->crc >> 24)) ? 0 : -1;
71
+ } else {
72
+ return ((c & 0xff) == (dostime >> 8)) ? 0 : -1;
73
+ }
74
+ }
75
+
76
+ static void decrypt_data(uLong *keys, char *buffer, size_t n) {
77
+ int i;
78
+
79
+ for (i = 0; i < n; i++) {
80
+ char temp = buffer[i] ^ decrypt_byte(keys);
81
+ update_keys(keys, temp);
82
+ buffer[i] = temp;
83
+ }
84
+ }
85
+
86
+ static int copy_decrypt(FILE *src, off_t len, const char *pwd, int pwdlen, struct zip_dirent *de, FILE *dest, struct zip_error *error, int *wrongpwd) {
87
+ char buf[BUFSIZE];
88
+ uLong keys[3];
89
+ int n;
90
+
91
+ *wrongpwd = 0;
92
+
93
+ if (len == 0) {
94
+ return 0;
95
+ }
96
+
97
+ init_keys(keys, pwd, pwdlen);
98
+
99
+ if (fread(buf, 1, ZIPENC_HEAD_LEN, src) < 0) {
100
+ _zip_error_set(error, ZIP_ER_READ, errno);
101
+ }
102
+
103
+ if (decrypt_header(keys, buf, de) == -1) {
104
+ // XXX: _zip_error_set
105
+ *wrongpwd = 1;
106
+ return -1;
107
+ }
108
+
109
+ while (len > 0) {
110
+ if ((n = fread(buf, 1, MIN(len, sizeof(buf)), src)) < 0) {
111
+ _zip_error_set(error, ZIP_ER_READ, errno);
112
+ return -1;
113
+ } else if (n == 0) {
114
+ _zip_error_set(error, ZIP_ER_EOF, 0);
115
+ return -1;
116
+ }
117
+
118
+ decrypt_data(keys, buf, n);
119
+
120
+ if (fwrite(buf, 1, n, dest) != ((size_t) n)) {
121
+ _zip_error_set(error, ZIP_ER_WRITE, errno);
122
+ return -1;
123
+ }
124
+
125
+ len -= n;
126
+ }
127
+
128
+ return 0;
129
+ }
130
+
131
+ static int _zip_crypt(struct zip *za, const char *pwd, int pwdlen, int decrypt, int *wrongpwd) {
132
+ int i, error = 0;
133
+ char *temp;
134
+ FILE *out;
135
+ #ifndef _WIN32
136
+ mode_t mask;
137
+ #endif
138
+ struct zip_cdir *cd;
139
+ struct zip_dirent de;
140
+ int reopen_on_error = 0;
141
+
142
+ if (za == NULL) {
143
+ return -1;
144
+ }
145
+
146
+ if (za->nentry < 1) {
147
+ _zip_free(za);
148
+ return 0;
149
+ }
150
+
151
+ if ((cd = _zip_cdir_new(za->nentry, &za->error)) == NULL) {
152
+ return -1;
153
+ }
154
+
155
+ for (i = 0; i < za->nentry; i++) {
156
+ _zip_dirent_init(&cd->entry[i]);
157
+ }
158
+
159
+ if (_zip_cdir_set_comment(cd, za) == -1) {
160
+ _zip_cdir_free(cd);
161
+ return -1;
162
+ }
163
+
164
+ if ((temp = _zip_create_temp_output(za, &out)) == NULL) {
165
+ _zip_cdir_free(cd);
166
+ return -1;
167
+ }
168
+
169
+ for (i = 0; i < za->nentry; i++) {
170
+ int encrypted;
171
+
172
+ if (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0) {
173
+ _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
174
+ error = 1;
175
+ break;
176
+ }
177
+
178
+ if (_zip_dirent_read(&de, za->zp, NULL, 0, 1, &za->error) != 0) {
179
+ error = 1;
180
+ break;
181
+ }
182
+
183
+ if (de.bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
184
+ de.crc = za->cdir->entry[i].crc;
185
+ de.comp_size = za->cdir->entry[i].comp_size;
186
+ de.uncomp_size = za->cdir->entry[i].uncomp_size;
187
+ de.bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
188
+ }
189
+
190
+ memcpy(cd->entry + i, za->cdir->entry + i, sizeof(cd->entry[i]));
191
+ cd->entry[i].offset = ftello(out);
192
+
193
+ encrypted = de.bitflags & ZIP_GPBF_ENCRYPTED;
194
+
195
+ if (decrypt && encrypted) {
196
+ de.comp_size -= ZIPENC_HEAD_LEN;
197
+ de.bitflags &= ~ZIP_GPBF_ENCRYPTED;
198
+ cd->entry[i].comp_size -= ZIPENC_HEAD_LEN;
199
+ cd->entry[i].bitflags &= ~ZIP_GPBF_ENCRYPTED;
200
+ } else if (!decrypt && !encrypted) {
201
+ // XXX
202
+ }
203
+
204
+ if (_zip_dirent_write(&de, out, 1, &za->error) < 0) {
205
+ error = 1;
206
+ break;
207
+ }
208
+
209
+ if (decrypt && encrypted) {
210
+ error = (copy_decrypt(za->zp, cd->entry[i].comp_size, pwd, pwdlen, &de, out, &za->error, wrongpwd) < 0);
211
+ } else if (!decrypt && !encrypted) {
212
+ // XXX
213
+ error = (copy_data(za->zp, cd->entry[i].comp_size, out, &za->error) < 0);
214
+ } else {
215
+ error = (copy_data(za->zp, cd->entry[i].comp_size, out, &za->error) < 0);
216
+ }
217
+
218
+ if (error) {
219
+ break;
220
+ }
221
+
222
+ _zip_dirent_finalize(&de);
223
+ }
224
+
225
+ if (!error && _zip_cdir_write(cd, out, &za->error) < 0) {
226
+ error = 1;
227
+ }
228
+
229
+ cd->nentry = 0;
230
+ _zip_cdir_free(cd);
231
+
232
+ if (error) {
233
+ _zip_dirent_finalize(&de);
234
+ fclose(out);
235
+ remove(temp);
236
+ free(temp);
237
+ return -1;
238
+ }
239
+
240
+ if (fclose(out) != 0) {
241
+ _zip_error_set(&za->error, ZIP_ER_CLOSE, errno);
242
+ remove(temp);
243
+ free(temp);
244
+ return -1;
245
+ }
246
+
247
+ if (za->zp) {
248
+ fclose(za->zp);
249
+ za->zp = NULL;
250
+ reopen_on_error = 1;
251
+ }
252
+
253
+ if (rename(temp, za->zn) != 0) {
254
+ _zip_error_set(&za->error, ZIP_ER_RENAME, errno);
255
+ remove(temp);
256
+ free(temp);
257
+
258
+ if (reopen_on_error) {
259
+ za->zp = fopen(za->zn, "rb");
260
+ }
261
+
262
+ return -1;
263
+ }
264
+
265
+ #ifndef _WIN32
266
+ mask = umask(0);
267
+ umask(mask);
268
+ chmod(za->zn, 0666&~mask);
269
+ #endif
270
+
271
+ free(temp);
272
+ return 0;
273
+ }
274
+
275
+ int zip_decrypt(const char *path, const char *pwd, int pwdlen, int *errorp, int *wrongpwd) {
276
+ struct zip *za;
277
+ int res;
278
+
279
+ if (pwd == NULL || pwdlen < 1) {
280
+ return -1;
281
+ }
282
+
283
+ if ((za = zip_open(path, 0, errorp)) == NULL) {
284
+ return -1;
285
+ }
286
+
287
+ res = _zip_crypt(za, pwd, pwdlen, 1, wrongpwd);
288
+ _zip_free(za);
289
+
290
+ return res;
291
+ }
data/ext/zip_dirent.c CHANGED
@@ -48,7 +48,8 @@
48
48
  static time_t _zip_d2u_time(int, int);
49
49
  static char *_zip_readfpstr(FILE *, unsigned int, int, struct zip_error *);
50
50
  static char *_zip_readstr(unsigned char **, int, int, struct zip_error *);
51
- static void _zip_u2d_time(time_t, unsigned short *, unsigned short *);
51
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
52
+ //static void _zip_u2d_time(time_t, unsigned short *, unsigned short *);
52
53
  static void _zip_write2(unsigned short, FILE *);
53
54
  static void _zip_write4(unsigned int, FILE *);
54
55
 
@@ -516,7 +517,8 @@ _zip_write4(unsigned int i, FILE *fp)
516
517
 
517
518
 
518
519
 
519
- static void
520
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
521
+ /*static*/ void
520
522
  _zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate)
521
523
  {
522
524
  struct tm *tm;
data/ext/zipint.h CHANGED
@@ -237,4 +237,10 @@ int _zip_set_name(struct zip *, int, const char *);
237
237
  int _zip_unchange(struct zip *, int, int);
238
238
  void _zip_unchange_data(struct zip_entry *);
239
239
 
240
+ // modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
241
+ int copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error);
242
+ int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
243
+ char *_zip_create_temp_output(struct zip *, FILE **);
244
+ void _zip_u2d_time(time_t, unsigned short *, unsigned short *);
245
+
240
246
  #endif /* zipint.h */
data/ext/zipruby.h CHANGED
@@ -1,8 +1,9 @@
1
1
  #ifndef __ZIPRUBY_H__
2
2
  #define __ZIPRUBY_H__
3
3
 
4
- #define VERSION "0.1.2"
4
+ #define VERSION "0.2.0"
5
5
  #define ERRSTR_BUFSIZE 256
6
+ #define DATA_BUFSIZE 8192
6
7
 
7
8
  void Init_zipruby();
8
9
 
@@ -9,6 +9,7 @@
9
9
  static VALUE zipruby_archive_alloc(VALUE klass);
10
10
  static void zipruby_archive_free(struct zipruby_archive *p);
11
11
  static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self);
12
+ static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password);
12
13
  static VALUE zipruby_archive_close(VALUE self);
13
14
  static VALUE zipruby_archive_num_files(VALUE self);
14
15
  static VALUE zipruby_archive_get_name(int argc, VALUE *argv, VALUE self);
@@ -48,6 +49,7 @@ void Init_zipruby_archive() {
48
49
  rb_define_alloc_func(Archive, zipruby_archive_alloc);
49
50
  rb_include_module(Archive, rb_mEnumerable);
50
51
  rb_define_singleton_method(Archive, "open", zipruby_archive_s_open, -1);
52
+ rb_define_singleton_method(Archive, "decrypt", zipruby_archive_s_decrypt, 2);
51
53
  rb_define_method(Archive, "close", zipruby_archive_close, 0);
52
54
  rb_define_method(Archive, "num_files", zipruby_archive_num_files, 0);
53
55
  rb_define_method(Archive, "get_name", zipruby_archive_get_name, -1);
@@ -131,7 +133,27 @@ static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self) {
131
133
  } else {
132
134
  return archive;
133
135
  }
134
- };
136
+ }
137
+
138
+ /* */
139
+ static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password) {
140
+ int errorp, wrongpwd;
141
+
142
+ Check_Type(path, T_STRING);
143
+ Check_Type(password, T_STRING);
144
+
145
+ if (zip_decrypt(StringValuePtr(path), StringValuePtr(password), RSTRING(password)->len, &errorp, &wrongpwd) == -1) {
146
+ if (wrongpwd) {
147
+ rb_raise(Error, "Decrypt archive failed - %s: Wrong password", StringValuePtr(path));
148
+ } else {
149
+ char errstr[ERRSTR_BUFSIZE];
150
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
151
+ rb_raise(Error, "Decrypt archive failed - %s: %s", StringValuePtr(path), errstr);
152
+ }
153
+ }
154
+
155
+ return Qnil;
156
+ }
135
157
 
136
158
  /* */
137
159
  static VALUE zipruby_archive_close(VALUE self) {
@@ -269,7 +291,11 @@ static VALUE zipruby_archive_replace_buffer(VALUE self, VALUE index, VALUE sourc
269
291
  Check_Archive(p_archive);
270
292
 
271
293
  len = RSTRING(source)->len;
272
- data = malloc(len);
294
+
295
+ if ((data = malloc(len)) == NULL) {
296
+ rb_raise(rb_eRuntimeError, "Replace file failed: Cannot allocate memory");
297
+ }
298
+
273
299
  memcpy(data, StringValuePtr(source), len);
274
300
 
275
301
  if ((zsource = zip_source_buffer(p_archive->archive, data, len, 1)) == NULL) {
data/ext/zipruby_file.c CHANGED
@@ -13,13 +13,15 @@
13
13
  #include "zipruby_stat.h"
14
14
  #include "ruby.h"
15
15
 
16
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
17
+
16
18
  static VALUE zipruby_file(VALUE klass);
17
19
  static VALUE zipruby_file_alloc(VALUE klass);
18
20
  static void zipruby_file_mark(struct zipruby_file *p);
19
21
  static void zipruby_file_free(struct zipruby_file *p);
20
22
  static VALUE zipruby_file_initialize(int argc, VALUE *argv, VALUE self);
21
23
  static VALUE zipruby_file_close(VALUE self);
22
- static VALUE zipruby_file_read(VALUE self);
24
+ static VALUE zipruby_file_read(int argc, VALUE *argv, VALUE self);
23
25
  static VALUE zipruby_file_stat(VALUE self);
24
26
  static VALUE zipruby_file_get_comment(int argc, VALUE *argv, VALUE self);
25
27
  static VALUE zipruby_file_set_comment(VALUE self, VALUE comment);
@@ -46,7 +48,7 @@ void Init_zipruby_file() {
46
48
  rb_define_alloc_func(File, zipruby_file_alloc);
47
49
  rb_define_method(File, "initialize", zipruby_file_initialize, -1);
48
50
  rb_define_method(File, "close", zipruby_file_close, 0);
49
- rb_define_method(File, "read", zipruby_file_read, 0);
51
+ rb_define_method(File, "read", zipruby_file_read, -1);
50
52
  rb_define_method(File, "stat", zipruby_file_stat, 0);
51
53
  rb_define_method(File, "get_comment", zipruby_file_get_comment, -1);
52
54
  rb_define_method(File, "comment", zipruby_file_get_comment, -1);
@@ -162,27 +164,55 @@ static VALUE zipruby_file_close(VALUE self) {
162
164
  }
163
165
 
164
166
  /* */
165
- static VALUE zipruby_file_read(VALUE self) {
167
+ static VALUE zipruby_file_read(int argc, VALUE *argv, VALUE self) {
168
+ VALUE size, retval = Qnil;
166
169
  struct zipruby_file *p_file;
167
170
  struct zip_stat sb;
168
- char *buf;
171
+ int block_given;
172
+ size_t bytes_left;
173
+ char buf[DATA_BUFSIZE];
174
+ ssize_t n;
169
175
 
176
+ rb_scan_args(argc, argv, "01", &size);
170
177
  Data_Get_Struct(self, struct zipruby_file, p_file);
171
178
  Check_File(p_file);
172
-
173
179
  zip_stat_init(&sb);
174
180
 
175
181
  if (zip_stat_index(p_file->archive, p_file->sb->index, 0, &sb)) {
176
182
  rb_raise(Error, "Read file failed: %s", zip_strerror(p_file->archive));
177
183
  }
178
184
 
179
- buf = alloca(sb.size);
180
-
181
- if (zip_fread(p_file->file, buf, sb.size) == -1) {
185
+ if (NIL_P(size)) {
186
+ bytes_left = sb.size;
187
+ } else {
188
+ bytes_left = NUM2LONG(size);
189
+ }
190
+
191
+ if (bytes_left <= 0) {
192
+ return Qnil;
193
+ }
194
+
195
+ block_given = rb_block_given_p();
196
+
197
+ while ((n = zip_fread(p_file->file, buf, MIN(bytes_left, sizeof(buf)))) > 0) {
198
+ if (block_given) {
199
+ rb_yield(rb_str_new(buf, n));
200
+ } else {
201
+ if (NIL_P(retval)) {
202
+ retval = rb_str_new(buf, n);
203
+ } else {
204
+ rb_str_buf_cat(retval, buf, n);
205
+ }
206
+ }
207
+
208
+ bytes_left -= n;
209
+ }
210
+
211
+ if (n == -1) {
182
212
  rb_raise(Error, "Read file failed: %s", zip_file_strerror(p_file->file));
183
213
  }
184
214
 
185
- return rb_str_new(buf, sb.size);
215
+ return retval;
186
216
  }
187
217
 
188
218
  /* */
data/zipruby.c CHANGED
@@ -28,6 +28,7 @@ void Init_zipruby() {
28
28
  static VALUE zipruby_archive_alloc(VALUE klass);
29
29
  static void zipruby_archive_free(struct zipruby_archive *p);
30
30
  static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self);
31
+ static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password);
31
32
  static VALUE zipruby_archive_close(VALUE self);
32
33
  static VALUE zipruby_archive_num_files(VALUE self);
33
34
  static VALUE zipruby_archive_get_name(int argc, VALUE *argv, VALUE self);
@@ -67,6 +68,7 @@ void Init_zipruby_archive() {
67
68
  rb_define_alloc_func(Archive, zipruby_archive_alloc);
68
69
  rb_include_module(Archive, rb_mEnumerable);
69
70
  rb_define_singleton_method(Archive, "open", zipruby_archive_s_open, -1);
71
+ rb_define_singleton_method(Archive, "decrypt", zipruby_archive_s_decrypt, 2);
70
72
  rb_define_method(Archive, "close", zipruby_archive_close, 0);
71
73
  rb_define_method(Archive, "num_files", zipruby_archive_num_files, 0);
72
74
  rb_define_method(Archive, "get_name", zipruby_archive_get_name, -1);
@@ -150,7 +152,27 @@ static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self) {
150
152
  } else {
151
153
  return archive;
152
154
  }
153
- };
155
+ }
156
+
157
+ /* */
158
+ static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password) {
159
+ int errorp, wrongpwd;
160
+
161
+ Check_Type(path, T_STRING);
162
+ Check_Type(password, T_STRING);
163
+
164
+ if (zip_decrypt(StringValuePtr(path), StringValuePtr(password), RSTRING(password)->len, &errorp, &wrongpwd) == -1) {
165
+ if (wrongpwd) {
166
+ rb_raise(Error, "Decrypt archive failed - %s: Wrong password", StringValuePtr(path));
167
+ } else {
168
+ char errstr[ERRSTR_BUFSIZE];
169
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
170
+ rb_raise(Error, "Decrypt archive failed - %s: %s", StringValuePtr(path), errstr);
171
+ }
172
+ }
173
+
174
+ return Qnil;
175
+ }
154
176
 
155
177
  /* */
156
178
  static VALUE zipruby_archive_close(VALUE self) {
@@ -288,7 +310,11 @@ static VALUE zipruby_archive_replace_buffer(VALUE self, VALUE index, VALUE sourc
288
310
  Check_Archive(p_archive);
289
311
 
290
312
  len = RSTRING(source)->len;
291
- data = malloc(len);
313
+
314
+ if ((data = malloc(len)) == NULL) {
315
+ rb_raise(rb_eRuntimeError, "Replace file failed: Cannot allocate memory");
316
+ }
317
+
292
318
  memcpy(data, StringValuePtr(source), len);
293
319
 
294
320
  if ((zsource = zip_source_buffer(p_archive->archive, data, len, 1)) == NULL) {
@@ -825,13 +851,15 @@ void Init_zipruby_error() {
825
851
  #include "zipruby_stat.h"
826
852
  #include "ruby.h"
827
853
 
854
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
855
+
828
856
  static VALUE zipruby_file(VALUE klass);
829
857
  static VALUE zipruby_file_alloc(VALUE klass);
830
858
  static void zipruby_file_mark(struct zipruby_file *p);
831
859
  static void zipruby_file_free(struct zipruby_file *p);
832
860
  static VALUE zipruby_file_initialize(int argc, VALUE *argv, VALUE self);
833
861
  static VALUE zipruby_file_close(VALUE self);
834
- static VALUE zipruby_file_read(VALUE self);
862
+ static VALUE zipruby_file_read(int argc, VALUE *argv, VALUE self);
835
863
  static VALUE zipruby_file_stat(VALUE self);
836
864
  static VALUE zipruby_file_get_comment(int argc, VALUE *argv, VALUE self);
837
865
  static VALUE zipruby_file_set_comment(VALUE self, VALUE comment);
@@ -858,7 +886,7 @@ void Init_zipruby_file() {
858
886
  rb_define_alloc_func(File, zipruby_file_alloc);
859
887
  rb_define_method(File, "initialize", zipruby_file_initialize, -1);
860
888
  rb_define_method(File, "close", zipruby_file_close, 0);
861
- rb_define_method(File, "read", zipruby_file_read, 0);
889
+ rb_define_method(File, "read", zipruby_file_read, -1);
862
890
  rb_define_method(File, "stat", zipruby_file_stat, 0);
863
891
  rb_define_method(File, "get_comment", zipruby_file_get_comment, -1);
864
892
  rb_define_method(File, "comment", zipruby_file_get_comment, -1);
@@ -974,27 +1002,55 @@ static VALUE zipruby_file_close(VALUE self) {
974
1002
  }
975
1003
 
976
1004
  /* */
977
- static VALUE zipruby_file_read(VALUE self) {
1005
+ static VALUE zipruby_file_read(int argc, VALUE *argv, VALUE self) {
1006
+ VALUE size, retval = Qnil;
978
1007
  struct zipruby_file *p_file;
979
1008
  struct zip_stat sb;
980
- char *buf;
1009
+ int block_given;
1010
+ size_t bytes_left;
1011
+ char buf[DATA_BUFSIZE];
1012
+ ssize_t n;
981
1013
 
1014
+ rb_scan_args(argc, argv, "01", &size);
982
1015
  Data_Get_Struct(self, struct zipruby_file, p_file);
983
1016
  Check_File(p_file);
984
-
985
1017
  zip_stat_init(&sb);
986
1018
 
987
1019
  if (zip_stat_index(p_file->archive, p_file->sb->index, 0, &sb)) {
988
1020
  rb_raise(Error, "Read file failed: %s", zip_strerror(p_file->archive));
989
1021
  }
990
1022
 
991
- buf = alloca(sb.size);
992
-
993
- if (zip_fread(p_file->file, buf, sb.size) == -1) {
1023
+ if (NIL_P(size)) {
1024
+ bytes_left = sb.size;
1025
+ } else {
1026
+ bytes_left = NUM2LONG(size);
1027
+ }
1028
+
1029
+ if (bytes_left <= 0) {
1030
+ return Qnil;
1031
+ }
1032
+
1033
+ block_given = rb_block_given_p();
1034
+
1035
+ while ((n = zip_fread(p_file->file, buf, MIN(bytes_left, sizeof(buf)))) > 0) {
1036
+ if (block_given) {
1037
+ rb_yield(rb_str_new(buf, n));
1038
+ } else {
1039
+ if (NIL_P(retval)) {
1040
+ retval = rb_str_new(buf, n);
1041
+ } else {
1042
+ rb_str_buf_cat(retval, buf, n);
1043
+ }
1044
+ }
1045
+
1046
+ bytes_left -= n;
1047
+ }
1048
+
1049
+ if (n == -1) {
994
1050
  rb_raise(Error, "Read file failed: %s", zip_file_strerror(p_file->file));
995
1051
  }
996
1052
 
997
- return rb_str_new(buf, sb.size);
1053
+ return retval;
998
1054
  }
999
1055
 
1000
1056
  /* */
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zipruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - winebarrel
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-04-26 00:00:00 +09:00
12
+ date: 2008-04-30 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -45,6 +45,7 @@ files:
45
45
  - ext/zip_add.c
46
46
  - ext/zip_add_dir.c
47
47
  - ext/zip_close.c
48
+ - ext/zip_crypt.c
48
49
  - ext/zip_delete.c
49
50
  - ext/zip_dirent.c
50
51
  - ext/zip_entry_free.c