zipruby 0.2.1 → 0.2.2
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 +8 -4
- data/ext/zip.h +1 -0
- data/ext/zip_crypt.c +116 -6
- data/ext/zipruby.h +1 -1
- data/ext/zipruby_archive.c +35 -1
- data/ext/zipruby_file.c +5 -0
- data/zipruby.c +40 -1
- metadata +1 -1
data/README.txt
CHANGED
@@ -21,7 +21,7 @@ gem install zipruby
|
|
21
21
|
https://rubyforge.org/frs/?group_id=6124
|
22
22
|
|
23
23
|
== Example
|
24
|
-
=== reading zip
|
24
|
+
=== reading zip archive
|
25
25
|
|
26
26
|
require 'zipruby'
|
27
27
|
|
@@ -64,7 +64,7 @@ https://rubyforge.org/frs/?group_id=6124
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
=== creating zip
|
67
|
+
=== creating zip archive
|
68
68
|
|
69
69
|
require 'zipruby'
|
70
70
|
|
@@ -94,7 +94,7 @@ https://rubyforge.org/frs/?group_id=6124
|
|
94
94
|
# args: <entry name>, <source>
|
95
95
|
end
|
96
96
|
|
97
|
-
=== modifying zip
|
97
|
+
=== modifying zip archive
|
98
98
|
|
99
99
|
require 'zipruby'
|
100
100
|
|
@@ -130,10 +130,14 @@ https://rubyforge.org/frs/?group_id=6124
|
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
|
-
=== decrypt zip
|
133
|
+
=== encrypt/decrypt zip archive
|
134
134
|
|
135
135
|
require 'zipruby'
|
136
136
|
|
137
|
+
# encrypt
|
138
|
+
Zip::Archive.encrypt('filename.zip', 'password')
|
139
|
+
|
140
|
+
# decrypt
|
137
141
|
Zip::Archive.decrypt('filename.zip', 'password')
|
138
142
|
|
139
143
|
== License
|
data/ext/zip.h
CHANGED
@@ -206,6 +206,7 @@ int zip_unchange_archive(struct zip *);
|
|
206
206
|
|
207
207
|
// modified for Zip/Ruby by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
|
208
208
|
int zip_decrypt(const char *path, const char *pwd, int pwdlen, int *errorp, int *wrongpwd);
|
209
|
+
int zip_encrypt(const char *path, const char *pwd, int pwdlen, int *errorp);
|
209
210
|
|
210
211
|
#ifdef __cplusplus
|
211
212
|
}
|
data/ext/zip_crypt.c
CHANGED
@@ -56,7 +56,6 @@ static void init_keys(uLong *keys, const char *password, size_t len) {
|
|
56
56
|
static int decrypt_header(unsigned long *keys, char *buffer, struct zip_dirent *de) {
|
57
57
|
int i;
|
58
58
|
char c;
|
59
|
-
unsigned short dostime, dosdate;
|
60
59
|
|
61
60
|
for (i = 0; i < ZIPENC_HEAD_LEN; i++) {
|
62
61
|
c = buffer[i] ^ decrypt_byte(keys);
|
@@ -64,11 +63,11 @@ static int decrypt_header(unsigned long *keys, char *buffer, struct zip_dirent *
|
|
64
63
|
buffer[i] = c;
|
65
64
|
}
|
66
65
|
|
67
|
-
_zip_u2d_time(de->last_mod, &dostime, &dosdate);
|
68
|
-
|
69
66
|
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
70
67
|
return ((c & 0xff) == (de->crc >> 24)) ? 0 : -1;
|
71
68
|
} else {
|
69
|
+
unsigned short dostime, dosdate;
|
70
|
+
_zip_u2d_time(de->last_mod, &dostime, &dosdate);
|
72
71
|
return ((c & 0xff) == (dostime >> 8)) ? 0 : -1;
|
73
72
|
}
|
74
73
|
}
|
@@ -128,6 +127,97 @@ static int copy_decrypt(FILE *src, off_t len, const char *pwd, int pwdlen, struc
|
|
128
127
|
return 0;
|
129
128
|
}
|
130
129
|
|
130
|
+
static void generate_random_header(unsigned long *keys, char *buffer) {
|
131
|
+
static int initialized = 0;
|
132
|
+
int i;
|
133
|
+
|
134
|
+
if (!initialized) {
|
135
|
+
srand((unsigned) time(NULL));
|
136
|
+
initialized = 1;
|
137
|
+
}
|
138
|
+
|
139
|
+
for (i = 0; i < ZIPENC_HEAD_LEN - 2; i++) {
|
140
|
+
char temp = decrypt_byte(keys);
|
141
|
+
char c = rand() % 0xff;
|
142
|
+
update_keys(keys, c);
|
143
|
+
buffer[i] = temp ^ c;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
static void encrypt_header(unsigned long *keys, char *buffer, struct zip_dirent *de) {
|
148
|
+
int i;
|
149
|
+
char c, temp;
|
150
|
+
|
151
|
+
for (i = 0; i < ZIPENC_HEAD_LEN - 2; i++) {
|
152
|
+
temp = decrypt_byte(keys);
|
153
|
+
c = buffer[i];
|
154
|
+
update_keys(keys, c);
|
155
|
+
buffer[i] = temp ^ c;
|
156
|
+
}
|
157
|
+
|
158
|
+
temp = decrypt_byte(keys);
|
159
|
+
c = (de->crc >> 16) & 0xff;
|
160
|
+
update_keys(keys, c);
|
161
|
+
buffer[ZIPENC_HEAD_LEN - 2] = temp ^ c;
|
162
|
+
|
163
|
+
temp = decrypt_byte(keys);
|
164
|
+
c = (de->crc >> 24) & 0xff;
|
165
|
+
update_keys(keys, c);
|
166
|
+
buffer[ZIPENC_HEAD_LEN - 1] = temp ^ c;
|
167
|
+
}
|
168
|
+
|
169
|
+
static void encrypt_data(uLong *keys, char *buffer, size_t n) {
|
170
|
+
int i;
|
171
|
+
|
172
|
+
for (i = 0; i < n; i++) {
|
173
|
+
char temp = decrypt_byte(keys);
|
174
|
+
char c = buffer[i];
|
175
|
+
update_keys(keys, c);
|
176
|
+
buffer[i] = temp ^ c;
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
static int copy_encrypt(FILE *src, off_t len, const char *pwd, int pwdlen, struct zip_dirent *de, FILE *dest, struct zip_error *error) {
|
181
|
+
char header[ZIPENC_HEAD_LEN];
|
182
|
+
char buf[BUFSIZE];
|
183
|
+
uLong keys[3];
|
184
|
+
int n;
|
185
|
+
|
186
|
+
if (len == 0) {
|
187
|
+
return 0;
|
188
|
+
}
|
189
|
+
|
190
|
+
init_keys(keys, pwd, pwdlen);
|
191
|
+
generate_random_header(keys, header);
|
192
|
+
init_keys(keys, pwd, pwdlen);
|
193
|
+
encrypt_header(keys, header, de);
|
194
|
+
|
195
|
+
if (fwrite(header, 1, ZIPENC_HEAD_LEN, dest) != ((size_t) ZIPENC_HEAD_LEN)) {
|
196
|
+
_zip_error_set(error, ZIP_ER_WRITE, errno);
|
197
|
+
}
|
198
|
+
|
199
|
+
while (len > 0) {
|
200
|
+
if ((n = fread(buf, 1, MIN(len, sizeof(buf)), src)) < 0) {
|
201
|
+
_zip_error_set(error, ZIP_ER_READ, errno);
|
202
|
+
return -1;
|
203
|
+
} else if (n == 0) {
|
204
|
+
_zip_error_set(error, ZIP_ER_EOF, 0);
|
205
|
+
return -1;
|
206
|
+
}
|
207
|
+
|
208
|
+
encrypt_data(keys, buf, n);
|
209
|
+
|
210
|
+
if (fwrite(buf, 1, n, dest) != ((size_t) n)) {
|
211
|
+
_zip_error_set(error, ZIP_ER_WRITE, errno);
|
212
|
+
return -1;
|
213
|
+
}
|
214
|
+
|
215
|
+
len -= n;
|
216
|
+
}
|
217
|
+
|
218
|
+
return 0;
|
219
|
+
}
|
220
|
+
|
131
221
|
static int _zip_crypt(struct zip *za, const char *pwd, int pwdlen, int decrypt, int *wrongpwd) {
|
132
222
|
int i, error = 0;
|
133
223
|
char *temp;
|
@@ -202,7 +292,10 @@ static int _zip_crypt(struct zip *za, const char *pwd, int pwdlen, int decrypt,
|
|
202
292
|
cd->entry[i].comp_size -= ZIPENC_HEAD_LEN;
|
203
293
|
cd->entry[i].bitflags &= ~ZIP_GPBF_ENCRYPTED;
|
204
294
|
} else if (!decrypt && !encrypted) {
|
205
|
-
|
295
|
+
de.comp_size += ZIPENC_HEAD_LEN;
|
296
|
+
de.bitflags |= ZIP_GPBF_ENCRYPTED;
|
297
|
+
cd->entry[i].comp_size += ZIPENC_HEAD_LEN;
|
298
|
+
cd->entry[i].bitflags |= ZIP_GPBF_ENCRYPTED;
|
206
299
|
}
|
207
300
|
|
208
301
|
if (_zip_dirent_write(&de, out, 1, &za->error) < 0) {
|
@@ -213,8 +306,7 @@ static int _zip_crypt(struct zip *za, const char *pwd, int pwdlen, int decrypt,
|
|
213
306
|
if (decrypt && encrypted) {
|
214
307
|
error = (copy_decrypt(za->zp, cd->entry[i].comp_size, pwd, pwdlen, &de, out, &za->error, wrongpwd) < 0);
|
215
308
|
} else if (!decrypt && !encrypted) {
|
216
|
-
|
217
|
-
error = (copy_data(za->zp, cd->entry[i].comp_size, out, &za->error) < 0);
|
309
|
+
error = (copy_encrypt(za->zp, (cd->entry[i].comp_size - ZIPENC_HEAD_LEN), pwd, pwdlen, &de, out, &za->error) < 0);
|
218
310
|
} else {
|
219
311
|
error = (copy_data(za->zp, cd->entry[i].comp_size, out, &za->error) < 0);
|
220
312
|
}
|
@@ -293,3 +385,21 @@ int zip_decrypt(const char *path, const char *pwd, int pwdlen, int *errorp, int
|
|
293
385
|
|
294
386
|
return res;
|
295
387
|
}
|
388
|
+
|
389
|
+
int zip_encrypt(const char *path, const char *pwd, int pwdlen, int *errorp) {
|
390
|
+
struct zip *za;
|
391
|
+
int res;
|
392
|
+
|
393
|
+
if (pwd == NULL || pwdlen < 1) {
|
394
|
+
return -1;
|
395
|
+
}
|
396
|
+
|
397
|
+
if ((za = zip_open(path, 0, errorp)) == NULL) {
|
398
|
+
return -1;
|
399
|
+
}
|
400
|
+
|
401
|
+
res = _zip_crypt(za, pwd, pwdlen, 0, NULL);
|
402
|
+
_zip_free(za);
|
403
|
+
|
404
|
+
return res;
|
405
|
+
}
|
data/ext/zipruby.h
CHANGED
data/ext/zipruby_archive.c
CHANGED
@@ -10,6 +10,7 @@ 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
12
|
static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password);
|
13
|
+
static VALUE zipruby_archive_s_encrypt(VALUE self, VALUE path, VALUE password);
|
13
14
|
static VALUE zipruby_archive_close(VALUE self);
|
14
15
|
static VALUE zipruby_archive_num_files(VALUE self);
|
15
16
|
static VALUE zipruby_archive_get_name(int argc, VALUE *argv, VALUE self);
|
@@ -50,6 +51,7 @@ void Init_zipruby_archive() {
|
|
50
51
|
rb_include_module(Archive, rb_mEnumerable);
|
51
52
|
rb_define_singleton_method(Archive, "open", zipruby_archive_s_open, -1);
|
52
53
|
rb_define_singleton_method(Archive, "decrypt", zipruby_archive_s_decrypt, 2);
|
54
|
+
rb_define_singleton_method(Archive, "encrypt", zipruby_archive_s_encrypt, 2);
|
53
55
|
rb_define_method(Archive, "close", zipruby_archive_close, 0);
|
54
56
|
rb_define_method(Archive, "num_files", zipruby_archive_num_files, 0);
|
55
57
|
rb_define_method(Archive, "get_name", zipruby_archive_get_name, -1);
|
@@ -138,11 +140,19 @@ static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self) {
|
|
138
140
|
/* */
|
139
141
|
static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password) {
|
140
142
|
int errorp, wrongpwd;
|
143
|
+
long pwdlen;
|
141
144
|
|
142
145
|
Check_Type(path, T_STRING);
|
143
146
|
Check_Type(password, T_STRING);
|
147
|
+
pwdlen = RSTRING(password)->len;
|
144
148
|
|
145
|
-
if (
|
149
|
+
if (pwdlen < 1) {
|
150
|
+
rb_raise(Error, "Decrypt archive failed - %s: Password is empty", StringValuePtr(path));
|
151
|
+
} else if (pwdlen > 0xff) {
|
152
|
+
rb_raise(Error, "Decrypt archive failed - %s: Password is too long", StringValuePtr(path));
|
153
|
+
}
|
154
|
+
|
155
|
+
if (zip_decrypt(StringValuePtr(path), StringValuePtr(password), pwdlen, &errorp, &wrongpwd) == -1) {
|
146
156
|
if (wrongpwd) {
|
147
157
|
rb_raise(Error, "Decrypt archive failed - %s: Wrong password", StringValuePtr(path));
|
148
158
|
} else {
|
@@ -155,6 +165,30 @@ static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password) {
|
|
155
165
|
return Qnil;
|
156
166
|
}
|
157
167
|
|
168
|
+
/* */
|
169
|
+
static VALUE zipruby_archive_s_encrypt(VALUE self, VALUE path, VALUE password) {
|
170
|
+
int errorp;
|
171
|
+
long pwdlen;
|
172
|
+
|
173
|
+
Check_Type(path, T_STRING);
|
174
|
+
Check_Type(password, T_STRING);
|
175
|
+
pwdlen = RSTRING(password)->len;
|
176
|
+
|
177
|
+
if (pwdlen < 1) {
|
178
|
+
rb_raise(Error, "Encrypt archive failed - %s: Password is empty", StringValuePtr(path));
|
179
|
+
} else if (pwdlen > 0xff) {
|
180
|
+
rb_raise(Error, "Encrypt archive failed - %s: Password is too long", StringValuePtr(path));
|
181
|
+
}
|
182
|
+
|
183
|
+
if (zip_encrypt(StringValuePtr(path), StringValuePtr(password), pwdlen, &errorp) == -1) {
|
184
|
+
char errstr[ERRSTR_BUFSIZE];
|
185
|
+
zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
|
186
|
+
rb_raise(Error, "Encrypt archive failed - %s: %s", StringValuePtr(path), errstr);
|
187
|
+
}
|
188
|
+
|
189
|
+
return Qnil;
|
190
|
+
}
|
191
|
+
|
158
192
|
/* */
|
159
193
|
static VALUE zipruby_archive_close(VALUE self) {
|
160
194
|
struct zipruby_archive *p_archive;
|
data/ext/zipruby_file.c
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
#endif
|
8
8
|
|
9
9
|
#include "zip.h"
|
10
|
+
#include "zipint.h"
|
10
11
|
#include "zipruby.h"
|
11
12
|
#include "zipruby_archive.h"
|
12
13
|
#include "zipruby_file.h"
|
@@ -178,6 +179,10 @@ static VALUE zipruby_file_read(int argc, VALUE *argv, VALUE self) {
|
|
178
179
|
Check_File(p_file);
|
179
180
|
zip_stat_init(&sb);
|
180
181
|
|
182
|
+
if (p_file->archive->cdir->entry[0].bitflags & ZIP_GPBF_ENCRYPTED) {
|
183
|
+
rb_raise(Error, "Read file failed: File encrypted");
|
184
|
+
}
|
185
|
+
|
181
186
|
if (zip_stat_index(p_file->archive, p_file->sb->index, 0, &sb)) {
|
182
187
|
rb_raise(Error, "Read file failed: %s", zip_strerror(p_file->archive));
|
183
188
|
}
|
data/zipruby.c
CHANGED
@@ -29,6 +29,7 @@ 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
31
|
static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password);
|
32
|
+
static VALUE zipruby_archive_s_encrypt(VALUE self, VALUE path, VALUE password);
|
32
33
|
static VALUE zipruby_archive_close(VALUE self);
|
33
34
|
static VALUE zipruby_archive_num_files(VALUE self);
|
34
35
|
static VALUE zipruby_archive_get_name(int argc, VALUE *argv, VALUE self);
|
@@ -69,6 +70,7 @@ void Init_zipruby_archive() {
|
|
69
70
|
rb_include_module(Archive, rb_mEnumerable);
|
70
71
|
rb_define_singleton_method(Archive, "open", zipruby_archive_s_open, -1);
|
71
72
|
rb_define_singleton_method(Archive, "decrypt", zipruby_archive_s_decrypt, 2);
|
73
|
+
rb_define_singleton_method(Archive, "encrypt", zipruby_archive_s_encrypt, 2);
|
72
74
|
rb_define_method(Archive, "close", zipruby_archive_close, 0);
|
73
75
|
rb_define_method(Archive, "num_files", zipruby_archive_num_files, 0);
|
74
76
|
rb_define_method(Archive, "get_name", zipruby_archive_get_name, -1);
|
@@ -157,11 +159,19 @@ static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self) {
|
|
157
159
|
/* */
|
158
160
|
static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password) {
|
159
161
|
int errorp, wrongpwd;
|
162
|
+
long pwdlen;
|
160
163
|
|
161
164
|
Check_Type(path, T_STRING);
|
162
165
|
Check_Type(password, T_STRING);
|
166
|
+
pwdlen = RSTRING(password)->len;
|
163
167
|
|
164
|
-
if (
|
168
|
+
if (pwdlen < 1) {
|
169
|
+
rb_raise(Error, "Decrypt archive failed - %s: Password is empty", StringValuePtr(path));
|
170
|
+
} else if (pwdlen > 0xff) {
|
171
|
+
rb_raise(Error, "Decrypt archive failed - %s: Password is too long", StringValuePtr(path));
|
172
|
+
}
|
173
|
+
|
174
|
+
if (zip_decrypt(StringValuePtr(path), StringValuePtr(password), pwdlen, &errorp, &wrongpwd) == -1) {
|
165
175
|
if (wrongpwd) {
|
166
176
|
rb_raise(Error, "Decrypt archive failed - %s: Wrong password", StringValuePtr(path));
|
167
177
|
} else {
|
@@ -174,6 +184,30 @@ static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password) {
|
|
174
184
|
return Qnil;
|
175
185
|
}
|
176
186
|
|
187
|
+
/* */
|
188
|
+
static VALUE zipruby_archive_s_encrypt(VALUE self, VALUE path, VALUE password) {
|
189
|
+
int errorp;
|
190
|
+
long pwdlen;
|
191
|
+
|
192
|
+
Check_Type(path, T_STRING);
|
193
|
+
Check_Type(password, T_STRING);
|
194
|
+
pwdlen = RSTRING(password)->len;
|
195
|
+
|
196
|
+
if (pwdlen < 1) {
|
197
|
+
rb_raise(Error, "Encrypt archive failed - %s: Password is empty", StringValuePtr(path));
|
198
|
+
} else if (pwdlen > 0xff) {
|
199
|
+
rb_raise(Error, "Encrypt archive failed - %s: Password is too long", StringValuePtr(path));
|
200
|
+
}
|
201
|
+
|
202
|
+
if (zip_encrypt(StringValuePtr(path), StringValuePtr(password), pwdlen, &errorp) == -1) {
|
203
|
+
char errstr[ERRSTR_BUFSIZE];
|
204
|
+
zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
|
205
|
+
rb_raise(Error, "Encrypt archive failed - %s: %s", StringValuePtr(path), errstr);
|
206
|
+
}
|
207
|
+
|
208
|
+
return Qnil;
|
209
|
+
}
|
210
|
+
|
177
211
|
/* */
|
178
212
|
static VALUE zipruby_archive_close(VALUE self) {
|
179
213
|
struct zipruby_archive *p_archive;
|
@@ -845,6 +879,7 @@ void Init_zipruby_error() {
|
|
845
879
|
#endif
|
846
880
|
|
847
881
|
#include "zip.h"
|
882
|
+
#include "zipint.h"
|
848
883
|
#include "zipruby.h"
|
849
884
|
#include "zipruby_archive.h"
|
850
885
|
#include "zipruby_file.h"
|
@@ -1016,6 +1051,10 @@ static VALUE zipruby_file_read(int argc, VALUE *argv, VALUE self) {
|
|
1016
1051
|
Check_File(p_file);
|
1017
1052
|
zip_stat_init(&sb);
|
1018
1053
|
|
1054
|
+
if (p_file->archive->cdir->entry[0].bitflags & ZIP_GPBF_ENCRYPTED) {
|
1055
|
+
rb_raise(Error, "Read file failed: File encrypted");
|
1056
|
+
}
|
1057
|
+
|
1019
1058
|
if (zip_stat_index(p_file->archive, p_file->sb->index, 0, &sb)) {
|
1020
1059
|
rb_raise(Error, "Read file failed: %s", zip_strerror(p_file->archive));
|
1021
1060
|
}
|