/* 

esp_bindb.c

Author: Liraz Siri <liraz@bigfoot.com>

Copyright (c) 1998 Liraz Siri <liraz@bigfoot.com>, Ariel, Israel,
		   All rights reserved.

Created: Thu Oct  1 23:02:39 GMT 1998

Binary database ssh extension.

- compression snipped from ssh/compress.c

*/

#include "zlib.h"
#include "getput.h"

static char *binary_db_filename;

static z_stream input_stream; 
static z_stream output_stream;

void pbdb_init(char *binary_db)
{
 binary_db_filename = binary_db;
 inflateInit(&input_stream);
 deflateInit(&output_stream, PBDB_COMPRESSION_LEVEL);
}

void pbdb_uninit(void)
{
 inflateEnd(&input_stream);
 deflateEnd(&output_stream);
}

void pbdb_compress(Buffer *input, Buffer *output)
{
 char buf[4096];

 if(buffer_len(input) == 0)
  return;

 output_stream.next_in = buffer_ptr(input);
 output_stream.avail_in = buffer_len(input);

 do {
  output_stream.next_out = (unsigned char *)buf;
  output_stream.avail_out = sizeof(buf);

  switch(deflate(&output_stream, Z_PARTIAL_FLUSH)) {
        case Z_OK:
          /* Append compressed data to output_buffer. */
          buffer_append(output, buf,
                        sizeof(buf) - output_stream.avail_out);
          break;
        case Z_STREAM_END:
          fatal("buffer_compress: deflate returned Z_STREAM_END");
          /*NOTREACHED*/
        case Z_STREAM_ERROR:
          fatal("buffer_compress: deflate returned Z_STREAM_ERROR");
          /*NOTREACHED*/
        case Z_BUF_ERROR:
          fatal("buffer_compress: deflate returned Z_BUF_ERROR");
          /*NOTREACHED*/
        default:
          fatal("buffer_compress: deflate returned %d", status);
          /*NOTREACHED*/
  }
 } while(output_stream.avail_out == 0);

}

void pbdb_decompress(Buffer *input, Buffer *output)
{
 char buf[4096];

 input_stream.next_in = buffer_ptr(input);
 input_stream.avail_in = buffer_len(input);

 input_stream.next_out = (unsigned char *)buf;
 input_stream.avail_out = sizeof(buf);

 for(;;) 
 {
  switch(inflate(&input_stream, Z_PARTIAL_FLUSH)) {
   case Z_OK	: 
    buffer_append(output, buf, sizeof(buf) - input_stream.avail_out);
    input_stream.next_out = (unsigned char *)buf;
    input_stream.avail_out = sizeof(buf);
    break;

   case Z_STREAM_END:
    fatal("buffer_uncompress: inflate returned Z_STREAM_END");
    /*NOTREACHED*/
   case Z_DATA_ERROR:
    fatal("buffer_uncompress: inflate returned Z_DATA_ERROR");
    /*NOTREACHED*/
   case Z_STREAM_ERROR:
    fatal("buffer_uncompress: inflate returned Z_STREAM_ERROR");
    /*NOTREACHED*/
   case Z_MEM_ERROR:
    fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");
    /*NOTREACHED*/
   case Z_BUF_ERROR:
    /* Comments in zlib.h say that we should keep calling inflate()
       until we get an error.  This appears to be the error that we
       get. */
    return;
   default:
    fatal("buffer_uncompress: inflate returned %d", status);
  }
 } 
	 
}

int pbdb_get_dbrec(char *label, Buffer *output)
{
 int len;
 char buf[4];
 FILE *dbfp;

 buffer_clear(output);
 if(!(dbfp = pbdb_open())) return -1;

 for(;;) {
  fread(buf, 2, 1, dbfp);
  len = GET_16BIT(buf);
  if(len < 1 || len > 128) {
   error("Read invalid db label length.");
   return -1;
  }

 }
 
 
}

FILE *pbdb_open(void)
{
 FILE *fp;
 int padding, pre_padding;
 struct stat stat_struct;

 if(stat(binary_filename_db, &stat_struct) < 0 ||
    !(fp = fopen(binary_filename_db, "rw")) )
  return NULL;

 for(pre_padding = padding = 0;;pre_padding++) 
 {
  switch(fgetc(fp)) {
   case		0 	:
    if(++padding == PBDB_NULL_PADDING) 
     goto beyond_padding;
    break;

   case		EOF	:
    goto fail;

   default		:
    if(padding) padding = 0;
  }

 }

fail:

 close(fp);
 return NULL;

beyond_padding:
 if(stat_struct.st_size - pre_padding < 9) return NULL;
 
 return fp;
}
