+/**
+ * @ingroup StrBuf_DeEnCoder
+ * @brief decode a buffer from base 64 encoding; expects targetbuffer
+ * @param BufIn Buffor to transform
+ * @param 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, BufIn->BufUsed, 0);
+
+ 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;
+
+void *StrBufNewStreamContext(eStreamType type)
+{
+ base64_decodestate *state;;
+
+ switch (type)
+ {
+ case eBase64Decode:
+ case eBase64Encode:
+ state = (base64_decodestate*) malloc(sizeof(base64_decodestate));
+ base64_init_decodestate(state);
+ return 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)
+ return NULL;/// tODO cleanup
+ return 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)
+ return NULL;/// tODO cleanup
+ return stream;
+ }
+ case eEmtyCodec:
+ /// TODO
+
+ break;
+ }
+ return NULL;
+}
+
+void StrBufDestroyStreamContext(eStreamType type, void **vStream)
+{
+ 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;
+ free(stream->OutBuf.buf);
+ free(stream);
+// todo more?
+ *vStream = NULL;
+ break;
+ }
+ case eEmtyCodec:
+ break; /// TODO
+ }
+}
+
+void StrBufStreamTranscode(eStreamType type, IOBuffer *Target, IOBuffer *In, const char* pIn, long pInLen, void *vStream, int LastChunk)
+{
+
+ switch (type)
+ {
+ case eBase64Encode:
+ {
+ /// TODO
+/*
+ // base64_decodestate *state = (base64_decodestate*)vStream;
+ long ExpectLen;
+
+ if (In != NULL)
+ {
+ pIn = In->buf;
+ pInLen = In->BufUsed;
+ }
+ if ((In == NULL) || (vStream == NULL))
+ return;
+
+ ExpectLen = (pInLen / 4) * 3;
+
+ if (Target->BufSize - Target->BufUsed < ExpectLen)
+ {
+ IncreaseBuf(Target, 1, Target->BufUsed + ExpectLen + 1);
+ }
+
+ //// ExpectLen = base64_encode_block(pIn, pInLen, Target->buf + Target->BufUsed, state);
+ Target->BufUsed += ExpectLen;
+ Target->buf[Target->BufUsed] = '\0';
+*/
+ }
+ break;
+ case eBase64Decode:
+ {
+/*
+ base64_decodestate *state = (base64_decodestate *)vStream;
+ long ExpectLen;
+
+ if (In != NULL)
+ {
+ pIn = In->buf;
+ pInLen = In->BufUsed;
+ }
+ if ((pIn == NULL) || (vStream == NULL))
+ return;
+
+ ExpectLen = (pInLen / 4) * 3;
+
+ if (Target->BufSize - Target->BufUsed < ExpectLen)
+ {
+ IncreaseBuf(Target, 1, Target->BufUsed + ExpectLen + 1);
+ }
+
+ ExpectLen = base64_decode_block(pIn, pInLen, Target->buf + Target->BufUsed, state);
+ Target->BufUsed += ExpectLen;
+ Target->buf[Target->BufUsed] = '\0';
+*/
+ }
+ break;
+ case eZLibEncode:
+ {
+ z_enc_stream *stream = (z_enc_stream *)vStream;
+ int org_outbuf_len = stream->zstream.total_out;
+ 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);
+ /// todo + org_outbuf_len;
+
+ if (Target) SwapBuffers(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 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:
+ fprintf(stderr, "sanoteuh\n");
+ case Z_MEM_ERROR:
+ (void)inflateEnd(&stream->zstream);
+ return err;
+ }
+
+ stream->OutBuf.BufUsed += stream->zstream.total_out + org_outbuf_len;
+
+ if (Target) SwapBuffers(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
+ }
+}
+