STATIC Bool GWENG_QueueFlush(EcmtQueueConnection* qc) { if (qc->header && BUFFER_Size(&qc->buf) >= ECMT_MSG_HEADER_SIZE) { char* hdr = BUFFER_Access(&qc->buf); if (GWENG_ParseEcmtHeader(hdr, &qc->uid, &qc->datalen)) { qc->header = False; qc->datalen -= ECMT_MSG_HEADER_SIZE; BUFFER_Skip(&qc->buf, ECMT_MSG_HEADER_SIZE); } else { /* There shoudn't be any garbage here */ ASSMSG("Garbage in GWENG_QueueFlush"); return False; } } if (!qc->header && BUFFER_Size(&qc->buf) >= qc->datalen) { char* data = BUFFER_Access(&qc->buf); GWENG_QueueAdd(qc->queue, qc->uid, data, qc->datalen); BUFFER_Skip(&qc->buf, qc->datalen); qc->header = True; qc->datalen = 0; qc->uid = 0; return True; } return False; }
STATIC void EXPAT_StartElement(void * ctx, XML_Str tag, XML_Str * atts) { ExpatContext * expat = (ExpatContext *)ctx; if (expat->cb.startElem) { XMLAttr aset; XML_Str * s = atts; BUFFER_Clear(&expat->buf); BUFFER_Clear(&expat->atts); while (*s) { wchar_t* ws; XML_Str xs = *s++; /* * store offset in the vector - later will be replaces with the * pointer. Cannot store the pointers now because buffer may be * reallocated during conversion. */ const int off = BUFFER_Size(&expat->buf)/sizeof(Char); BUFFER_Put(&expat->atts, &off, sizeof(off), False); /* Convert from UTF-8 XML_Str to Str */ ws = STRING_ToUnicode(xs); if (ws) { #ifdef UNICODE BUFFER_Put(&expat->buf,ws,(wcslen(ws)+1)*sizeof(ws[0]),False); #else char * mb = STRING_ToMultiByte(ws); if (mb) { BUFFER_Put(&expat->buf, mb, strlen(mb)+1, False); MEM_Free(mb); } else { BUFFER_Put(&expat->buf, xs, strlen(xs)+1, False); } #endif MEM_Free(ws); } } ASSERT(!((BUFFER_Size(&expat->atts)/sizeof(int))%2)); aset.storage = BUFFER_Access(&expat->buf); aset.size = BUFFER_Size(&expat->buf); aset.off = BUFFER_Access(&expat->atts); aset.n = BUFFER_Size(&expat->atts)/sizeof(int)/2; EXPAT_ConvertTag(&expat->sb, tag); (*expat->cb.startElem)(expat->ctx, STRBUF_Text(&expat->sb), &aset); } }
/** * Decodes a BASE64 encoded data block. Returns True if string has been * successfully decoded, or False if it cannot be decoded (or memory * allocation fails). The len parameter is negative if the amount of * data is unknown in advance. */ STATIC Bool BASE64_DecodeFile2(File * in, size_t len, Buffer * out, const I8u * map) { Base64Decode decode; /* pre-allocate memory in the output buffer */ if (out && len > 0) { size_t nbytes = 3*len/4; if (len%4) nbytes++; if (!BUFFER_EnsureCapacity(out, BUFFER_Size(out) + nbytes, False)) { return False; } } /* initialize the context */ decode.in = in; decode.nread = 0; decode.out = out; if (map) { decode.decodeMap = map; decode.flags = 0; } else { decode.decodeMap = base64_decodeMap; decode.flags = FLAG_DETECT; } /* run the decoder */ return BASE64_InternalDecode(&decode); }
STATIC void EXPAT_StartElement(void * ctx, XML_Str tag, XML_Str * atts) { ExpatContext * expat = (ExpatContext *)ctx; if (expat->cb.startElem) { XMLAttr aset; XML_Str * s = atts; BUFFER_Clear(&expat->buf); VECTOR_Clear(&expat->atts); while (*s) { Char tmp; const XML_Char * c = (*s); /* * store offset in the vector - later will be replaces with the * pointer. Cannot store the pointers now because buffer may be * reallocated during conversion. */ int off = BUFFER_Size(&expat->buf)/sizeof(Char); VECTOR_Add(&expat->atts,(VElement)(PtrWord)off); /* * Pretty naive convertion of attribute names and values from * XML_Str to Str. This part may need some improvement... */ while (*c) { tmp = (Char)*c; BUFFER_Put(&expat->buf, &tmp, sizeof(tmp), False); c++; } tmp = 0; BUFFER_Put(&expat->buf, &tmp, sizeof(tmp), False); s++; } ASSERT(!(VECTOR_Size(&expat->atts)%2)); aset.storage = (Char*)BUFFER_Access(&expat->buf); aset.size = BUFFER_Size(&expat->buf); aset.off = (int*)VECTOR_GetElements(&expat->atts); aset.n = VECTOR_Size(&expat->atts)/2; EXPAT_ConvertTag(&expat->sb, tag); (*expat->cb.startElem)(expat->ctx, STRBUF_Text(&expat->sb), &aset); } }
STATIC Bool GWENG_QueueWrite(EcmtConnection* c, const void* data, int size) { EcmtQueueConnection* qc = CAST(c,EcmtQueueConnection,connection); /* * Try to avoid copying. Most of the time we can safely do that because * both header and data are written as single chunks. However, if they * are not so nicely packaged, we have plan B. */ if (!BUFFER_Size(&qc->buf)) { if (qc->header && size>=ECMT_MSG_HEADER_SIZE) { if (GWENG_ParseEcmtHeader(data, &qc->uid, &qc->datalen)) { data = ((char*)data) + ECMT_MSG_HEADER_SIZE; size -= ECMT_MSG_HEADER_SIZE; qc->datalen -= ECMT_MSG_HEADER_SIZE; qc->header = False; } else { /* There shoudn't be any garbage here */ ASSMSG("Garbage in GWENG_QueueWrite"); return False; } } if (!qc->header && size >= qc->datalen) { GWENG_QueueAdd(qc->queue, qc->uid, data, qc->datalen); data = ((char*)data) + qc->datalen; size -= qc->datalen; qc->uid = 0; qc->datalen = 0; qc->header = True; } } if (size > 0) { /* Plan B */ if (BUFFER_Put(&qc->buf, data, size, False) == size) { while (GWENG_QueueFlush(qc)); } else { return False; } } return True; }
/** * Decodes a BASE32 encoded data block. Returns True if string has been * successfully decoded, or False if it cannot be decoded (or memory * allocation fails). The len parameter is negative if the amount of * data is unknown in advance. */ STATIC Bool BASE32_DecodeFile2(File * in,int len,Buffer * out,const I8u * map) { Base32Decode decode; /* pre-allocate maximum amount of memory for the output buffer */ if (out && len > 0) { int nbytes = ENCODE_CHUNK_SIZE*(len/DECODE_CHUNK_SIZE); switch (len % DECODE_CHUNK_SIZE) { case 0: case 1: break; case 2: case 3: nbytes++; /* NOBREAK */ case 4: nbytes++; /* NOBREAK */ case 5: case 6: nbytes++; /* NOBREAK */ case 7: nbytes++; break; } if (!BUFFER_EnsureCapacity(out, BUFFER_Size(out) + nbytes, False)) { return False; } } /* initialize the context */ decode.in = in; decode.nread = 0; decode.out = out; decode.decodeMap = map; decode.flags = 0; /* run the decoder */ return BASE32_InternalDecode(&decode); }
/** * Decodes a BASE64 encoded data block. Returns True if string has been * successfully decoded, or False if it cannot be decoded (or memory * allocation fails). Does not destroy the original contents of the * buffer */ STATIC Bool BASE64_InternalDecode(Base64Decode * decode) { /* remember the original length so that we can undo the damage */ Buffer* out = decode->out; size_t origLen = (out ? BUFFER_Size(out) : 0); /* read the bulk of the data */ int n; Bool ok = True; I8u chunk[4]; while ((n = BASE64_ReadChunk(decode, chunk)) == 4) { if (out) { if (!BUFFER_PutByte(out,BASE64_DECODE_1(chunk[0],chunk[1])) || !BUFFER_PutByte(out,BASE64_DECODE_2(chunk[1],chunk[2])) || !BUFFER_PutByte(out,BASE64_DECODE_3(chunk[2],chunk[3]))) { /* out of memory */ ok = False; break; } } } /* deal with the trailer */ if (out && ok) { switch (n) { case 0: break; case 1: /* premature end of BASE64 stream */ decode->flags |= FLAG_ERROR; break; case 2: if (!BUFFER_PutByte(out,BASE64_DECODE_1(chunk[0],chunk[1]))) { /* out of memory */ ok = False; } break; case 3: if (!BUFFER_PutByte(out,BASE64_DECODE_1(chunk[0],chunk[1])) || !BUFFER_PutByte(out,BASE64_DECODE_2(chunk[1],chunk[2]))) { /* out of memory */ ok = False; } break; case 4: if (!BUFFER_PutByte(out,BASE64_DECODE_1(chunk[0],chunk[1])) || !BUFFER_PutByte(out,BASE64_DECODE_2(chunk[1],chunk[2])) || !BUFFER_PutByte(out,BASE64_DECODE_3(chunk[2],chunk[3]))) { /* out of memory */ ok = False; } break; } } /* return True if the input was a valid BASE64 sequence */ if ((decode->flags & FLAG_ERROR) || !ok) { if (out) { BUFFER_Unput(out,BUFFER_Size(out)-origLen); ASSERT(BUFFER_Size(out) == (int)origLen); } return False; } else { return True; } }
/** * Decodes a BASE32 encoded data block. Returns True if string has been * successfully decoded, or False if it cannot be decoded (or memory * allocation fails). Does not destroy the original contents of the * buffer */ STATIC Bool BASE32_InternalDecode(Base32Decode * decode) { /* remember the original length so that we can undo the damage */ Buffer * out = decode->out; int origLen = (out ? BUFFER_Size(out) : 0); /* read the bulk of the data */ int n; Bool ok = True; I8u b[DECODE_CHUNK_SIZE]; while ((n = BASE32_ReadChunk(decode, b)) == DECODE_CHUNK_SIZE) { if (out) { if (!BUFFER_PutByte(out,BASE32_DECODE_1(b[0],b[1])) || !BUFFER_PutByte(out,BASE32_DECODE_2(b[1],b[2],b[3])) || !BUFFER_PutByte(out,BASE32_DECODE_3(b[3],b[4])) || !BUFFER_PutByte(out,BASE32_DECODE_4(b[4],b[5],b[6])) || !BUFFER_PutByte(out,BASE32_DECODE_5(b[6],b[7]))) { /* out of memory */ ok = False; break; } } } /* * +--- octet 0 ---+--- octet 1 ---+--- octet 2 ---+ * |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| * +---------+-----+---+---------+-+-------+-------+ * |4 3 2 1 0|4 3 2 1 0|4 3 2 1 0|4 3 2 1 0|4 3 2 1 * +-0.index-+-1.index-+-2.index-+-3.index-+-4.index * * +--- octet 3 ---+--- octet 4 ---+ * |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| * +-+---------+---+-----+---------+ * 0|4 3 2 1 0|4 3 2 1 0|4 3 2 1 0| * --+-5.index-+-6.index-+-7.index-+ */ /* deal with the trailer */ if (out && ok) { switch (n) { case 0: break; case 1: case 3: case 6: /* incorrect trailer */ decode->flags |= FLAG_ERROR; break; case 2: if (!BUFFER_PutByte(out,BASE32_DECODE_1(b[0],b[1]))) { /* out of memory */ ok = False; } break; case 4: if (!BUFFER_PutByte(out,BASE32_DECODE_1(b[0],b[1])) || !BUFFER_PutByte(out,BASE32_DECODE_2(b[1],b[2],b[3]))) { /* out of memory */ ok = False; return False; } break; case 5: if (!BUFFER_PutByte(out,BASE32_DECODE_1(b[0],b[1])) || !BUFFER_PutByte(out,BASE32_DECODE_2(b[1],b[2],b[3])) || !BUFFER_PutByte(out,BASE32_DECODE_3(b[3],b[4]))) { /* out of memory */ ok = False; return False; } break; case 7: if (!BUFFER_PutByte(out,BASE32_DECODE_1(b[0],b[1])) || !BUFFER_PutByte(out,BASE32_DECODE_2(b[1],b[2],b[3])) || !BUFFER_PutByte(out,BASE32_DECODE_3(b[3],b[4])) || !BUFFER_PutByte(out,BASE32_DECODE_4(b[4],b[5],b[6]))) { /* out of memory */ ok = False; return False; } break; } } /* return True if the input was a valid BASE32 sequence */ if ((decode->flags & FLAG_ERROR) || !ok) { if (out) { BUFFER_Unput(out,BUFFER_Size(out)-origLen); ASSERT(BUFFER_Size(out) == origLen); } return False; } else { return True; } }