Exemple #1
0
static int
copy_source(struct zip *za, struct zip_source *src, FILE *ft)
{
    char buf[BUFSIZE];
    zip_int64_t n;
    int ret;

    if (zip_source_open(src) < 0) {
	_zip_error_set_from_source(&za->error, src);
	return -1;
    }

    ret = 0;
    while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
	if (fwrite(buf, 1, (size_t)n, ft) != (size_t)n) {
	    _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
	    ret = -1;
	    break;
	}
    }
    
    if (n < 0) {
	if (ret == 0)
	    _zip_error_set_from_source(&za->error, src);
	ret = -1;
    }	

    zip_source_close(src);
    
    return ret;
}
Exemple #2
0
static int
copy_source(zip_t *za, zip_source_t *src)
{
    zip_uint8_t buf[BUFSIZE];
    zip_int64_t n;
    int ret;

    if (zip_source_open(src) < 0) {
	_zip_error_set_from_source(&za->error, src);
	return -1;
    }

    ret = 0;
    while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
	if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
	    ret = -1;
	    break;
	}
    }
    
    if (n < 0) {
	_zip_error_set_from_source(&za->error, src);
	ret = -1;
    }

    zip_source_close(src);
    
    return ret;
}
Exemple #3
0
zip_fread(struct zip_file *zf, void *outbuf, zip_uint64_t toread)
{
    zip_int64_t n;

    if (!zf)
	return -1;

    if (zf->error.zip_err != 0)
	return -1;

    if (toread > ZIP_INT64_MAX) {
	_zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
	return -1;
    }

    if ((zf->eof) || (toread == 0))
	return 0;

    if ((n=zip_source_read(zf->src, outbuf, toread)) < 0) {
	_zip_error_set_from_source(&zf->error, zf->src);
	return -1;
    }

    return n;
}
static int
decrypt_header(zip_source_t *src, struct winzip_aes *ctx)
{
    zip_uint8_t header[MAX_HEADER_LENGTH];
    zip_uint8_t password_verification[PWD_VER_LENGTH];
    zip_uint8_t headerlen;
    zip_int64_t n;

    headerlen = PWD_VER_LENGTH + salt_length[ctx->mode];
    if ((n=zip_source_read(src, header, headerlen)) < 0) {
	_zip_error_set_from_source(&ctx->error, src);
	return -1;
    }
    
    if (n != headerlen) {
	zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
	return -1;
    }

    if (_zip_fcrypt_init(ctx->mode, ctx->password, strlen(ctx->password), header, password_verification, &ctx->fcrypt_ctx) != 0) {
	zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
	return -1;
    }
    if (memcmp(password_verification, header + salt_length[ctx->mode], PWD_VER_LENGTH) != 0) {
	zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0);
	return -1;
    }
    return 0;
}
static bool
verify_hmac(zip_source_t *src, struct winzip_aes *ctx)
{
    unsigned char computed[HMAC_LENGTH], from_file[HMAC_LENGTH];
    if (zip_source_read(src, from_file, HMAC_LENGTH) < HMAC_LENGTH) {
	_zip_error_set_from_source(&ctx->error, src);
	return false;
    }

    _zip_fcrypt_end(computed, &ctx->fcrypt_ctx);
    
    if (memcmp(from_file, computed, HMAC_LENGTH) != 0) {
	zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
	return false;
    }

    return true;
}
Exemple #6
0
int main()
{
	zip_source_t *zsrc = loadFromFile();
	if (!zsrc) return 1;

	fprintf(stderr, "zip_open_from_source...\n");
	zip_error_t error;
	zip_error_init(&error);
	zip_t *archive = zip_open_from_source(zsrc, 0, &error);
	if (!archive) return 2;
	zip_error_fini(&error);

	show(archive, "after zip_open_from_source");

	const char *name = "y.txt";
	zip_flags_t flags = 0;
	zip_source_t *otherZsrc = zip_source_buffer_create("hello", 5, 0, &error);

	fprintf(stderr, "zip_file_add...\n");
	zip_int64_t i = zip_file_add(archive, name, otherZsrc, flags);
	fprintf(stderr, "zip_file_add(): i=%lld\n", i);
	//
	show(archive, "after zip_file_add");
	zip_source_keep(zsrc);
	int ret;
	ret = zip_close(archive);

	// print to stdout

	zip_stat_t zst;
	ret = zip_source_stat(zsrc, &zst);
	fprintf(stderr, "zip_source_stat: ret=%d, zst.size=%d\n", ret, zst.size);

	ret = zip_source_open(zsrc);
	fprintf(stderr, "zip_source_open: ret=%d\n", ret);
	unsigned char data[10000];
	zip_uint64_t n = zip_source_read(zsrc, data, sizeof(data));
	fprintf(stderr, "zip_source_read: n=%d\n", n);
	write(1, data, n); // print to stdout

	
}
Exemple #7
0
int
_zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error)
{
    zip_int64_t n;

    if (length > ZIP_INT64_MAX) {
	zip_error_set(error, ZIP_ER_INTERNAL, 0);
	return -1;
    }

    if ((n = zip_source_read(src, b, length)) < 0) {
	_zip_error_set_from_source(error, src);
	return -1;
    }

    if (n < (zip_int64_t)length) {
	zip_error_set(error, ZIP_ER_EOF, 0);
	return -1;
    }

    return 0;
}
int
_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error)
{
    Bytef buf[BUFSIZE];
    zip_int64_t n;

    *crcp = crc32(0L, Z_NULL, 0);

    if (start > ZIP_INT64_MAX) {
	zip_error_set(error, ZIP_ER_SEEK, EFBIG);
	return -1;
    }

    if (zip_source_seek(src, (zip_int64_t)start, SEEK_SET) != 0) {
	_zip_error_set_from_source(error, src);
	return -1;
    }
    
    while (len > 0) {
	n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len);
	if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) {
	    _zip_error_set_from_source(error, src);
	    return -1;
	}
	if (n == 0) {
	    zip_error_set(error, ZIP_ER_EOF, 0);
	    return -1;
	}

	*crcp = crc32(*crcp, buf, (uInt)n);

	len -= (zip_uint64_t)n;
    }

    return 0;
}
static zip_int64_t
compress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
{
    int end, ret;
    zip_int64_t n;
    zip_uint64_t out_offset;
    uInt out_len;

    if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
	return -1;
    
    if (len == 0 || ctx->is_stored) {
	return 0;
    }
	
    out_offset = 0;
    out_len = (uInt)ZIP_MIN(UINT_MAX, len);
    ctx->zstr.next_out = (Bytef *)data;
    ctx->zstr.avail_out = out_len;

    end = 0;
    while (!end) {
	ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);

	switch (ret) {
        case Z_STREAM_END:
            if (ctx->can_store && ctx->zstr.total_in <= ctx->zstr.total_out) {
                ctx->is_stored = true;
                ctx->size = ctx->zstr.total_in;
                memcpy(data, ctx->buffer, ctx->size);
                return (zip_int64_t)ctx->size;
            }
            /* fallthrough */
	case Z_OK:
	    /* all ok */

	    if (ctx->zstr.avail_out == 0) {
		out_offset += out_len;
		if (out_offset < len) {
		    out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
		    ctx->zstr.next_out = (Bytef *)data+out_offset;
		    ctx->zstr.avail_out = out_len;
		}
		else {
                    ctx->can_store = false;
		    end = 1;
		}
	    }
	    else if (ctx->eof && ctx->zstr.avail_in == 0)
		end = 1;
	    break;

	case Z_BUF_ERROR:
	    if (ctx->zstr.avail_in == 0) {
		if (ctx->eof) {
		    end = 1;
		    break;
		}

		if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
                    _zip_error_set_from_source(&ctx->error, src);
		    end = 1;
		    break;
		}
		else if (n == 0) {
		    ctx->eof = true;
		    /* TODO: check against stat of src? */
		    ctx->size = ctx->zstr.total_in;
		}
		else {
                    if (ctx->zstr.total_in > 0) {
                        /* we overwrote a previously filled ctx->buffer */
                        ctx->can_store = false;
                    }
		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
		    ctx->zstr.avail_in = (uInt)n;
		}
		continue;
	    }
	    /* fallthrough */
	case Z_NEED_DICT:
	case Z_DATA_ERROR:
	case Z_STREAM_ERROR:
	case Z_MEM_ERROR:
            zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);

	    end = 1;
	    break;
	}
    }

    if (ctx->zstr.avail_out < len) {
	ctx->can_store = false;
	return (zip_int64_t)(len - ctx->zstr.avail_out);
    }

    return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
}
static zip_int64_t
deflate_decompress(zip_source_t *src, void *ud, void *data,
		   zip_uint64_t len, zip_source_cmd_t cmd)
{
    struct deflate *ctx;
    zip_int64_t n;
    int ret;

    ctx = (struct deflate *)ud;

    switch (cmd) {
        case ZIP_SOURCE_OPEN:
            if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }

            ctx->zstr.zalloc = Z_NULL;
            ctx->zstr.zfree = Z_NULL;
            ctx->zstr.opaque = NULL;
            ctx->zstr.next_in = (Bytef *)ctx->buffer;
            ctx->zstr.avail_in = (uInt)n;

            /* negative value to tell zlib that there is no header */
            if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
                zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
                return -1;
            }
            return 0;

        case ZIP_SOURCE_READ:
            return decompress_read(src, ctx, data, len);

        case ZIP_SOURCE_CLOSE:
            inflateEnd(&ctx->zstr);
            return 0;

        case ZIP_SOURCE_STAT:
        {
            zip_stat_t *st;
            
            st = (zip_stat_t *)data;
            
            st->comp_method = ZIP_CM_STORE;
            if (st->comp_size > 0 && st->size > 0)
                st->comp_size = st->size;
            
            return 0;
        }

        case ZIP_SOURCE_ERROR:
            return zip_error_to_data(&ctx->error, data, len);

        case ZIP_SOURCE_FREE:
            free(ctx);
            return 0;
            
        case ZIP_SOURCE_SUPPORTS:
            return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);

        default:
            zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
            return -1;
    }
}
static zip_int64_t
decompress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
{
    int end, ret;
    zip_int64_t n;
    zip_uint64_t out_offset;
    uInt out_len;

    if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
	return -1;
    
    if (len == 0)
	return 0;

    out_offset = 0;
    out_len = (uInt)ZIP_MIN(UINT_MAX, len);
    ctx->zstr.next_out = (Bytef *)data;
    ctx->zstr.avail_out = out_len;

    end = 0;
    while (!end) {
	ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);

	switch (ret) {
	case Z_OK:
	    if (ctx->zstr.avail_out == 0) {
		out_offset += out_len;
		if (out_offset < len) {
		    out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
		    ctx->zstr.next_out = (Bytef *)data+out_offset;
		    ctx->zstr.avail_out = out_len;
		}
		else {
		    end = 1;
		}
	    }
	    break;
	    
	case Z_STREAM_END:
	    ctx->eof = 1;
	    end = 1;
	    break;

	case Z_BUF_ERROR:
	    if (ctx->zstr.avail_in == 0) {
		if (ctx->eof) {
		    end = 1;
		    break;
		}

		if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
                    _zip_error_set_from_source(&ctx->error, src);
		    end = 1;
		    break;
		}
		else if (n == 0) {
		    ctx->eof = 1;
		}
		else {
		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
		    ctx->zstr.avail_in = (uInt)n;
		}
		continue;
	    }
	    /* fallthrough */
	case Z_NEED_DICT:
	case Z_DATA_ERROR:
	case Z_STREAM_ERROR:
	case Z_MEM_ERROR:
            zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
	    end = 1;
	    break;
	}
    }

    if (ctx->zstr.avail_out < len)
	return (zip_int64_t)(len - ctx->zstr.avail_out);

    return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
}
Exemple #12
0
static zip_int64_t
window_read(struct zip_source *src, void *_ctx, void *data,
	    zip_uint64_t len, enum zip_source_cmd cmd)
{
    struct window *ctx;
    zip_int64_t ret;
    zip_uint64_t n, i;
    char b[8192];

    ctx = (struct window *)_ctx;

    switch (cmd) {
    case ZIP_SOURCE_OPEN:
	for (n=0; n<ctx->skip; n+=(zip_uint64_t)ret) {
	    i = (ctx->skip-n > sizeof(b) ? sizeof(b) : ctx->skip-n);
	    if ((ret=zip_source_read(src, b, i)) < 0)
		return ZIP_SOURCE_ERR_LOWER;
	    if (ret==0) {
		ctx->e[0] = ZIP_ER_EOF;
		ctx->e[1] = 0;
		return -1;
	    }
	}
	return 0;

    case ZIP_SOURCE_READ:
	if (len > ctx->left)
	    len = ctx->left;
	
	if (len <= 0)
	    return 0;

	if ((ret=zip_source_read(src, data, len)) < 0)
	    return ZIP_SOURCE_ERR_LOWER;

	ctx->left -= (zip_uint64_t)ret;

        if (ret == 0) {
	    if (ctx->left > 0) {
		ctx->e[0] = ZIP_ER_EOF;
		ctx->e[1] = 0;
		return -1;
	    }
	}
	return ret;

    case ZIP_SOURCE_CLOSE:
	return 0;

    case ZIP_SOURCE_STAT:
	{
	    struct zip_stat *st;

	    st = (struct zip_stat *)data;

	    st->size = ctx->len;
	    st->valid |= ZIP_STAT_SIZE;
	    st->valid &= ~(ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE);
	}
	return 0;
	
    case ZIP_SOURCE_ERROR:
	memcpy(data, ctx->e, sizeof(ctx->e));
	return 0;

    case ZIP_SOURCE_FREE:
	free(ctx);
	return 0;

    default:
	return -1;
    }
    
}
Exemple #13
0
static zip_int64_t
compress_read(struct zip_source *src, struct deflate *ctx,
	      void *data, zip_uint64_t len)
{
    int end, ret;
    zip_int64_t n;

    if (ctx->e[0] != 0)
	return -1;
    
    if (len == 0)
	return 0;
	
    ctx->zstr.next_out = (Bytef *)data;
    ctx->zstr.avail_out = (uInt)len; /* TODO: check for overflow */

    end = 0;
    while (!end) {
	ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);

	switch (ret) {
	case Z_OK:
	case Z_STREAM_END:
	    /* all ok */

	    if (ctx->zstr.avail_out == 0
		|| (ctx->eof && ctx->zstr.avail_in == 0))
		end = 1;
	    break;

	case Z_BUF_ERROR:
	    if (ctx->zstr.avail_in == 0) {
		if (ctx->eof) {
		    end = 1;
		    break;
		}

		if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
		    zip_source_error(src, ctx->e, ctx->e+1);
		    end = 1;
		    break;
		}
		else if (n == 0) {
		    ctx->eof = 1;
		    ctx->size = ctx->zstr.total_in;
		    /* TODO: check against stat of src? */
		}
		else {
		    ctx->zstr.next_in = (Bytef *)ctx->buffer;
		    ctx->zstr.avail_in = (uInt)n;
		}
		continue;
	    }
	    /* fallthrough */
	case Z_NEED_DICT:
	case Z_DATA_ERROR:
	case Z_STREAM_ERROR:
	case Z_MEM_ERROR:
	    ctx->e[0] = ZIP_ER_ZLIB;
	    ctx->e[1] = ret;

	    end = 1;
	    break;
	}
    }

    if (ctx->zstr.avail_out < len)
	return (zip_int64_t)(len - ctx->zstr.avail_out);

    return (ctx->e[0] == 0) ? 0 : -1;
}
Exemple #14
0
static zip_int64_t
deflate_decompress(struct zip_source *src, void *ud, void *data,
		   zip_uint64_t len, enum zip_source_cmd cmd)
{
    struct deflate *ctx;
    zip_int64_t n;
    int ret;

    ctx = (struct deflate *)ud;

    switch (cmd) {
    case ZIP_SOURCE_OPEN:
	if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0)
	    return ZIP_SOURCE_ERR_LOWER;

	ctx->zstr.zalloc = Z_NULL;
	ctx->zstr.zfree = Z_NULL;
	ctx->zstr.opaque = NULL;
	ctx->zstr.next_in = (Bytef *)ctx->buffer;
	ctx->zstr.avail_in = (uInt)n /* TODO: check for overflow */;

	/* negative value to tell zlib that there is no header */
	if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
	    ctx->e[0] = ZIP_ER_ZLIB;
	    ctx->e[1] = ret;

	    return -1;
	}
	return 0;

    case ZIP_SOURCE_READ:
	return decompress_read(src, ctx, data, len);

    case ZIP_SOURCE_CLOSE:
	inflateEnd(&ctx->zstr);
	return 0;

    case ZIP_SOURCE_STAT:
	{
	    struct zip_stat *st;

	    st = (struct zip_stat *)data;

	    st->comp_method = ZIP_CM_STORE;
	    if (st->comp_size > 0 && st->size > 0)
		st->comp_size = st->size;
	}
	return 0;

    case ZIP_SOURCE_ERROR:
	if (len < sizeof(int)*2)
	    return -1;

	memcpy(data, ctx->e, sizeof(int)*2);
	return sizeof(int)*2;

    case ZIP_SOURCE_FREE:
	/* TODO: inflateEnd if close was not called */
	free(ctx);
	return 0;

    default:
	ctx->e[0] = ZIP_ER_INVAL;
	ctx->e[1] = 0;
	return -1;
    }
    
}
Exemple #15
0
static zip_int64_t
crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
{
    struct crc_context *ctx;
    zip_int64_t n;

    ctx = (struct crc_context *)_ctx;

    switch (cmd) {
        case ZIP_SOURCE_OPEN:
            ctx->position = 0;
            return 0;

        case ZIP_SOURCE_READ:
            if ((n = zip_source_read(src, data, len)) < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }

            if (n == 0) {
                if (ctx->crc_position == ctx->position) {
                    ctx->crc_complete = 1;
                    ctx->size = ctx->position;

                    if (ctx->validate) {
                        struct zip_stat st;

                        if (zip_source_stat(src, &st) < 0) {
                            _zip_error_set_from_source(&ctx->error, src);
                            return -1;
                        }

                        if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
                            zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
                            return -1;
                        }
                        if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
                            zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
                            return -1;
                        }
                    }
                }
            }
            else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
		zip_uint64_t i, nn;

		for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
		    nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);

		    ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
                    ctx->crc_position += nn;
		}
            }
            ctx->position += (zip_uint64_t)n;
            return n;

        case ZIP_SOURCE_CLOSE:
            return 0;

        case ZIP_SOURCE_STAT:
        {
            zip_stat_t *st;

	    st = (zip_stat_t *)data;

	    if (ctx->crc_complete) {
		/* TODO: Set comp_size, comp_method, encryption_method?
		        After all, this only works for uncompressed data. */
		st->size = ctx->size;
		st->crc = ctx->crc;
		st->comp_size = ctx->size;
		st->comp_method = ZIP_CM_STORE;
		st->encryption_method = ZIP_EM_NONE;
		st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;;
	    }
            return 0;
        }

        case ZIP_SOURCE_ERROR:
            return zip_error_to_data(&ctx->error, data, len);

        case ZIP_SOURCE_FREE:
            free(ctx);
            return 0;

        case ZIP_SOURCE_SUPPORTS:
        {
            zip_int64_t mask = zip_source_supports(src);

            if (mask < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }

            return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
        }

        case ZIP_SOURCE_SEEK:
        {
            zip_int64_t new_position;
            zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);

	    if (args == NULL) {
		return -1;
	    }
            if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }

            ctx->position = (zip_uint64_t)new_position;

            return 0;
        }

        case ZIP_SOURCE_TELL:
            return (zip_int64_t)ctx->position;

        default:
            zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
            return -1;
    }
}
static zip_int64_t
winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
{
    struct winzip_aes *ctx;
    zip_int64_t n;
    zip_uint64_t total, offset;

    ctx = (struct winzip_aes *)ud;

    switch (cmd) {
    case ZIP_SOURCE_OPEN:
	if (decrypt_header(src, ctx) < 0) {
	    return -1;
	}
	ctx->current_position = 0;
	return 0;

    case ZIP_SOURCE_READ:
	if (len > ctx->data_length - ctx->current_position) {
	    len = ctx->data_length - ctx->current_position;
	}

	if (len == 0) {
	    if (!verify_hmac(src, ctx)) {
		return -1;
	    }
	    return 0;
	}
	
	if ((n=zip_source_read(src, data, len)) < 0) {
	    _zip_error_set_from_source(&ctx->error, src);
	    return -1;
	}
	ctx->current_position += n;

	total = (zip_uint64_t)n;
	for (offset = 0; offset < total; offset += ZIP_MIN(total - offset, UINT_MAX)) {
	    _zip_fcrypt_decrypt(data + offset, ZIP_MIN(total - offset, UINT_MAX), &ctx->fcrypt_ctx);
	}

	return n;

    case ZIP_SOURCE_CLOSE:
	return 0;

    case ZIP_SOURCE_STAT:
    {
	zip_stat_t *st;

	st = (zip_stat_t *)data;

	st->encryption_method = ZIP_EM_NONE;
	st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
	if (st->valid & ZIP_STAT_COMP_SIZE) {
	    st->comp_size -= 12 + salt_length[ctx->mode];
	}
	
	return 0;
    }
            
    case ZIP_SOURCE_SUPPORTS:
	return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);

    case ZIP_SOURCE_ERROR:
	return zip_error_to_data(&ctx->error, data, len);

    case ZIP_SOURCE_FREE:
	winzip_aes_free(ctx);
	return 0;

    default:
	zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
	return -1;
    }
}
Exemple #17
0
static zip_int64_t
crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
{
    struct crc_context *ctx;
    zip_int64_t n;

    ctx = (struct crc_context *)_ctx;

    switch (cmd) {
        case ZIP_SOURCE_OPEN:
            ctx->eof = 0;
            ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
            ctx->size = 0;
            
            return 0;
            
        case ZIP_SOURCE_READ:
            if (ctx->eof || len == 0)
                return 0;
            
            if ((n=zip_source_read(src, data, len)) < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }
            
            if (n == 0) {
                ctx->eof = 1;
                if (ctx->validate) {
                    struct zip_stat st;
                    
                    if (zip_source_stat(src, &st) < 0) {
                        _zip_error_set_from_source(&ctx->error, src);
                        return -1;
                    }
                    
                    if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
                        zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
                        return -1;
                    }
                    if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
                        zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
                        return -1;
                    }
                }
            }
            else {
		zip_uint64_t i, nn;

		for (i=0; i < (zip_uint64_t)n; i += nn) {
		    nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);

		    ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
		}
                ctx->size += (zip_uint64_t)n;
            }
            return n;

        case ZIP_SOURCE_CLOSE:
            return 0;

        case ZIP_SOURCE_STAT:
        {
            zip_stat_t *st;

	    st = (zip_stat_t *)data;

	    if (ctx->eof) {
		/* TODO: Set comp_size, comp_method, encryption_method?
		        After all, this only works for uncompressed data. */
		st->size = ctx->size;
		st->crc = ctx->crc;
		st->comp_size = ctx->size;
		st->comp_method = ZIP_CM_STORE;
		st->encryption_method = ZIP_EM_NONE;
		st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;;
	    }
            return 0;
        }
            
        case ZIP_SOURCE_ERROR:
            return zip_error_to_data(&ctx->error, data, len);

        case ZIP_SOURCE_FREE:
            free(ctx);
            return 0;
            
        case ZIP_SOURCE_SUPPORTS:
            return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
            
        default:
            zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
            return -1;
    }
}