return -1;
if (DestSize > 0)
- while (NewSize <= DestSize)
+ while ((NewSize <= DestSize) && (NewSize != 0))
NewSize *= 2;
+ if (NewSize == 0)
+ return -1;
+
NewBuf= (char*) malloc(NewSize);
if (NewBuf == NULL)
return -1;
else
CopySize = nChars;
- while (Siz <= CopySize)
+ while ((Siz <= CopySize) && (Siz != 0))
Siz *= 2;
+ if (Siz == 0)
+ {
+ return NULL;
+ }
+
NewBuf->buf = (char*) malloc(Siz);
if (NewBuf->buf == NULL)
{
else
CopySize = nChars;
- while (Siz <= CopySize)
+ while ((Siz <= CopySize) && (Siz != 0))
Siz *= 2;
+ if (Siz == 0) {
+ FlushStrBuf(Buf);
+ return -1;
+ }
+
if (Siz != Buf->BufSize)
IncreaseBuf(Buf, 0, Siz);
memcpy(Buf->buf, ptr, CopySize);
va_end(apl);
newused = Offset + nWritten;
if (newused >= Buf->BufSize) {
- IncreaseBuf(Buf, 1, newused);
+ if (IncreaseBuf(Buf, 1, newused) == -1)
+ return; /* TODO: error handling? */
newused = Buf->BufSize + 1;
}
else {
va_end(arg_ptr);
newused = Buf->BufUsed + nWritten;
if (newused >= Buf->BufSize) {
- IncreaseBuf(Buf, 1, newused);
+ if (IncreaseBuf(Buf, 1, newused) == -1)
+ return; /* TODO: error handling? */
newused = Buf->BufSize + 1;
}
else {
nWritten = vsnprintf(Buf->buf, Buf->BufSize, format, arg_ptr);
va_end(arg_ptr);
if (nWritten >= Buf->BufSize) {
- IncreaseBuf(Buf, 0, 0);
+ if (IncreaseBuf(Buf, 0, 0) == -1)
+ return; /* TODO: error handling? */
nWritten = Buf->BufSize + 1;
continue;
}
//cit_backtrace();
//lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
- while ((s<e) && !IsEmptyStr(s)) {
+ while ((s < e) && !IsEmptyStr(s)) {
if (*s == separator) {
++current_token;
}
(Source->BufUsed == 0) )
{
*pStart = StrBufNOTNULL;
+ if (dest != NULL)
+ FlushStrBuf(dest);
return -1;
}
//cit_backtrace();
//lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
- while ((s<EndBuffer) && !IsEmptyStr(s)) {
+ while ((s < EndBuffer) && !IsEmptyStr(s)) {
if (*s == separator) {
++current_token;
}
* @param OutBuf the output buffer
* @param In Buffer to encode
* @param PlainIn way in from plain old c strings
+ * @param PlainInLen way in from plain old c strings; maybe you've got binary data or know the length?
*/
-void StrBufHexescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn)
+void StrBufHexEscAppend(StrBuf *OutBuf, const StrBuf *In, const unsigned char *PlainIn, long PlainInLen)
{
- const char *pch, *pche;
+ const unsigned char *pch, *pche;
char *pt, *pte;
int len;
if (((In == NULL) && (PlainIn == NULL)) || (OutBuf == NULL) )
return;
if (PlainIn != NULL) {
- len = strlen(PlainIn);
+ if (PlainInLen < 0)
+ len = strlen((const char*)PlainIn);
+ else
+ len = PlainInLen;
pch = PlainIn;
pche = pch + len;
}
else {
- pch = In->buf;
+ pch = (const unsigned char*)In->buf;
pche = pch + In->BufUsed;
len = In->BufUsed;
}
pt = OutBuf->buf + OutBuf->BufUsed;
}
- *pt = HexList[(unsigned char)*pch][0];
+ *pt = HexList[*pch][0];
pt ++;
- *pt = HexList[(unsigned char)*pch][1];
+ *pt = HexList[*pch][1];
pt ++; pch ++; OutBuf->BufUsed += 2;
}
*pt = '\0';
}
+/**
+ * @ingroup StrBuf_DeEnCoder
+ * @brief append a string in hex encoding to the buffer
+ * @param OutBuf the output buffer
+ * @param In Buffer to encode
+ * @param PlainIn way in from plain old c strings
+ */
+void StrBufHexescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn)
+{
+ StrBufHexEscAppend(OutBuf, In, (const unsigned char*) PlainIn, -1);
+}
+
/**
* @ingroup StrBuf_DeEnCoder
* @brief Append a string, escaping characters which have meaning in HTML.
return NULL;
if ((Buf->BufUsed - (end - Buf->buf) > 3) &&
- ((*(end + 1) == 'B') || (*(end + 1) == 'Q')) &&
+ (((*(end + 1) == 'B') || (*(end + 1) == 'Q')) ||
+ ((*(end + 1) == 'b') || (*(end + 1) == 'q'))) &&
(*(end + 2) == '?')) {
/* skip on to the end of the cluster, the next ?= */
end = strstr(end + 3, "?=");
start = strstr(DecodeMee->buf, "=?");
eptr = DecodeMee->buf + DecodeMee->BufUsed;
if (start != NULL)
- end = FindNextEnd (DecodeMee, start);
+ end = FindNextEnd (DecodeMee, start + 2);
else {
StrBufAppendBuf(Target, DecodeMee, 0);
FreeStrBuf(&DecodedInvalidBuf);
return 0;
}
+/*******************************************************************************
+ * File I/O; Callbacks to libevent *
+ *******************************************************************************/
+
+long StrBuf_read_one_chunk_callback (int fd, short event, IOBuffer *FB)
+{
+ long bufremain = 0;
+ int n;
+
+ if ((FB == NULL) || (FB->Buf == NULL))
+ return -1;
+
+ /*
+ * check whether the read pointer is somewhere in a range
+ * where a cut left is inexpensive
+ */
+
+ if (FB->ReadWritePointer != NULL)
+ {
+ long already_read;
+
+ already_read = FB->ReadWritePointer - FB->Buf->buf;
+ bufremain = FB->Buf->BufSize - FB->Buf->BufUsed - 1;
+
+ if (already_read != 0) {
+ long unread;
+
+ unread = FB->Buf->BufUsed - already_read;
+
+ /* else nothing to compact... */
+ if (unread == 0) {
+ FB->ReadWritePointer = FB->Buf->buf;
+ bufremain = FB->Buf->BufSize;
+ }
+ else if ((unread < 64) ||
+ (bufremain < already_read))
+ {
+ /*
+ * if its just a tiny bit remaining, or we run out of space...
+ * lets tidy up.
+ */
+ FB->Buf->BufUsed = unread;
+ if (unread < already_read)
+ memcpy(FB->Buf->buf, FB->ReadWritePointer, unread);
+ else
+ memmove(FB->Buf->buf, FB->ReadWritePointer, unread);
+ FB->ReadWritePointer = FB->Buf->buf;
+ bufremain = FB->Buf->BufSize - unread - 1;
+ }
+ else if (bufremain < (FB->Buf->BufSize / 10))
+ {
+ /* get a bigger buffer */
+
+ IncreaseBuf(FB->Buf, 0, FB->Buf->BufUsed + 1);
+
+ FB->ReadWritePointer = FB->Buf->buf + unread;
+
+ bufremain = FB->Buf->BufSize - unread - 1;
+/*TODO: special increase function that won't copy the already read! */
+ }
+ }
+ else if (bufremain < 10) {
+ IncreaseBuf(FB->Buf, 1, FB->Buf->BufUsed + 10);
+
+ FB->ReadWritePointer = FB->Buf->buf;
+
+ bufremain = FB->Buf->BufSize - FB->Buf->BufUsed - 1;
+ }
+
+ }
+ else {
+ FB->ReadWritePointer = FB->Buf->buf;
+ bufremain = FB->Buf->BufSize - 1;
+ }
+
+ n = read(fd, FB->Buf->buf + FB->Buf->BufUsed, bufremain);
+
+ if (n > 0) {
+ FB->Buf->BufUsed += n;
+ FB->Buf->buf[FB->Buf->BufUsed] = '\0';
+ }
+ return n;
+}
+
+int StrBuf_write_one_chunk_callback(int fd, short event, IOBuffer *FB)
+{
+ long WriteRemain;
+ int n;
+
+ if ((FB == NULL) || (FB->Buf == NULL))
+ return -1;
+
+ if (FB->ReadWritePointer != NULL)
+ {
+ WriteRemain = FB->Buf->BufUsed -
+ (FB->ReadWritePointer -
+ FB->Buf->buf);
+ }
+ else {
+ FB->ReadWritePointer = FB->Buf->buf;
+ WriteRemain = FB->Buf->BufUsed;
+ }
+
+ n = write(fd, FB->ReadWritePointer, WriteRemain);
+ if (n > 0) {
+ FB->ReadWritePointer += n;
+
+ if (FB->ReadWritePointer ==
+ FB->Buf->buf + FB->Buf->BufUsed)
+ {
+ FlushStrBuf(FB->Buf);
+ FB->ReadWritePointer = NULL;
+ return 0;
+ }
+ // check whether we've got something to write
+ // get the maximum chunk plus the pointer we can send
+ // write whats there
+ // if not all was sent, remember the send pointer for the next time
+ return FB->ReadWritePointer - FB->Buf->buf + FB->Buf->BufUsed;
+ }
+ return n;
+}
+
+/**
+ * @ingroup StrBuf_IO
+ * @brief extract a "next line" from Buf; Ptr to persist across several iterations
+ * @param LineBuf your line will be copied here.
+ * @param FB BLOB with lines of text...
+ * @param Ptr moved arround to keep the next-line across several iterations
+ * has to be &NULL on start; will be &NotNULL on end of buffer
+ * @returns size of copied buffer
+ */
+eReadState StrBufChunkSipLine(StrBuf *LineBuf, IOBuffer *FB)
+{
+ const char *aptr, *ptr, *eptr;
+ char *optr, *xptr;
+ if ((FB->Buf == NULL) || (FB->ReadWritePointer == StrBufNOTNULL)) {
+ FB->ReadWritePointer = StrBufNOTNULL;
+ return eReadFail;
+ }
+
+ FlushStrBuf(LineBuf);
+ if (FB->ReadWritePointer == NULL)
+ ptr = aptr = FB->Buf->buf;
+ else
+ ptr = aptr = FB->ReadWritePointer;
+
+ optr = LineBuf->buf;
+ eptr = FB->Buf->buf + FB->Buf->BufUsed;
+ xptr = LineBuf->buf + LineBuf->BufSize - 1;
+
+ while ((ptr <= eptr) &&
+ (*ptr != '\n') &&
+ (*ptr != '\r') )
+ {
+ *optr = *ptr;
+ optr++; ptr++;
+ if (optr == xptr) {
+ LineBuf->BufUsed = optr - LineBuf->buf;
+ IncreaseBuf(LineBuf, 1, LineBuf->BufUsed + 1);
+ optr = LineBuf->buf + LineBuf->BufUsed;
+ xptr = LineBuf->buf + LineBuf->BufSize - 1;
+ }
+ }
+
+ if (ptr >= eptr) {
+ if (optr > LineBuf->buf)
+ optr --;
+ if ((*(ptr - 1) != '\r') && (*(ptr - 1) != '\n')) {
+ LineBuf->BufUsed = optr - LineBuf->buf;
+ *optr = '\0';
+ return eMustReadMore;
+ }
+ }
+ LineBuf->BufUsed = optr - LineBuf->buf;
+ *optr = '\0';
+ if ((ptr <= eptr) && (*ptr == '\r'))
+ ptr ++;
+ if ((ptr <= eptr) && (*ptr == '\n'))
+ ptr ++;
+
+ if (ptr < eptr) {
+ FB->ReadWritePointer = ptr;
+ }
+ else {
+ FlushStrBuf(FB->Buf);
+ FB->ReadWritePointer = NULL;
+ }
+
+ return eReadSuccess;
+}
+
+/**
+ * @ingroup StrBuf_CHUNKED_IO
+ * @brief check whether the chunk-buffer has more data waiting or not.
+ * @param FB Chunk-Buffer to inspect
+ */
+eReadState StrBufCheckBuffer(IOBuffer *FB)
+{
+ if (FB == NULL)
+ return eReadFail;
+ if (FB->Buf->BufUsed == 0)
+ return eReadSuccess;
+ if (FB->ReadWritePointer == NULL)
+ return eBufferNotEmpty;
+ if (FB->Buf->buf + FB->Buf->BufUsed > FB->ReadWritePointer)
+ return eBufferNotEmpty;
+ return eReadSuccess;
+}
/*******************************************************************************
* File I/O; Prefer buffered read since its faster! *
* @param Buf BLOB with lines of text...
* @param Ptr moved arround to keep the next-line across several iterations
* has to be &NULL on start; will be &NotNULL on end of buffer
- * @returns size of copied buffer
+ * @returns size of remaining buffer
*/
int StrBufSipLine(StrBuf *LineBuf, StrBuf *Buf, const char **Ptr)
{