zipruby 0.2.6 → 0.2.8
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/ext/extconf.rb +3 -0
- data/ext/tmpfile.c +173 -0
- data/ext/tmpfile.h +9 -0
- data/ext/zip.h +3 -0
- data/ext/zip_close.c +3 -3
- data/ext/zip_open.c +4 -0
- data/ext/zipruby.h +1 -1
- data/ext/zipruby_archive.c +165 -1
- data/ext/zipruby_archive.h +2 -0
- data/ext/zipruby_zip.c +1 -0
- data/ext/zipruby_zip_source_proc.c +6 -3
- data/zipruby.c +345 -4
- metadata +4 -4
- data/ext/foo.txt +0 -315
- data/ext/zipruby_archive.c.r112 +0 -978
data/ext/extconf.rb
CHANGED
data/ext/tmpfile.c
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include <sys/types.h>
|
5
|
+
#include <sys/stat.h>
|
6
|
+
|
7
|
+
#ifdef _WIN32
|
8
|
+
#include <windows.h>
|
9
|
+
#include <io.h>
|
10
|
+
#include <fcntl.h>
|
11
|
+
#include <share.h>
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#include "tmpfile.h"
|
15
|
+
#include "ruby.h"
|
16
|
+
|
17
|
+
#ifndef _WIN32
|
18
|
+
#ifndef HAVE_MKSTEMP
|
19
|
+
int _zip_mkstemp(char *);
|
20
|
+
#define mkstemp _zip_mkstemp
|
21
|
+
#endif
|
22
|
+
#endif
|
23
|
+
|
24
|
+
static int write_from_proc(VALUE proc, int fd);
|
25
|
+
static VALUE proc_call(VALUE proc);
|
26
|
+
|
27
|
+
char *zipruby_tmpnam(void *data, int len) {
|
28
|
+
char *filnam;
|
29
|
+
|
30
|
+
#ifdef _WIN32
|
31
|
+
int fd;
|
32
|
+
char tmpdirnam[_MAX_PATH];
|
33
|
+
char tmpfilnam[_MAX_PATH];
|
34
|
+
int namlen;
|
35
|
+
|
36
|
+
memset(tmpdirnam, 0, _MAX_PATH);
|
37
|
+
|
38
|
+
if (GetTempPathA(_MAX_PATH, tmpdirnam) == 0) {
|
39
|
+
return NULL;
|
40
|
+
}
|
41
|
+
|
42
|
+
memset(tmpfilnam, 0, _MAX_PATH);
|
43
|
+
|
44
|
+
if (GetTempFileNameA(tmpdirnam, "zrb", 0, tmpfilnam) == 0) {
|
45
|
+
return NULL;
|
46
|
+
}
|
47
|
+
|
48
|
+
namlen = strlen(tmpfilnam) + 1;
|
49
|
+
|
50
|
+
if ((filnam = calloc(namlen, sizeof(char))) == NULL) {
|
51
|
+
return NULL;
|
52
|
+
}
|
53
|
+
|
54
|
+
if (strcpy_s(filnam, namlen, tmpfilnam) != 0) {
|
55
|
+
free(filnam);
|
56
|
+
return NULL;
|
57
|
+
}
|
58
|
+
|
59
|
+
if (data) {
|
60
|
+
if ((_sopen_s(&fd, filnam, _O_WRONLY | _O_BINARY, _SH_DENYRD, _S_IWRITE)) != 0) {
|
61
|
+
free(filnam);
|
62
|
+
return NULL;
|
63
|
+
}
|
64
|
+
|
65
|
+
if (len < 0) {
|
66
|
+
if (write_from_proc((VALUE) data, fd) == -1) {
|
67
|
+
free(filnam);
|
68
|
+
return NULL;
|
69
|
+
}
|
70
|
+
} else {
|
71
|
+
if (_write(fd, data, len) == -1) {
|
72
|
+
free(filnam);
|
73
|
+
return NULL;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
if (_close(fd) == -1) {
|
78
|
+
free(filnam);
|
79
|
+
return NULL;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
#else
|
83
|
+
int fd;
|
84
|
+
#ifdef P_tmpdir
|
85
|
+
int namlen = 16 + strlen(P_tmpdir);
|
86
|
+
char *dirnam = P_tmpdir;
|
87
|
+
#else
|
88
|
+
int namlen = 20;
|
89
|
+
char *dirnam = "/tmp";
|
90
|
+
#endif
|
91
|
+
|
92
|
+
if ((filnam = calloc(namlen, sizeof(char))) == NULL) {
|
93
|
+
return NULL;
|
94
|
+
}
|
95
|
+
|
96
|
+
strcpy(filnam, dirnam);
|
97
|
+
strcat(filnam, "/zipruby.XXXXXX");
|
98
|
+
|
99
|
+
if ((fd = mkstemp(filnam)) == -1) {
|
100
|
+
free(filnam);
|
101
|
+
return NULL;
|
102
|
+
}
|
103
|
+
|
104
|
+
if (data) {
|
105
|
+
if (len < 0) {
|
106
|
+
if (write_from_proc((VALUE) data, fd) == -1) {
|
107
|
+
free(filnam);
|
108
|
+
return NULL;
|
109
|
+
}
|
110
|
+
} else {
|
111
|
+
if (write(fd, data, len) == -1) {
|
112
|
+
free(filnam);
|
113
|
+
return NULL;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
if (close(fd) == -1) {
|
119
|
+
free(filnam);
|
120
|
+
return NULL;
|
121
|
+
}
|
122
|
+
#endif
|
123
|
+
|
124
|
+
return filnam;
|
125
|
+
}
|
126
|
+
|
127
|
+
void zipruby_rmtmp(const char *tmpfilnam) {
|
128
|
+
struct stat st;
|
129
|
+
|
130
|
+
if (!tmpfilnam) {
|
131
|
+
return;
|
132
|
+
}
|
133
|
+
|
134
|
+
if (stat(tmpfilnam, &st) != 0) {
|
135
|
+
return;
|
136
|
+
}
|
137
|
+
|
138
|
+
#ifdef _WIN32
|
139
|
+
_unlink(tmpfilnam);
|
140
|
+
#else
|
141
|
+
unlink(tmpfilnam);
|
142
|
+
#endif
|
143
|
+
}
|
144
|
+
|
145
|
+
static int write_from_proc(VALUE proc, int fd) {
|
146
|
+
while (1) {
|
147
|
+
VALUE src = rb_protect(proc_call, proc, NULL);
|
148
|
+
|
149
|
+
if (TYPE(src) != T_STRING) {
|
150
|
+
break;
|
151
|
+
}
|
152
|
+
|
153
|
+
if (RSTRING(src)->len < 1) {
|
154
|
+
break;
|
155
|
+
}
|
156
|
+
|
157
|
+
#ifdef _WIN32
|
158
|
+
if (_write(fd, StringValuePtr(src), RSTRING(src)->len) == -1) {
|
159
|
+
return -1;
|
160
|
+
}
|
161
|
+
#else
|
162
|
+
if (write(fd, StringValuePtr(src), RSTRING(src)->len) == -1) {
|
163
|
+
return -1;
|
164
|
+
}
|
165
|
+
#endif
|
166
|
+
}
|
167
|
+
|
168
|
+
return 0;
|
169
|
+
}
|
170
|
+
|
171
|
+
static VALUE proc_call(VALUE proc) {
|
172
|
+
return rb_funcall(proc, rb_intern("call"), 0);
|
173
|
+
}
|
data/ext/tmpfile.h
ADDED
data/ext/zip.h
CHANGED
@@ -55,6 +55,8 @@ typedef int ssize_t;
|
|
55
55
|
#define ZIP_CREATE 1
|
56
56
|
#define ZIP_EXCL 2
|
57
57
|
#define ZIP_CHECKCONS 4
|
58
|
+
// modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
59
|
+
#define ZIP_TRUNC 8
|
58
60
|
|
59
61
|
|
60
62
|
/* flags for zip_name_locate, zip_fopen, zip_stat, ... */
|
@@ -207,6 +209,7 @@ int zip_unchange_archive(struct zip *);
|
|
207
209
|
// modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
208
210
|
int zip_decrypt(const char *path, const char *pwd, int pwdlen, int *errorp, int *wrongpwd);
|
209
211
|
int zip_encrypt(const char *path, const char *pwd, int pwdlen, int *errorp);
|
212
|
+
int _zip_changed(struct zip *, int *);
|
210
213
|
|
211
214
|
#ifdef __cplusplus
|
212
215
|
}
|
data/ext/zip_close.c
CHANGED
@@ -61,8 +61,7 @@ static void ch_set_error(struct zip_error *, zip_source_callback, void *);
|
|
61
61
|
// modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
62
62
|
//static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
|
63
63
|
//static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
|
64
|
-
static int _zip_changed(struct zip *, int *);
|
65
|
-
// modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
64
|
+
//static int _zip_changed(struct zip *, int *);
|
66
65
|
//static char *_zip_create_temp_output(struct zip *, FILE **);
|
67
66
|
|
68
67
|
|
@@ -512,7 +511,8 @@ _zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src)
|
|
512
511
|
|
513
512
|
|
514
513
|
|
515
|
-
|
514
|
+
// modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
515
|
+
/*static*/ int
|
516
516
|
_zip_changed(struct zip *za, int *survivorsp)
|
517
517
|
{
|
518
518
|
int changed, i, survivors;
|
data/ext/zip_open.c
CHANGED
@@ -409,6 +409,10 @@ _zip_file_exists(const char *fn, int flags, int *zep)
|
|
409
409
|
return -1;
|
410
410
|
}
|
411
411
|
}
|
412
|
+
// modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
413
|
+
else if ((flags & ZIP_CREATE) && (flags & ZIP_TRUNC)) {
|
414
|
+
return 0;
|
415
|
+
}
|
412
416
|
else if ((flags & ZIP_EXCL)) {
|
413
417
|
set_error(zep, NULL, ZIP_ER_EXISTS);
|
414
418
|
return -1;
|
data/ext/zipruby.h
CHANGED
data/ext/zipruby_archive.c
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
#include "zipruby.h"
|
5
5
|
#include "zipruby_archive.h"
|
6
6
|
#include "zipruby_zip_source_proc.h"
|
7
|
+
#include "tmpfile.h"
|
7
8
|
#include "ruby.h"
|
8
9
|
#include "rubyio.h"
|
9
10
|
|
@@ -11,6 +12,7 @@ static VALUE zipruby_archive_alloc(VALUE klass);
|
|
11
12
|
static void zipruby_archive_mark(struct zipruby_archive *p);
|
12
13
|
static void zipruby_archive_free(struct zipruby_archive *p);
|
13
14
|
static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self);
|
15
|
+
static VALUE zipruby_archive_s_open_buffer(int argc, VALUE *argv, VALUE self);
|
14
16
|
static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password);
|
15
17
|
static VALUE zipruby_archive_s_encrypt(VALUE self, VALUE path, VALUE password);
|
16
18
|
static VALUE zipruby_archive_close(VALUE self);
|
@@ -47,6 +49,7 @@ static VALUE zipruby_archive_commit(VALUE self);
|
|
47
49
|
static VALUE zipruby_archive_is_open(VALUE self);
|
48
50
|
static VALUE zipruby_archive_decrypt(VALUE self, VALUE password);
|
49
51
|
static VALUE zipruby_archive_encrypt(VALUE self, VALUE password);
|
52
|
+
static VALUE zipruby_archive_read(VALUE self);
|
50
53
|
|
51
54
|
extern VALUE Zip;
|
52
55
|
VALUE Archive;
|
@@ -59,6 +62,7 @@ void Init_zipruby_archive() {
|
|
59
62
|
rb_define_alloc_func(Archive, zipruby_archive_alloc);
|
60
63
|
rb_include_module(Archive, rb_mEnumerable);
|
61
64
|
rb_define_singleton_method(Archive, "open", zipruby_archive_s_open, -1);
|
65
|
+
rb_define_singleton_method(Archive, "open_buffer", zipruby_archive_s_open_buffer, -1);
|
62
66
|
rb_define_singleton_method(Archive, "decrypt", zipruby_archive_s_decrypt, 2);
|
63
67
|
rb_define_singleton_method(Archive, "encrypt", zipruby_archive_s_encrypt, 2);
|
64
68
|
rb_define_method(Archive, "close", zipruby_archive_close, 0);
|
@@ -98,6 +102,7 @@ void Init_zipruby_archive() {
|
|
98
102
|
rb_define_method(Archive, "open?", zipruby_archive_is_open, 0);
|
99
103
|
rb_define_method(Archive, "decrypt", zipruby_archive_decrypt, 1);
|
100
104
|
rb_define_method(Archive, "encrypt", zipruby_archive_encrypt, 1);
|
105
|
+
rb_define_method(Archive, "read", zipruby_archive_read, 0);
|
101
106
|
}
|
102
107
|
|
103
108
|
static VALUE zipruby_archive_alloc(VALUE klass) {
|
@@ -106,15 +111,23 @@ static VALUE zipruby_archive_alloc(VALUE klass) {
|
|
106
111
|
p->archive = NULL;
|
107
112
|
p->path = Qnil;
|
108
113
|
p->flags = 0;
|
114
|
+
p->tmpfilnam = NULL;
|
115
|
+
p->buffer = Qnil;
|
109
116
|
|
110
117
|
return Data_Wrap_Struct(klass, zipruby_archive_mark, zipruby_archive_free, p);
|
111
118
|
}
|
112
119
|
|
113
120
|
static void zipruby_archive_mark(struct zipruby_archive *p) {
|
114
121
|
rb_gc_mark(p->path);
|
122
|
+
rb_gc_mark(p->buffer);
|
115
123
|
}
|
116
124
|
|
117
125
|
static void zipruby_archive_free(struct zipruby_archive *p) {
|
126
|
+
if (p->tmpfilnam) {
|
127
|
+
zipruby_rmtmp(p->tmpfilnam);
|
128
|
+
free(p->tmpfilnam);
|
129
|
+
}
|
130
|
+
|
118
131
|
xfree(p);
|
119
132
|
}
|
120
133
|
|
@@ -162,6 +175,76 @@ static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self) {
|
|
162
175
|
}
|
163
176
|
}
|
164
177
|
|
178
|
+
/* */
|
179
|
+
static VALUE zipruby_archive_s_open_buffer(int argc, VALUE *argv, VALUE self) {
|
180
|
+
VALUE buffer, flags;
|
181
|
+
VALUE archive;
|
182
|
+
struct zipruby_archive *p_archive;
|
183
|
+
void *data = NULL;
|
184
|
+
int len = 0, i_flags = 0;
|
185
|
+
int errorp;
|
186
|
+
|
187
|
+
rb_scan_args(argc, argv, "02", &buffer, &flags);
|
188
|
+
|
189
|
+
if (FIXNUM_P(buffer) && NIL_P(flags)) {
|
190
|
+
flags = buffer;
|
191
|
+
buffer = Qnil;
|
192
|
+
}
|
193
|
+
|
194
|
+
if (!NIL_P(flags)) {
|
195
|
+
i_flags = NUM2INT(flags);
|
196
|
+
}
|
197
|
+
|
198
|
+
if (i_flags & ZIP_CREATE) {
|
199
|
+
if (!NIL_P(buffer)) {
|
200
|
+
Check_Type(buffer, T_STRING);
|
201
|
+
}
|
202
|
+
|
203
|
+
i_flags = (i_flags | ZIP_TRUNC);
|
204
|
+
} else if (TYPE(buffer) == T_STRING) {
|
205
|
+
data = StringValuePtr(buffer);
|
206
|
+
len = RSTRING(buffer)->len;
|
207
|
+
} else if (rb_obj_is_instance_of(buffer, rb_cProc)) {
|
208
|
+
data = (void *) buffer;
|
209
|
+
len = -1;
|
210
|
+
} else {
|
211
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Proc)", rb_class2name(CLASS_OF(buffer)));
|
212
|
+
}
|
213
|
+
|
214
|
+
archive = rb_funcall(Archive, rb_intern("new"), 0);
|
215
|
+
Data_Get_Struct(archive, struct zipruby_archive, p_archive);
|
216
|
+
|
217
|
+
if ((p_archive->tmpfilnam = zipruby_tmpnam(data, len)) == NULL) {
|
218
|
+
rb_raise(Error, "Open archive failed: Failed to create temporary file");
|
219
|
+
}
|
220
|
+
|
221
|
+
if ((p_archive->archive = zip_open(p_archive->tmpfilnam, i_flags, &errorp)) == NULL) {
|
222
|
+
char errstr[ERRSTR_BUFSIZE];
|
223
|
+
zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
|
224
|
+
rb_raise(Error, "Open archive failed: %s", errstr);
|
225
|
+
}
|
226
|
+
|
227
|
+
p_archive->path = rb_str_new2(p_archive->tmpfilnam);
|
228
|
+
p_archive->flags = i_flags;
|
229
|
+
p_archive->buffer = buffer;
|
230
|
+
|
231
|
+
if (rb_block_given_p()) {
|
232
|
+
VALUE retval;
|
233
|
+
int status;
|
234
|
+
|
235
|
+
retval = rb_protect(rb_yield, archive, &status);
|
236
|
+
zipruby_archive_close(archive);
|
237
|
+
|
238
|
+
if (status != 0) {
|
239
|
+
rb_jump_tag(status);
|
240
|
+
}
|
241
|
+
|
242
|
+
return retval;
|
243
|
+
} else {
|
244
|
+
return archive;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
165
248
|
/* */
|
166
249
|
static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password) {
|
167
250
|
int errorp, wrongpwd;
|
@@ -217,6 +300,7 @@ static VALUE zipruby_archive_s_encrypt(VALUE self, VALUE path, VALUE password) {
|
|
217
300
|
/* */
|
218
301
|
static VALUE zipruby_archive_close(VALUE self) {
|
219
302
|
struct zipruby_archive *p_archive;
|
303
|
+
int changed, survivors;
|
220
304
|
|
221
305
|
if (!zipruby_archive_is_open(self)) {
|
222
306
|
return Qfalse;
|
@@ -225,14 +309,20 @@ static VALUE zipruby_archive_close(VALUE self) {
|
|
225
309
|
Data_Get_Struct(self, struct zipruby_archive, p_archive);
|
226
310
|
Check_Archive(p_archive);
|
227
311
|
|
312
|
+
changed = _zip_changed(p_archive->archive, &survivors);
|
313
|
+
|
228
314
|
if (zip_close(p_archive->archive) == -1) {
|
229
315
|
zip_unchange_all(p_archive->archive);
|
230
316
|
zip_unchange_archive(p_archive->archive);
|
231
317
|
rb_raise(Error, "Close archive failed: %s", zip_strerror(p_archive->archive));
|
232
318
|
}
|
233
319
|
|
320
|
+
if (!NIL_P(p_archive->buffer) && changed) {
|
321
|
+
rb_funcall(p_archive->buffer, rb_intern("replace"), 1, rb_funcall(self, rb_intern("read"), 0));
|
322
|
+
}
|
323
|
+
|
324
|
+
zipruby_rmtmp(p_archive->tmpfilnam);
|
234
325
|
p_archive->archive = NULL;
|
235
|
-
p_archive->path = Qnil;
|
236
326
|
p_archive->flags = 0;
|
237
327
|
|
238
328
|
return Qtrue;
|
@@ -1068,17 +1158,24 @@ static VALUE zipruby_archive_each(VALUE self) {
|
|
1068
1158
|
/* */
|
1069
1159
|
static VALUE zipruby_archive_commit(VALUE self) {
|
1070
1160
|
struct zipruby_archive *p_archive;
|
1161
|
+
int changed, survivors;
|
1071
1162
|
int errorp;
|
1072
1163
|
|
1073
1164
|
Data_Get_Struct(self, struct zipruby_archive, p_archive);
|
1074
1165
|
Check_Archive(p_archive);
|
1075
1166
|
|
1167
|
+
changed = _zip_changed(p_archive->archive, &survivors);
|
1168
|
+
|
1076
1169
|
if (zip_close(p_archive->archive) == -1) {
|
1077
1170
|
zip_unchange_all(p_archive->archive);
|
1078
1171
|
zip_unchange_archive(p_archive->archive);
|
1079
1172
|
rb_raise(Error, "Commit archive failed: %s", zip_strerror(p_archive->archive));
|
1080
1173
|
}
|
1081
1174
|
|
1175
|
+
if (!NIL_P(p_archive->buffer) && changed) {
|
1176
|
+
rb_funcall(p_archive->buffer, rb_intern("replace"), 1, rb_funcall(self, rb_intern("read"), 0));
|
1177
|
+
}
|
1178
|
+
|
1082
1179
|
p_archive->archive = NULL;
|
1083
1180
|
p_archive->flags = (p_archive->flags & ~(ZIP_CREATE | ZIP_EXCL));
|
1084
1181
|
|
@@ -1103,6 +1200,7 @@ static VALUE zipruby_archive_is_open(VALUE self) {
|
|
1103
1200
|
static VALUE zipruby_archive_decrypt(VALUE self, VALUE password) {
|
1104
1201
|
struct zipruby_archive *p_archive;
|
1105
1202
|
long pwdlen;
|
1203
|
+
int changed, survivors;
|
1106
1204
|
int errorp;
|
1107
1205
|
|
1108
1206
|
Check_Type(password, T_STRING);
|
@@ -1117,12 +1215,18 @@ static VALUE zipruby_archive_decrypt(VALUE self, VALUE password) {
|
|
1117
1215
|
Data_Get_Struct(self, struct zipruby_archive, p_archive);
|
1118
1216
|
Check_Archive(p_archive);
|
1119
1217
|
|
1218
|
+
changed = _zip_changed(p_archive->archive, &survivors);
|
1219
|
+
|
1120
1220
|
if (zip_close(p_archive->archive) == -1) {
|
1121
1221
|
zip_unchange_all(p_archive->archive);
|
1122
1222
|
zip_unchange_archive(p_archive->archive);
|
1123
1223
|
rb_raise(Error, "Decrypt archive failed: %s", zip_strerror(p_archive->archive));
|
1124
1224
|
}
|
1125
1225
|
|
1226
|
+
if (!NIL_P(p_archive->buffer) && changed) {
|
1227
|
+
rb_funcall(p_archive->buffer, rb_intern("replace"), 1, rb_funcall(self, rb_intern("read"), 0));
|
1228
|
+
}
|
1229
|
+
|
1126
1230
|
p_archive->archive = NULL;
|
1127
1231
|
p_archive->flags = (p_archive->flags & ~(ZIP_CREATE | ZIP_EXCL));
|
1128
1232
|
|
@@ -1141,6 +1245,7 @@ static VALUE zipruby_archive_decrypt(VALUE self, VALUE password) {
|
|
1141
1245
|
static VALUE zipruby_archive_encrypt(VALUE self, VALUE password) {
|
1142
1246
|
struct zipruby_archive *p_archive;
|
1143
1247
|
long pwdlen;
|
1248
|
+
int changed, survivors;
|
1144
1249
|
int errorp;
|
1145
1250
|
|
1146
1251
|
Check_Type(password, T_STRING);
|
@@ -1155,12 +1260,18 @@ static VALUE zipruby_archive_encrypt(VALUE self, VALUE password) {
|
|
1155
1260
|
Data_Get_Struct(self, struct zipruby_archive, p_archive);
|
1156
1261
|
Check_Archive(p_archive);
|
1157
1262
|
|
1263
|
+
changed = _zip_changed(p_archive->archive, &survivors);
|
1264
|
+
|
1158
1265
|
if (zip_close(p_archive->archive) == -1) {
|
1159
1266
|
zip_unchange_all(p_archive->archive);
|
1160
1267
|
zip_unchange_archive(p_archive->archive);
|
1161
1268
|
rb_raise(Error, "Encrypt archive failed: %s", zip_strerror(p_archive->archive));
|
1162
1269
|
}
|
1163
1270
|
|
1271
|
+
if (!NIL_P(p_archive->buffer) && changed) {
|
1272
|
+
rb_funcall(p_archive->buffer, rb_intern("replace"), 1, rb_funcall(self, rb_intern("read"), 0));
|
1273
|
+
}
|
1274
|
+
|
1164
1275
|
p_archive->archive = NULL;
|
1165
1276
|
p_archive->flags = (p_archive->flags & ~(ZIP_CREATE | ZIP_EXCL));
|
1166
1277
|
|
@@ -1174,3 +1285,56 @@ static VALUE zipruby_archive_encrypt(VALUE self, VALUE password) {
|
|
1174
1285
|
|
1175
1286
|
return Qnil;
|
1176
1287
|
}
|
1288
|
+
|
1289
|
+
static VALUE zipruby_archive_read(VALUE self) {
|
1290
|
+
VALUE retval = Qnil;
|
1291
|
+
struct zipruby_archive *p_archive;
|
1292
|
+
FILE *fzip;
|
1293
|
+
char buf[DATA_BUFSIZE];
|
1294
|
+
ssize_t n;
|
1295
|
+
int block_given;
|
1296
|
+
|
1297
|
+
Data_Get_Struct(self, struct zipruby_archive, p_archive);
|
1298
|
+
|
1299
|
+
if (NIL_P(p_archive->path)) {
|
1300
|
+
rb_raise(rb_eRuntimeError, "invalid Zip::Archive");
|
1301
|
+
}
|
1302
|
+
|
1303
|
+
#ifdef _WIN32
|
1304
|
+
if (fopen_s(&fzip ,StringValuePtr(p_archive->path), "rb") != 0) {
|
1305
|
+
rb_raise(Error, "Read archive failed: Cannot open archive");
|
1306
|
+
}
|
1307
|
+
#else
|
1308
|
+
if ((fzip = fopen(StringValuePtr(p_archive->path), "rb")) == NULL) {
|
1309
|
+
rb_raise(Error, "Read archive failed: Cannot open archive");
|
1310
|
+
}
|
1311
|
+
#endif
|
1312
|
+
|
1313
|
+
block_given = rb_block_given_p();
|
1314
|
+
|
1315
|
+
while ((n = fread(buf, 1, sizeof(buf), fzip)) > 0) {
|
1316
|
+
if (block_given) {
|
1317
|
+
rb_yield(rb_str_new(buf, n));
|
1318
|
+
} else {
|
1319
|
+
if (NIL_P(retval)) {
|
1320
|
+
retval = rb_str_new(buf, n);
|
1321
|
+
} else {
|
1322
|
+
rb_str_buf_cat(retval, buf, n);
|
1323
|
+
}
|
1324
|
+
}
|
1325
|
+
}
|
1326
|
+
|
1327
|
+
#ifdef RUBY_WIN32_H
|
1328
|
+
#undef fclose
|
1329
|
+
fclose(fzip);
|
1330
|
+
#define fclose(f) rb_w32_fclose(f)
|
1331
|
+
#else
|
1332
|
+
fclose(fzip);
|
1333
|
+
#endif
|
1334
|
+
|
1335
|
+
if (n == -1) {
|
1336
|
+
rb_raise(Error, "Read archive failed");
|
1337
|
+
}
|
1338
|
+
|
1339
|
+
return retval;
|
1340
|
+
}
|
data/ext/zipruby_archive.h
CHANGED
data/ext/zipruby_zip.c
CHANGED
@@ -12,6 +12,7 @@ void Init_zipruby_zip() {
|
|
12
12
|
rb_define_const(Zip, "CREATE", INT2NUM(ZIP_CREATE));
|
13
13
|
rb_define_const(Zip, "EXCL", INT2NUM(ZIP_EXCL));
|
14
14
|
rb_define_const(Zip, "CHECKCONS", INT2NUM(ZIP_CHECKCONS));
|
15
|
+
rb_define_const(Zip, "TRUNC", INT2NUM(ZIP_TRUNC));
|
15
16
|
|
16
17
|
rb_define_const(Zip, "FL_NOCASE", INT2NUM(ZIP_FL_NOCASE));
|
17
18
|
rb_define_const(Zip, "FL_NODIR", INT2NUM(ZIP_FL_NODIR));
|
@@ -5,6 +5,10 @@
|
|
5
5
|
#include "zipruby_zip_source_proc.h"
|
6
6
|
#include "ruby.h"
|
7
7
|
|
8
|
+
static VALUE proc_call(VALUE proc) {
|
9
|
+
return rb_funcall(proc, rb_intern("call"), 0);
|
10
|
+
}
|
11
|
+
|
8
12
|
static ssize_t read_proc(void *state, void *data, size_t len, enum zip_source_cmd cmd) {
|
9
13
|
struct read_proc *z;
|
10
14
|
VALUE src;
|
@@ -19,13 +23,12 @@ static ssize_t read_proc(void *state, void *data, size_t len, enum zip_source_cm
|
|
19
23
|
return 0;
|
20
24
|
|
21
25
|
case ZIP_SOURCE_READ:
|
22
|
-
src =
|
26
|
+
src = rb_protect(proc_call, z->proc, NULL);
|
23
27
|
|
24
|
-
if (
|
28
|
+
if (TYPE(src) != T_STRING) {
|
25
29
|
return 0;
|
26
30
|
}
|
27
31
|
|
28
|
-
src = rb_check_convert_type(src, T_STRING, "String", "to_s");
|
29
32
|
n = RSTRING(src)->len;
|
30
33
|
|
31
34
|
if (n > 0) {
|