diff options
Diffstat (limited to 'libssh')
-rw-r--r-- | libssh/gzip.c | 250 |
1 files changed, 162 insertions, 88 deletions
diff --git a/libssh/gzip.c b/libssh/gzip.c index a5edb44..7394012 100644 --- a/libssh/gzip.c +++ b/libssh/gzip.c @@ -4,6 +4,7 @@ * This file is part of the SSH Library * * Copyright (c) 2003 by Aris Adamantiadis + * Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org> * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -34,110 +35,183 @@ #define BLOCKSIZE 4092 -static z_stream *initcompress(SSH_SESSION *session,int level){ - z_stream *stream=malloc(sizeof(z_stream)); - int status; - memset(stream,0,sizeof(z_stream)); - status=deflateInit(stream,level); - if (status!=0) - ssh_set_error(session,SSH_FATAL,"status %d inititalising zlib deflate",status); - return stream; +static z_stream *initcompress(SSH_SESSION *session, int level) { + z_stream *stream = NULL; + int status; + + stream = malloc(sizeof(z_stream)); + if (stream == NULL) { + return NULL; + } + memset(stream, 0, sizeof(z_stream)); + + status = deflateInit(stream, level); + if (status != Z_OK) { + SAFE_FREE(stream); + ssh_set_error(session, SSH_FATAL, + "status %d inititalising zlib deflate", status); + return NULL; + } + + return stream; } static BUFFER *gzip_compress(SSH_SESSION *session,BUFFER *source,int level){ - BUFFER *dest; - static unsigned char out_buf[BLOCKSIZE]; - void *in_ptr=buffer_get(source); - unsigned long in_size=buffer_get_len(source); - unsigned long len; - int status; - z_stream *zout=session->current_crypto->compress_out_ctx; - if(!zout) - zout=session->current_crypto->compress_out_ctx=initcompress(session,level); - dest=buffer_new(); - zout->next_out=out_buf; - zout->next_in=in_ptr; - zout->avail_in=in_size; - do { - zout->avail_out=BLOCKSIZE; - status=deflate(zout,Z_PARTIAL_FLUSH); - if(status !=0){ - ssh_set_error(session,SSH_FATAL,"status %d deflating zlib packet",status); - return NULL; - } - len=BLOCKSIZE-zout->avail_out; - buffer_add_data(dest,out_buf,len); - zout->next_out=out_buf; - } while (zout->avail_out == 0); - - return dest; + z_stream *zout = session->current_crypto->compress_out_ctx; + void *in_ptr = buffer_get(source); + unsigned long in_size = buffer_get_len(source); + BUFFER *dest = NULL; + static unsigned char out_buf[BLOCKSIZE] = {0}; + unsigned long len; + int status; + + if(zout == NULL) { + zout = session->current_crypto->compress_out_ctx = initcompress(session, level); + if (zout == NULL) { + return NULL; + } + } + + dest = buffer_new(); + if (dest == NULL) { + return NULL; + } + + zout->next_out = out_buf; + zout->next_in = in_ptr; + zout->avail_in = in_size; + do { + zout->avail_out = BLOCKSIZE; + status = deflate(zout, Z_PARTIAL_FLUSH); + if (status != Z_OK) { + buffer_free(dest); + ssh_set_error(session, SSH_FATAL, + "status %d deflating zlib packet", status); + return NULL; + } + len = BLOCKSIZE - zout->avail_out; + if (buffer_add_data(dest, out_buf, len) < 0) { + buffer_free(dest); + return NULL; + } + zout->next_out = out_buf; + } while (zout->avail_out == 0); + + return dest; } -int compress_buffer(SSH_SESSION *session,BUFFER *buf){ - BUFFER *dest=gzip_compress(session,buf,9); - if(!dest) - return -1; - buffer_reinit(buf); - buffer_add_data(buf,buffer_get(dest),buffer_get_len(dest)); +int compress_buffer(SSH_SESSION *session, BUFFER *buf) { + BUFFER *dest = NULL; + + dest = gzip_compress(session, buf, 9); + if (dest == NULL) { + return -1; + } + + if (buffer_reinit(buf) < 0) { + buffer_free(dest); + return -1; + } + + if (buffer_add_data(buf, buffer_get(dest), buffer_get_len(dest)) < 0) { buffer_free(dest); - return 0; + return -1; + } + + buffer_free(dest); + return 0; } /* decompression */ -static z_stream *initdecompress(SSH_SESSION *session){ - z_stream *stream=malloc(sizeof(z_stream)); - int status; - memset(stream,0,sizeof(z_stream)); - status=inflateInit(stream); - if (status!=0){ - ssh_set_error(session,SSH_FATAL,"Status = %d initiating inflate context !",status); - free(stream); - stream=NULL; - } - return stream; +static z_stream *initdecompress(SSH_SESSION *session) { + z_stream *stream = NULL; + int status; + + stream = malloc(sizeof(z_stream)); + if (stream == NULL) { + return NULL; + } + memset(stream,0,sizeof(z_stream)); + + status = inflateInit(stream); + if (status != Z_OK) { + SAFE_FREE(stream); + ssh_set_error(session, SSH_FATAL, + "Status = %d initiating inflate context!", status); + return NULL; + } + + return stream; } -static BUFFER *gzip_decompress(SSH_SESSION *session,BUFFER *source){ - BUFFER *dest; - static unsigned char out_buf[BLOCKSIZE]; - void *in_ptr=buffer_get_rest(source); - unsigned long in_size=buffer_get_rest_len(source); - unsigned long len; - int status; - z_stream *zin=session->current_crypto->compress_in_ctx; - if(!zin) - zin=session->current_crypto->compress_in_ctx=initdecompress(session); - dest=buffer_new(); - zin->next_out=out_buf; - zin->next_in=in_ptr; - zin->avail_in=in_size; - do { - zin->avail_out=BLOCKSIZE; - status=inflate(zin,Z_PARTIAL_FLUSH); - if(status !=Z_OK){ - ssh_set_error(session,SSH_FATAL,"status %d inflating zlib packet",status); - buffer_free(dest); - return NULL; - } - len=BLOCKSIZE-zin->avail_out; - buffer_add_data(dest,out_buf,len); - zin->next_out=out_buf; - } while (zin->avail_out == 0); - - return dest; +static BUFFER *gzip_decompress(SSH_SESSION *session, BUFFER *source) { + z_stream *zin = session->current_crypto->compress_in_ctx; + void *in_ptr = buffer_get_rest(source); + unsigned long in_size = buffer_get_rest_len(source); + static unsigned char out_buf[BLOCKSIZE] = {0}; + BUFFER *dest = NULL; + unsigned long len; + int status; + + if (zin == NULL) { + zin = session->current_crypto->compress_in_ctx = initdecompress(session); + if (zin == NULL) { + return NULL; + } + } + + dest = buffer_new(); + if (dest == NULL) { + return NULL; + } + + zin->next_out = out_buf; + zin->next_in = in_ptr; + zin->avail_in = in_size; + + do { + zin->avail_out = BLOCKSIZE; + status = inflate(zin, Z_PARTIAL_FLUSH); + if (status != Z_OK) { + ssh_set_error(session, SSH_FATAL, + "status %d inflating zlib packet", status); + buffer_free(dest); + return NULL; + } + + len = BLOCKSIZE - zin->avail_out; + if (buffer_add_data(dest,out_buf,len) < 0) { + buffer_free(dest); + return NULL; + } + + zin->next_out = out_buf; + } while (zin->avail_out == 0); + + return dest; } int decompress_buffer(SSH_SESSION *session,BUFFER *buf){ - BUFFER *dest=gzip_decompress(session,buf); - buffer_reinit(buf); - if(!dest){ - return -1; /* failed */ - } - buffer_reinit(buf); - buffer_add_data(buf,buffer_get(dest),buffer_get_len(dest)); + BUFFER *dest = NULL; + + dest = gzip_decompress(session,buf); + if (dest == NULL) { + return -1; + } + + if (buffer_reinit(buf) < 0) { + buffer_free(dest); + return -1; + } + + if (buffer_add_data(buf, buffer_get(dest), buffer_get_len(dest)) < 0) { buffer_free(dest); - return 0; + return -1; + } + + buffer_free(dest); + return 0; } #endif /* HAVE_LIBZ && WITH_LIBZ */ |