+
+/*
+ * decode a buffer from base 64 encoding; expects targetbuffer
+ * BufIn Buffor to transform
+ * BufOut Buffer to put result into
+ */
+int StrBufDecodeBase64To(const StrBuf *BufIn, StrBuf *BufOut) {
+ if ((BufIn == NULL) || (BufOut == NULL))
+ return -1;
+
+ if (BufOut->BufSize < BufIn->BufUsed) {
+ IncreaseBuf(BufOut, 0, BufIn->BufUsed);
+ }
+
+ BufOut->BufUsed = CtdlDecodeBase64(BufOut->buf, BufIn->buf, BufIn->BufUsed);
+ return BufOut->BufUsed;
+}
+
+typedef struct __z_enc_stream {
+ StrBuf OutBuf;
+ z_stream zstream;
+} z_enc_stream;
+
+
+vStreamT *StrBufNewStreamContext(eStreamType type, const char **Err) {
+ //base64_decodestate *state;;
+ *Err = NULL;
+
+ switch (type) {
+
+ //case eBase64Decode:
+ //case eBase64Encode:
+ //state = (base64_decodestate*) malloc(sizeof(base64_decodestate));
+ //base64_init_decodestate(state);
+ //return (vStreamT*) state;
+ //break;
+
+ case eZLibDecode: {
+
+ z_enc_stream *stream;
+ int err;
+
+ stream = (z_enc_stream *) malloc(sizeof(z_enc_stream));
+ memset(stream, 0, sizeof(z_enc_stream));
+ stream->OutBuf.BufSize = 4*SIZ; /// TODO 64
+ stream->OutBuf.buf = (char*)malloc(stream->OutBuf.BufSize);
+
+ err = inflateInit(&stream->zstream);
+
+ if (err != Z_OK) {
+ StrBufDestroyStreamContext(type, (vStreamT**) &stream, Err);
+ *Err = zError(err);
+ return NULL;
+ }
+ return (vStreamT*) stream;
+
+ }
+
+ case eZLibEncode: {
+ z_enc_stream *stream;
+ int err;
+
+ stream = (z_enc_stream *) malloc(sizeof(z_enc_stream));
+ memset(stream, 0, sizeof(z_enc_stream));
+ stream->OutBuf.BufSize = 4*SIZ; /// todo 64
+ stream->OutBuf.buf = (char*)malloc(stream->OutBuf.BufSize);
+ /* write gzip header */
+ stream->OutBuf.BufUsed = snprintf
+ (stream->OutBuf.buf,
+ stream->OutBuf.BufSize,
+ "%c%c%c%c%c%c%c%c%c%c",
+ gz_magic[0], gz_magic[1], Z_DEFLATED,
+ 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /* xflags */ ,
+ OS_CODE);
+
+ err = deflateInit2(&stream->zstream,
+ ZLibCompressionRatio,
+ Z_DEFLATED,
+ -MAX_WBITS,
+ DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY);
+ if (err != Z_OK) {
+ StrBufDestroyStreamContext(type, (vStreamT**) &stream, Err);
+ *Err = zError(err);
+ return NULL;
+ }
+ return (vStreamT*) stream;
+ }
+
+ case eEmtyCodec:
+ /// TODO
+ break;
+ }
+ return NULL;
+}
+
+
+int StrBufDestroyStreamContext(eStreamType type, vStreamT **vStream, const char **Err) {
+ int err;
+ int rc = 0;
+ *Err = NULL;
+
+ if ((vStream == NULL) || (*vStream==NULL)) {
+ *Err = strerror(EINVAL);
+ return EINVAL;
+ }
+ switch (type)
+ {
+ //case eBase64Encode:
+ //case eBase64Decode:
+ //free(*vStream);
+ //*vStream = NULL;
+ //break;
+ case eZLibDecode:
+ {
+ z_enc_stream *stream = (z_enc_stream *)*vStream;
+ (void)inflateEnd(&stream->zstream);
+ free(stream->OutBuf.buf);
+ free(stream);
+ }
+ case eZLibEncode:
+ {
+ z_enc_stream *stream = (z_enc_stream *)*vStream;
+ err = deflateEnd(&stream->zstream);
+ if (err != Z_OK) {
+ *Err = zError(err);
+ rc = -1;
+ }
+ free(stream->OutBuf.buf);
+ free(stream);
+ *vStream = NULL;
+ break;
+ }
+ case eEmtyCodec:
+ break; /// TODO
+ }
+ return rc;
+}
+
+int StrBufStreamTranscode(eStreamType type, IOBuffer *Target, IOBuffer *In, const char* pIn, long pInLen, vStreamT *vStream, int LastChunk, const char **Err) {
+ int rc = 0;
+ switch (type)
+ {
+ //case eBase64Encode:
+ //{
+ // ???
+ //}
+ //break;
+ //case eBase64Decode:
+ //{
+ //// ???
+ //}
+ //break;
+ case eZLibEncode:
+ {
+ z_enc_stream *stream = (z_enc_stream *)vStream;
+ int org_outbuf_len = stream->OutBuf.BufUsed;
+ int err;
+ unsigned int chunkavail;
+
+ if (In->ReadWritePointer != NULL)
+ {
+ stream->zstream.next_in = (Bytef *) In->ReadWritePointer;
+ stream->zstream.avail_in = (uInt) In->Buf->BufUsed -
+ (In->ReadWritePointer - In->Buf->buf);
+ }
+ else
+ {
+ stream->zstream.next_in = (Bytef *) In->Buf->buf;
+ stream->zstream.avail_in = (uInt) In->Buf->BufUsed;
+ }
+
+ stream->zstream.next_out = (unsigned char*)stream->OutBuf.buf + stream->OutBuf.BufUsed;
+ stream->zstream.avail_out = chunkavail = (uInt) stream->OutBuf.BufSize - stream->OutBuf.BufUsed;
+
+ err = deflate(&stream->zstream, (LastChunk) ? Z_FINISH : Z_NO_FLUSH);
+
+ stream->OutBuf.BufUsed += (chunkavail - stream->zstream.avail_out);
+
+ if (Target && (LastChunk || (stream->OutBuf.BufUsed != org_outbuf_len))) {
+ iSwapBuffers(Target->Buf, &stream->OutBuf);
+ }
+
+ if (stream->zstream.avail_in == 0) {
+ FlushStrBuf(In->Buf);
+ In->ReadWritePointer = NULL;
+ }
+ else {
+ if (stream->zstream.avail_in < 64) {
+ memmove(In->Buf->buf,
+ In->Buf->buf + In->Buf->BufUsed - stream->zstream.avail_in,
+ stream->zstream.avail_in);
+
+ In->Buf->BufUsed = stream->zstream.avail_in;
+ In->Buf->buf[In->Buf->BufUsed] = '\0';
+ }
+ else {
+ In->ReadWritePointer = In->Buf->buf + (In->Buf->BufUsed - stream->zstream.avail_in);
+ }
+ }
+ rc = (LastChunk && (err != Z_FINISH));
+ if (!rc && (err != Z_OK)) {
+ *Err = zError(err);
+ }
+
+ }
+ break;
+ case eZLibDecode: {
+ z_enc_stream *stream = (z_enc_stream *)vStream;
+ int org_outbuf_len = stream->zstream.total_out;
+ int err;
+
+ if ((stream->zstream.avail_out != 0) && (stream->zstream.next_in != NULL)) {
+ if (In->ReadWritePointer != NULL) {
+ stream->zstream.next_in = (Bytef *) In->ReadWritePointer;
+ stream->zstream.avail_in = (uInt) In->Buf->BufUsed - (In->ReadWritePointer - In->Buf->buf);
+ }
+ else {
+ stream->zstream.next_in = (Bytef *) In->Buf->buf;
+ stream->zstream.avail_in = (uInt) In->Buf->BufUsed;
+ }
+ }
+
+ stream->zstream.next_out = (unsigned char*)stream->OutBuf.buf + stream->OutBuf.BufUsed;
+ stream->zstream.avail_out = (uInt) stream->OutBuf.BufSize - stream->OutBuf.BufUsed;
+
+ err = inflate(&stream->zstream, Z_NO_FLUSH);
+
+ ///assert(ret != Z_STREAM_ERROR); /* state not clobbered * /
+ switch (err) {
+ case Z_NEED_DICT:
+ err = Z_DATA_ERROR; /* and fall through */
+
+ case Z_DATA_ERROR:
+ *Err = zError(err);
+ case Z_MEM_ERROR:
+ (void)inflateEnd(&stream->zstream);
+ return err;
+ }
+
+ stream->OutBuf.BufUsed += stream->zstream.total_out + org_outbuf_len;
+
+ if (Target) iSwapBuffers(Target->Buf, &stream->OutBuf);
+
+ if (stream->zstream.avail_in == 0) {
+ FlushStrBuf(In->Buf);
+ In->ReadWritePointer = NULL;
+ }
+ else {
+ if (stream->zstream.avail_in < 64) {
+ memmove(In->Buf->buf,
+ In->Buf->buf + In->Buf->BufUsed - stream->zstream.avail_in,
+ stream->zstream.avail_in);
+
+ In->Buf->BufUsed = stream->zstream.avail_in;
+ In->Buf->buf[In->Buf->BufUsed] = '\0';
+ }
+ else {
+
+ In->ReadWritePointer = In->Buf->buf + (In->Buf->BufUsed - stream->zstream.avail_in);
+ }
+ }
+ }
+ break;
+ case eEmtyCodec: {
+
+ }
+ break; /// TODO
+ }
+ return rc;
+}
+