示例#1
0
static zip_int64_t
buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length)
{
    zip_uint64_t n, i, fragment_offset;

    length = ZIP_MIN(length, buffer->size - buffer->offset);

    if (length == 0) {
	return 0;
    }
    if (length > ZIP_INT64_MAX) {
	return -1;
    }

    i = buffer->offset / buffer->fragment_size;
    fragment_offset = buffer->offset % buffer->fragment_size;
    n = 0;
    while (n < length) {
	zip_uint64_t left = ZIP_MIN(length - n, buffer->fragment_size - fragment_offset);
	
	memcpy(data + n, buffer->fragments[i] + fragment_offset, left);

	n += left;
	i++;
	fragment_offset = 0;
    }

    buffer->offset += n;
    return (zip_int64_t)n;
}
示例#2
0
static zip_compression_status_t
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
    struct ctx *ctx = (struct ctx *)ud;

    int ret;

    if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) {
	*length = 0;
	return ZIP_COMPRESSION_NEED_DATA;
    }

    ctx->zstr.avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length);
    ctx->zstr.next_out = (char *)data;

    if (ctx->compress) {
	ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN);
    }
    else {
	ret = BZ2_bzDecompress(&ctx->zstr);
    }

    *length = *length - ctx->zstr.avail_out;

    switch (ret) {
    case BZ_FINISH_OK: /* compression */
	return ZIP_COMPRESSION_OK;

    case BZ_OK:	/* decompression */
    case BZ_RUN_OK: /* compression */
	if (ctx->zstr.avail_in == 0) {
	    return ZIP_COMPRESSION_NEED_DATA;
	}
	return ZIP_COMPRESSION_OK;

    case BZ_STREAM_END:
	return ZIP_COMPRESSION_END;

    default:
	zip_error_set(ctx->error, map_error(ret), 0);
	return ZIP_COMPRESSION_ERROR;
    }
}
示例#3
0
static zip_int64_t
buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error)
{
    zip_uint64_t n, i, fragment_offset;
    zip_uint8_t **fragments;

    if (buffer->offset + length + buffer->fragment_size - 1 < length) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return -1;
    }

    /* grow buffer if needed */
    if (buffer->offset + length > buffer->nfragments * buffer->fragment_size) {
	zip_uint64_t needed_fragments = (buffer->offset + length + buffer->fragment_size - 1) / buffer->fragment_size;
	
	if (needed_fragments > buffer->fragments_capacity) {
	    zip_uint64_t new_capacity = buffer->fragments_capacity;

	    while (new_capacity < needed_fragments) {
		new_capacity *= 2;
	    }

	    fragments = realloc(buffer->fragments, new_capacity * sizeof(*fragments));

	    if (fragments == NULL) {
		zip_error_set(error, ZIP_ER_MEMORY, 0);
		return -1;
	    }

	    buffer->fragments = fragments;
	    buffer->fragments_capacity = new_capacity;
	}

	while (buffer->nfragments < needed_fragments) {
	    if ((buffer->fragments[buffer->nfragments] = malloc(buffer->fragment_size)) == NULL) {
		zip_error_set(error, ZIP_ER_MEMORY, 0);
		return -1;
	    }
	    buffer->nfragments++;
	}
    }

    i = buffer->offset / buffer->fragment_size;
    fragment_offset = buffer->offset % buffer->fragment_size;
    n = 0;
    while (n < length) {
	zip_uint64_t left = ZIP_MIN(length - n, buffer->fragment_size - fragment_offset);
		
	memcpy(buffer->fragments[i] + fragment_offset, data + n, left);

	n += left;
	i++;
	fragment_offset = 0;
    }

    buffer->offset += n;
    if (buffer->offset > buffer->size) {
	buffer->size = buffer->offset;
    }

    return (zip_int64_t)n;
}
示例#4
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;
}
示例#5
0
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;
}
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;
    }
}
示例#7
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;
    }
}
示例#8
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;
    }
}