X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=libcitadel%2Flib%2Fstringbuf.c;h=d31c227c53059edb6e74c4958b5c1b6d7e459a1e;hb=7d66c47a0d5c5c1b0053409153db4a3750aa70d6;hp=4cee2be32980d3133f41bdd9749a48ae850b375e;hpb=e3e7a535f4370c4cd45cb9f820cb858eef349e80;p=citadel.git diff --git a/libcitadel/lib/stringbuf.c b/libcitadel/lib/stringbuf.c index 4cee2be32..d31c227c5 100644 --- a/libcitadel/lib/stringbuf.c +++ b/libcitadel/lib/stringbuf.c @@ -1,20 +1,7 @@ -/* - * Copyright (c) 1987-2013 by the citadel.org team - * - * This program is open source software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ +// Copyright (c) 1987-2023 by the citadel.org team +// +// This program is open source software. Use, duplication, or disclosure +// is subject to the terms of the GNU General Public License, version 3. #define _GNU_SOURCE #include "sysdep.h" @@ -46,11 +33,16 @@ #ifdef HAVE_ZLIB #include -int ZEXPORT compress_gzip(Bytef * dest, size_t * destLen, - const Bytef * source, uLong sourceLen, int level); +int ZEXPORT compress_gzip(Bytef * dest, size_t * destLen, const Bytef * source, uLong sourceLen, int level); #endif int BaseStrBufSize = 64; int EnableSplice = 0; +int ZLibCompressionRatio = -1; /* defaults to 6 */ +#ifdef HAVE_ZLIB +#define DEF_MEM_LEVEL 8 /*< memlevel??? */ +#define OS_CODE 0x03 /*< unix */ +const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */ +#endif const char *StrBufNOTNULL = ((char*) NULL) - 1; @@ -72,68 +64,8 @@ const char HexList[256][3] = { "E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF", "F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"}; -/** - * @defgroup StrBuf Stringbuffer, A class for manipulating strings with dynamic buffers - * StrBuf is a versatile class, aiding the handling of dynamic strings - * * reduce de/reallocations - * * reduce the need to remeasure it - * * reduce scanning over the string (in @ref StrBuf_NextTokenizer "Tokenizers") - * * allow asyncroneous IO for line and Blob based operations - * * reduce the use of memove in those - * * Quick filling in several operations with append functions - */ - -/** - * @defgroup StrBuf_DeConstructors Create/Destroy StrBufs - * @ingroup StrBuf - */ - -/** - * @defgroup StrBuf_Cast Cast operators to interact with char* based code - * @ingroup StrBuf - * use these operators to interfere with code demanding char*; - * if you need to own the content, smash me. Avoid, since we loose the length information. - */ - -/** - * @defgroup StrBuf_Filler Create/Replace/Append Content into a StrBuf - * @ingroup StrBuf - * operations to get your Strings into a StrBuf, manipulating them, or appending - */ -/** - * @defgroup StrBuf_NextTokenizer Fast tokenizer to pull tokens in sequence - * @ingroup StrBuf - * Quick tokenizer; demands of the user to pull its tokens in sequence - */ - -/** - * @defgroup StrBuf_Tokenizer tokenizer Functions; Slow ones. - * @ingroup StrBuf - * versatile tokenizer; random access to tokens, but slower; Prefer the @ref StrBuf_NextTokenizer "Next Tokenizer" - */ - -/** - * @defgroup StrBuf_BufferedIO Buffered IO with Asynchroneous reads and no unneeded memmoves (the fast ones) - * @ingroup StrBuf - * File IO to fill StrBufs; Works with work-buffer shared across several calls; - * External Cursor to maintain the current read position inside of the buffer - * the non-fast ones will use memove to keep the start of the buffer the read buffer (which is slower) - */ - -/** - * @defgroup StrBuf_IO FileIO; Prefer @ref StrBuf_BufferedIO - * @ingroup StrBuf - * Slow I/O; avoid. - */ - -/** - * @defgroup StrBuf_DeEnCoder functions to translate the contents of a buffer - * @ingroup StrBuf - * these functions translate the content of a buffer into another representation; - * some are combined Fillers and encoders - */ -/** +/* * Private Structure for the Stringbuffer */ struct StrBuf { @@ -154,8 +86,7 @@ static inline int Ctdl_IsUtf8SequenceStart(const char Char); #ifdef SIZE_DEBUG #ifdef HAVE_BACKTRACE -static void StrBufBacktrace(StrBuf *Buf, int which) -{ +static void StrBufBacktrace(StrBuf *Buf, int which) { int n; char *pstart, *pch; void *stack_frames[50]; @@ -181,16 +112,15 @@ static void StrBufBacktrace(StrBuf *Buf, int which) } #endif -void dbg_FreeStrBuf(StrBuf *FreeMe, char *FromWhere) -{ - if (hFreeDbglog == -1){ + +void dbg_FreeStrBuf(StrBuf *FreeMe, char *FromWhere) { + if (hFreeDbglog == -1) { pid_t pid = getpid(); char path [SIZ]; snprintf(path, SIZ, "/tmp/libcitadel_strbuf_realloc.log.%d", pid); hFreeDbglog = open(path, O_APPEND|O_CREAT|O_WRONLY); } - if ((*FreeMe)->nIncreases > 0) - { + if ((*FreeMe)->nIncreases > 0) { char buf[SIZ * 3]; long n; n = snprintf(buf, SIZ * 3, "%c+|%ld|%ld|%ld|%s|%s|\n", @@ -202,8 +132,7 @@ void dbg_FreeStrBuf(StrBuf *FreeMe, char *FromWhere) (*FreeMe)->bt_lastinc); n = write(hFreeDbglog, buf, n); } - else - { + else { char buf[128]; long n; n = snprintf(buf, 128, "%c_|0|%ld%ld|\n", @@ -214,16 +143,16 @@ void dbg_FreeStrBuf(StrBuf *FreeMe, char *FromWhere) } } -void dbg_IncreaseBuf(StrBuf *IncMe) -{ + +void dbg_IncreaseBuf(StrBuf *IncMe) { Buf->nIncreases++; #ifdef HAVE_BACKTRACE StrBufBacktrace(Buf, 1); #endif } -void dbg_Init(StrBuf *Buf) -{ + +void dbg_Init(StrBuf *Buf) { Buf->nIncreases = 0; Buf->bt[0] = '\0'; Buf->bt_lastinc[0] = '\0'; @@ -240,15 +169,13 @@ void dbg_Init(StrBuf *Buf) #endif -/** - * @ingroup StrBuf - * @brief swaps the contents of two StrBufs +/* + * swaps the contents of two StrBufs * this is to be used to have cheap switched between a work-buffer and a target buffer - * @param A First one - * @param B second one + * A First one + * B second one */ -static inline void SwapBuffers(StrBuf *A, StrBuf *B) -{ +static inline void iSwapBuffers(StrBuf *A, StrBuf *B) { StrBuf C; memcpy(&C, A, sizeof(*A)); @@ -257,66 +184,69 @@ static inline void SwapBuffers(StrBuf *A, StrBuf *B) } -/** - * @ingroup StrBuf_Cast - * @brief Cast operator to Plain String + +void SwapBuffers(StrBuf *A, StrBuf *B) { + iSwapBuffers(A, B); +} + + +/* + * Cast operator to Plain String * @note if the buffer is altered by StrBuf operations, this pointer may become * invalid. So don't lean on it after altering the buffer! * Since this operation is considered cheap, rather call it often than risking * your pointer to become invalid! - * @param Str the string we want to get the c-string representation for + * Str the string we want to get the c-string representation for * @returns the Pointer to the Content. Don't mess with it! */ -inline const char *ChrPtr(const StrBuf *Str) -{ +inline const char *ChrPtr(const StrBuf *Str) { if (Str == NULL) return ""; return Str->buf; } -/** - * @ingroup StrBuf_Cast - * @brief since we know strlen()'s result, provide it here. - * @param Str the string to return the length to + +/* + * since we know strlen()'s result, provide it here. + * Str the string to return the length to * @returns contentlength of the buffer */ -inline int StrLength(const StrBuf *Str) -{ +inline int StrLength(const StrBuf *Str) { return (Str != NULL) ? Str->BufUsed : 0; } -/** - * @ingroup StrBuf_DeConstructors - * @brief local utility function to resize the buffer - * @param Buf the buffer whichs storage we should increase - * @param KeepOriginal should we copy the original buffer or just start over with a new one - * @param DestSize what should fit in after? - */ -static int IncreaseBuf(StrBuf *Buf, int KeepOriginal, int DestSize) -{ + +// local utility function to resize the buffer +// Buf the buffer whichs storage we should increase +// KeepOriginal should we copy the original buffer or just start over with a new one +// DestSize what should fit in after? +static int IncreaseBuf(StrBuf *Buf, int KeepOriginal, int DestSize) { char *NewBuf; size_t NewSize = Buf->BufSize * 2; - if (Buf->ConstBuf) + if (Buf->ConstBuf) { return -1; + } - if (DestSize > 0) - while ((NewSize <= DestSize) && (NewSize != 0)) + if (DestSize > 0) { + while ((NewSize <= DestSize) && (NewSize != 0)) { NewSize *= 2; + } + } - if (NewSize == 0) + if (NewSize == 0) { return -1; + } - NewBuf= (char*) malloc(NewSize); - if (NewBuf == NULL) + NewBuf = (char*) malloc(NewSize); + if (NewBuf == NULL) { return -1; + } - if (KeepOriginal && (Buf->BufUsed > 0)) - { + if (KeepOriginal && (Buf->BufUsed > 0)) { memcpy(NewBuf, Buf->buf, Buf->BufUsed); } - else - { + else { NewBuf[0] = '\0'; Buf->BufUsed = 0; } @@ -329,18 +259,13 @@ static int IncreaseBuf(StrBuf *Buf, int KeepOriginal, int DestSize) return Buf->BufSize; } -/** - * @ingroup StrBuf_DeConstructors - * @brief shrink / increase an _EMPTY_ buffer to NewSize. Buffercontent is thoroughly ignored and flushed. - * @param Buf Buffer to shrink (has to be empty) - * @param ThreshHold if the buffer is bigger then this, its readjusted - * @param NewSize if we Shrink it, how big are we going to be afterwards? - */ -void ReAdjustEmptyBuf(StrBuf *Buf, long ThreshHold, long NewSize) -{ - if ((Buf != NULL) && - (Buf->BufUsed == 0) && - (Buf->BufSize < ThreshHold)) { + +// shrink / increase an _EMPTY_ buffer to NewSize. Buffercontent is thoroughly ignored and flushed. +// Buf Buffer to shrink (has to be empty) +// ThreshHold if the buffer is bigger then this, its readjusted +// NewSize if we Shrink it, how big are we going to be afterwards? +void ReAdjustEmptyBuf(StrBuf *Buf, long ThreshHold, long NewSize) { + if ((Buf != NULL) && (Buf->BufUsed == 0) && (Buf->BufSize < ThreshHold)) { free(Buf->buf); Buf->buf = (char*) malloc(NewSize); Buf->BufUsed = 0; @@ -348,20 +273,17 @@ void ReAdjustEmptyBuf(StrBuf *Buf, long ThreshHold, long NewSize) } } -/** - * @ingroup StrBuf_DeConstructors - * @brief shrink long term buffers to their real size so they don't waste memory - * @param Buf buffer to shrink - * @param Force if not set, will just executed if the buffer is much to big; set for lifetime strings + +/* + * shrink long term buffers to their real size so they don't waste memory + * Buf buffer to shrink + * Force if not set, will just executed if the buffer is much to big; set for lifetime strings * @returns physical size of the buffer */ -long StrBufShrinkToFit(StrBuf *Buf, int Force) -{ +long StrBufShrinkToFit(StrBuf *Buf, int Force) { if (Buf == NULL) return -1; - if (Force || - (Buf->BufUsed + (Buf->BufUsed / 3) > Buf->BufSize)) - { + if (Force || (Buf->BufUsed + (Buf->BufUsed / 3) > Buf->BufSize)) { char *TmpBuf; TmpBuf = (char*) malloc(Buf->BufUsed + 1); @@ -376,13 +298,12 @@ long StrBufShrinkToFit(StrBuf *Buf, int Force) return Buf->BufUsed; } -/** - * @ingroup StrBuf_DeConstructors - * @brief Allocate a new buffer with default buffer size + +/* + * Allocate a new buffer with default buffer size * @returns the new stringbuffer */ -StrBuf* NewStrBuf(void) -{ +StrBuf *NewStrBuf(void) { StrBuf *NewBuf; NewBuf = (StrBuf*) malloc(sizeof(StrBuf)); @@ -390,8 +311,7 @@ StrBuf* NewStrBuf(void) return NULL; NewBuf->buf = (char*) malloc(BaseStrBufSize); - if (NewBuf->buf == NULL) - { + if (NewBuf->buf == NULL) { free(NewBuf); return NULL; } @@ -401,18 +321,16 @@ StrBuf* NewStrBuf(void) NewBuf->ConstBuf = 0; dbg_Init (NewBuf); - return NewBuf; } -/** - * @ingroup StrBuf_DeConstructors - * @brief Copy Constructor; returns a duplicate of CopyMe - * @param CopyMe Buffer to faxmilate + +/* + * Copy Constructor; returns a duplicate of CopyMe + * CopyMe Buffer to faxmilate * @returns the new stringbuffer */ -StrBuf* NewStrBufDup(const StrBuf *CopyMe) -{ +StrBuf *NewStrBufDup(const StrBuf *CopyMe) { StrBuf *NewBuf; if (CopyMe == NULL) @@ -423,8 +341,7 @@ StrBuf* NewStrBufDup(const StrBuf *CopyMe) return NULL; NewBuf->buf = (char*) malloc(CopyMe->BufSize); - if (NewBuf->buf == NULL) - { + if (NewBuf->buf == NULL) { free(NewBuf); return NULL; } @@ -439,24 +356,22 @@ StrBuf* NewStrBufDup(const StrBuf *CopyMe) return NewBuf; } -/** - * @ingroup StrBuf_DeConstructors - * @brief Copy Constructor; CreateRelpaceMe will contain CopyFlushMe afterwards. - * @param NoMe if non-NULL, we will use that buffer as value; KeepOriginal will abused as len. - * @param CopyFlushMe Buffer to faxmilate if KeepOriginal, or to move into CreateRelpaceMe if !KeepOriginal. - * @param CreateRelpaceMe If NULL, will be created, else Flushed and filled CopyFlushMe - * @param KeepOriginal should CopyFlushMe remain intact? or may we Steal its buffer? + +/* + * Copy Constructor; CreateRelpaceMe will contain CopyFlushMe afterwards. + * NoMe if non-NULL, we will use that buffer as value; KeepOriginal will abused as len. + * CopyFlushMe Buffer to faxmilate if KeepOriginal, or to move into CreateRelpaceMe if !KeepOriginal. + * CreateRelpaceMe If NULL, will be created, else Flushed and filled CopyFlushMe + * KeepOriginal should CopyFlushMe remain intact? or may we Steal its buffer? * @returns the new stringbuffer */ -void NewStrBufDupAppendFlush(StrBuf **CreateRelpaceMe, StrBuf *CopyFlushMe, const char *NoMe, int KeepOriginal) -{ +void NewStrBufDupAppendFlush(StrBuf **CreateRelpaceMe, StrBuf *CopyFlushMe, const char *NoMe, int KeepOriginal) { StrBuf *NewBuf; if (CreateRelpaceMe == NULL) return; - if (NoMe != NULL) - { + if (NoMe != NULL) { if (*CreateRelpaceMe != NULL) StrBufPlain(*CreateRelpaceMe, NoMe, KeepOriginal); else @@ -464,8 +379,7 @@ void NewStrBufDupAppendFlush(StrBuf **CreateRelpaceMe, StrBuf *CopyFlushMe, cons return; } - if (CopyFlushMe == NULL) - { + if (CopyFlushMe == NULL) { if (*CreateRelpaceMe != NULL) FlushStrBuf(*CreateRelpaceMe); else @@ -478,47 +392,43 @@ void NewStrBufDupAppendFlush(StrBuf **CreateRelpaceMe, StrBuf *CopyFlushMe, cons * else *CreateRelpaceMe may use more memory than needed in a longer term, CopyFlushMe might * be a big IO-Buffer... */ - if (KeepOriginal || (StrLength(CopyFlushMe) < 256)) - { - if (*CreateRelpaceMe == NULL) - { + if (KeepOriginal || (StrLength(CopyFlushMe) < 256)) { + if (*CreateRelpaceMe == NULL) { *CreateRelpaceMe = NewBuf = NewStrBufPlain(NULL, CopyFlushMe->BufUsed); dbg_Init(NewBuf); } - else - { + else { NewBuf = *CreateRelpaceMe; FlushStrBuf(NewBuf); } StrBufAppendBuf(NewBuf, CopyFlushMe, 0); } - else - { - if (*CreateRelpaceMe == NULL) - { + else { + if (*CreateRelpaceMe == NULL) { *CreateRelpaceMe = NewBuf = NewStrBufPlain(NULL, CopyFlushMe->BufUsed); dbg_Init(NewBuf); } - else + else { NewBuf = *CreateRelpaceMe; - SwapBuffers (NewBuf, CopyFlushMe); + } + iSwapBuffers (NewBuf, CopyFlushMe); } - if (!KeepOriginal) + if (!KeepOriginal) { FlushStrBuf(CopyFlushMe); + } return; } -/** - * @ingroup StrBuf_DeConstructors - * @brief create a new Buffer using an existing c-string + +/* + * create a new Buffer using an existing c-string * this function should also be used if you want to pre-suggest * the buffer size to allocate in conjunction with ptr == NULL - * @param ptr the c-string to copy; may be NULL to create a blank instance - * @param nChars How many chars should we copy; -1 if we should measure the length ourselves + * ptr the c-string to copy; may be NULL to create a blank instance + * nChars How many chars should we copy; -1 if we should measure the length ourselves * @returns the new stringbuffer */ -StrBuf* NewStrBufPlain(const char* ptr, int nChars) -{ +StrBuf *NewStrBufPlain(const char* ptr, int nChars) { StrBuf *NewBuf; size_t Siz = BaseStrBufSize; size_t CopySize; @@ -535,15 +445,13 @@ StrBuf* NewStrBufPlain(const char* ptr, int nChars) while ((Siz <= CopySize) && (Siz != 0)) Siz *= 2; - if (Siz == 0) - { + if (Siz == 0) { free(NewBuf); return NULL; } NewBuf->buf = (char*) malloc(Siz); - if (NewBuf->buf == NULL) - { + if (NewBuf->buf == NULL) { free(NewBuf); return NULL; } @@ -564,16 +472,15 @@ StrBuf* NewStrBufPlain(const char* ptr, int nChars) return NewBuf; } -/** - * @ingroup StrBuf_DeConstructors - * @brief Set an existing buffer from a c-string - * @param Buf buffer to load - * @param ptr c-string to put into - * @param nChars set to -1 if we should work 0-terminated + +/* + * Set an existing buffer from a c-string + * Buf buffer to load + * ptr c-string to put into + * nChars set to -1 if we should work 0-terminated * @returns the new length of the string */ -int StrBufPlain(StrBuf *Buf, const char* ptr, int nChars) -{ +int StrBufPlain(StrBuf *Buf, const char* ptr, int nChars) { size_t Siz; size_t CopySize; @@ -609,11 +516,10 @@ int StrBufPlain(StrBuf *Buf, const char* ptr, int nChars) } -/** - * @ingroup StrBuf_DeConstructors - * @brief use strbuf as wrapper for a string constant for easy handling - * @param StringConstant a string to wrap - * @param SizeOfStrConstant should be sizeof(StringConstant)-1 +/* + * use strbuf as wrapper for a string constant for easy handling + * StringConstant a string to wrap + * SizeOfStrConstant should be sizeof(StringConstant)-1 */ StrBuf* _NewConstStrBuf(const char* StringConstant, size_t SizeOfStrConstant) { @@ -633,10 +539,9 @@ StrBuf* _NewConstStrBuf(const char* StringConstant, size_t SizeOfStrConstant) } -/** - * @ingroup StrBuf_DeConstructors - * @brief flush the content of a Buf; keep its struct - * @param buf Buffer to flush +/* + * flush the content of a Buf; keep its struct + * buf Buffer to flush */ int FlushStrBuf(StrBuf *buf) { @@ -649,10 +554,9 @@ int FlushStrBuf(StrBuf *buf) return 0; } -/** - * @ingroup StrBuf_DeConstructors - * @brief wipe the content of a Buf thoroughly (overwrite it -> expensive); keep its struct - * @param buf Buffer to wipe +/* + * wipe the content of a Buf thoroughly (overwrite it -> expensive); keep its struct + * buf Buffer to wipe */ int FLUSHStrBuf(StrBuf *buf) { @@ -670,12 +574,11 @@ int FLUSHStrBuf(StrBuf *buf) #ifdef SIZE_DEBUG int hFreeDbglog = -1; #endif -/** - * @ingroup StrBuf_DeConstructors - * @brief Release a Buffer +/* + * Release a Buffer * Its a double pointer, so it can NULL your pointer * so fancy SIG11 appear instead of random results - * @param FreeMe Pointer Pointer to the buffer to free + * FreeMe Pointer Pointer to the buffer to free */ void FreeStrBuf (StrBuf **FreeMe) { @@ -690,17 +593,15 @@ void FreeStrBuf (StrBuf **FreeMe) *FreeMe = NULL; } -/** - * @ingroup StrBuf_DeConstructors - * @brief flatten a Buffer to the Char * we return +/* + * flatten a Buffer to the Char * we return * Its a double pointer, so it can NULL your pointer * so fancy SIG11 appear instead of random results * The Callee then owns the buffer and is responsible for freeing it. - * @param SmashMe Pointer Pointer to the buffer to release Buf from and free + * SmashMe Pointer Pointer to the buffer to release Buf from and free * @returns the pointer of the buffer; Callee owns the memory thereafter. */ -char *SmashStrBuf (StrBuf **SmashMe) -{ +char *SmashStrBuf (StrBuf **SmashMe) { char *Ret; if ((SmashMe == NULL) || (*SmashMe == NULL)) @@ -714,14 +615,13 @@ char *SmashStrBuf (StrBuf **SmashMe) return Ret; } -/** - * @ingroup StrBuf_DeConstructors - * @brief Release the buffer + +/* + * Release the buffer * If you want put your StrBuf into a Hash, use this as Destructor. - * @param VFreeMe untyped pointer to a StrBuf. be shure to do the right thing [TM] + * VFreeMe untyped pointer to a StrBuf. be shure to do the right thing [TM] */ -void HFreeStrBuf (void *VFreeMe) -{ +void HFreeStrBuf (void *VFreeMe) { StrBuf *FreeMe = (StrBuf*)VFreeMe; if (FreeMe == NULL) return; @@ -738,9 +638,8 @@ void HFreeStrBuf (void *VFreeMe) * Simple string transformations * *******************************************************************************/ -/** - * @ingroup StrBuf - * @brief Wrapper around atol +/* + * Wrapper around atol */ long StrTol(const StrBuf *Buf) { @@ -752,9 +651,8 @@ long StrTol(const StrBuf *Buf) return 0; } -/** - * @ingroup StrBuf - * @brief Wrapper around atoi +/* + * Wrapper around atoi */ int StrToi(const StrBuf *Buf) { @@ -766,10 +664,9 @@ int StrToi(const StrBuf *Buf) return 0; } -/** - * @ingroup StrBuf - * @brief Checks to see if the string is a pure number - * @param Buf The buffer to inspect +/* + * Checks to see if the string is a pure number + * Buf The buffer to inspect * @returns 1 if its a pure number, 0, if not. */ int StrBufIsNumber(const StrBuf *Buf) { @@ -788,13 +685,12 @@ int StrBufIsNumber(const StrBuf *Buf) { } /** - * @ingroup StrBuf_Filler - * @brief modifies a Single char of the Buf + * modifies a Single char of the Buf * You can point to it via char* or a zero-based integer - * @param Buf The buffer to manipulate - * @param ptr char* to zero; use NULL if unused - * @param nThChar zero based pointer into the string; use -1 if unused - * @param PeekValue The Character to place into the position + * Buf The buffer to manipulate + * ptr char* to zero; use NULL if unused + * nThChar zero based pointer into the string; use -1 if unused + * PeekValue The Character to place into the position */ long StrBufPeek(StrBuf *Buf, const char* ptr, long nThChar, char PeekValue) { @@ -809,14 +705,13 @@ long StrBufPeek(StrBuf *Buf, const char* ptr, long nThChar, char PeekValue) } /** - * @ingroup StrBuf_Filler - * @brief modifies a range of chars of the Buf + * modifies a range of chars of the Buf * You can point to it via char* or a zero-based integer - * @param Buf The buffer to manipulate - * @param ptr char* to zero; use NULL if unused - * @param nThChar zero based pointer into the string; use -1 if unused - * @param nChars how many chars are to be flushed? - * @param PookValue The Character to place into that area + * Buf The buffer to manipulate + * ptr char* to zero; use NULL if unused + * nThChar zero based pointer into the string; use -1 if unused + * nChars how many chars are to be flushed? + * PookValue The Character to place into that area */ long StrBufPook(StrBuf *Buf, const char* ptr, long nThChar, long nChars, char PookValue) { @@ -836,11 +731,10 @@ long StrBufPook(StrBuf *Buf, const char* ptr, long nThChar, long nChars, char Po } /** - * @ingroup StrBuf_Filler - * @brief Append a StringBuffer to the buffer - * @param Buf Buffer to modify - * @param AppendBuf Buffer to copy at the end of our buffer - * @param Offset Should we start copying from an offset? + * Append a StringBuffer to the buffer + * Buf Buffer to modify + * AppendBuf Buffer to copy at the end of our buffer + * Offset Should we start copying from an offset? */ void StrBufAppendBuf(StrBuf *Buf, const StrBuf *AppendBuf, unsigned long Offset) { @@ -849,42 +743,37 @@ void StrBufAppendBuf(StrBuf *Buf, const StrBuf *AppendBuf, unsigned long Offset) return; if (Buf->BufSize - Offset < AppendBuf->BufUsed + Buf->BufUsed + 1) - IncreaseBuf(Buf, - (Buf->BufUsed > 0), - AppendBuf->BufUsed + Buf->BufUsed); + IncreaseBuf(Buf, (Buf->BufUsed > 0), AppendBuf->BufUsed + Buf->BufUsed); - memcpy(Buf->buf + Buf->BufUsed, - AppendBuf->buf + Offset, - AppendBuf->BufUsed - Offset); + memcpy(Buf->buf + Buf->BufUsed, AppendBuf->buf + Offset, AppendBuf->BufUsed - Offset); Buf->BufUsed += AppendBuf->BufUsed - Offset; Buf->buf[Buf->BufUsed] = '\0'; } -/** - * @ingroup StrBuf_Filler - * @brief Append a C-String to the buffer - * @param Buf Buffer to modify - * @param AppendBuf Buffer to copy at the end of our buffer - * @param AppendSize number of bytes to copy; set to -1 if we should count it in advance - * @param Offset Should we start copying from an offset? - */ -void StrBufAppendBufPlain(StrBuf *Buf, const char *AppendBuf, long AppendSize, unsigned long Offset) -{ +// Append a C-String to the buffer +// Buf Buffer to modify +// AppendBuf Buffer to copy at the end of our buffer +// AppendSize number of bytes to copy; set to -1 if we should count it in advance +// Offset Should we start copying from an offset? +void StrBufAppendBufPlain(StrBuf *Buf, const char *AppendBuf, long AppendSize, unsigned long Offset) { long aps; long BufSizeRequired; if ((AppendBuf == NULL) || (Buf == NULL)) return; - if (AppendSize < 0 ) + if (AppendSize < 0) { aps = strlen(AppendBuf + Offset); - else + } + else { aps = AppendSize - Offset; + } BufSizeRequired = Buf->BufUsed + aps + 1; - if (Buf->BufSize <= BufSizeRequired) + if (Buf->BufSize <= BufSizeRequired) { IncreaseBuf(Buf, (Buf->BufUsed > 0), BufSizeRequired); + } memcpy(Buf->buf + Buf->BufUsed, AppendBuf + Offset, @@ -893,13 +782,12 @@ void StrBufAppendBufPlain(StrBuf *Buf, const char *AppendBuf, long AppendSize, u Buf->buf[Buf->BufUsed] = '\0'; } -/** - * @ingroup StrBuf_Filler - * @brief sprintf like function appending the formated string to the buffer +/* + * sprintf like function appending the formated string to the buffer * vsnprintf version to wrap into own calls - * @param Buf Buffer to extend by format and Params - * @param format printf alike format to add - * @param ap va_list containing the items for format + * Buf Buffer to extend by format and Params + * format printf alike format to add + * ap va_list containing the items for format */ void StrBufVAppendPrintf(StrBuf *Buf, const char *format, va_list ap) { @@ -938,10 +826,9 @@ void StrBufVAppendPrintf(StrBuf *Buf, const char *format, va_list ap) } /** - * @ingroup StrBuf_Filler - * @brief sprintf like function appending the formated string to the buffer - * @param Buf Buffer to extend by format and Params - * @param format printf alike format to add + * sprintf like function appending the formated string to the buffer + * Buf Buffer to extend by format and Params + * format printf alike format to add */ void StrBufAppendPrintf(StrBuf *Buf, const char *format, ...) { @@ -980,10 +867,9 @@ void StrBufAppendPrintf(StrBuf *Buf, const char *format, ...) } /** - * @ingroup StrBuf_Filler - * @brief sprintf like function putting the formated string into the buffer - * @param Buf Buffer to extend by format and Parameters - * @param format printf alike format to add + * sprintf like function putting the formated string into the buffer + * Buf Buffer to extend by format and Parameters + * format printf alike format to add */ void StrBufPrintf(StrBuf *Buf, const char *format, ...) { @@ -1009,12 +895,11 @@ void StrBufPrintf(StrBuf *Buf, const char *format, ...) } /** - * @ingroup StrBuf_Filler - * @brief Callback for cURL to append the webserver reply to a buffer - * @param ptr pre-defined by the cURL API; see man 3 curl for mre info - * @param size pre-defined by the cURL API; see man 3 curl for mre info - * @param nmemb pre-defined by the cURL API; see man 3 curl for mre info - * @param stream pre-defined by the cURL API; see man 3 curl for mre info + * Callback for cURL to append the webserver reply to a buffer + * ptr pre-defined by the cURL API; see man 3 curl for mre info + * size pre-defined by the cURL API; see man 3 curl for mre info + * nmemb pre-defined by the cURL API; see man 3 curl for mre info + * stream pre-defined by the cURL API; see man 3 curl for mre info */ size_t CurlFillStrBuf_callback(void *ptr, size_t size, size_t nmemb, void *stream) { @@ -1031,12 +916,11 @@ size_t CurlFillStrBuf_callback(void *ptr, size_t size, size_t nmemb, void *strea /** - * @ingroup StrBuf - * @brief extracts a substring from Source into dest - * @param dest buffer to place substring into - * @param Source string to copy substring from - * @param Offset chars to skip from start - * @param nChars number of chars to copy + * extracts a substring from Source into dest + * dest buffer to place substring into + * Source string to copy substring from + * Offset chars to skip from start + * nChars number of chars to copy * @returns the number of chars copied; may be different from nChars due to the size of Source */ int StrBufSub(StrBuf *dest, const StrBuf *Source, unsigned long Offset, size_t nChars) @@ -1069,10 +953,9 @@ int StrBufSub(StrBuf *dest, const StrBuf *Source, unsigned long Offset, size_t n } /** - * @ingroup StrBuf - * @brief Cut nChars from the start of the string - * @param Buf Buffer to modify - * @param nChars how many chars should be skipped? + * Cut nChars from the start of the string + * Buf Buffer to modify + * nChars how many chars should be skipped? */ void StrBufCutLeft(StrBuf *Buf, int nChars) { @@ -1087,10 +970,9 @@ void StrBufCutLeft(StrBuf *Buf, int nChars) } /** - * @ingroup StrBuf - * @brief Cut the trailing n Chars from the string - * @param Buf Buffer to modify - * @param nChars how many chars should be trunkated? + * Cut the trailing n Chars from the string + * Buf Buffer to modify + * nChars how many chars should be trunkated? */ void StrBufCutRight(StrBuf *Buf, int nChars) { @@ -1106,11 +988,10 @@ void StrBufCutRight(StrBuf *Buf, int nChars) } /** - * @ingroup StrBuf - * @brief Cut the string after n Chars - * @param Buf Buffer to modify - * @param AfternChars after how many chars should we trunkate the string? - * @param At if non-null and points inside of our string, cut it there. + * Cut the string after n Chars + * Buf Buffer to modify + * AfternChars after how many chars should we trunkate the string? + * At if non-null and points inside of our string, cut it there. */ void StrBufCutAt(StrBuf *Buf, int AfternChars, const char *At) { @@ -1127,9 +1008,8 @@ void StrBufCutAt(StrBuf *Buf, int AfternChars, const char *At) /** - * @ingroup StrBuf - * @brief Strip leading and trailing spaces from a string; with premeasured and adjusted length. - * @param Buf the string to modify + * Strip leading and trailing spaces from a string; with premeasured and adjusted length. + * Buf the string to modify */ void StrBufTrim(StrBuf *Buf) { @@ -1151,9 +1031,8 @@ void StrBufTrim(StrBuf *Buf) if (delta > 0) StrBufCutLeft(Buf, delta); } /** - * @ingroup StrBuf - * @brief changes all spaces in the string (tab, linefeed...) to Blank (0x20) - * @param Buf the string to modify + * changes all spaces in the string (tab, linefeed...) to Blank (0x20) + * Buf the string to modify */ void StrBufSpaceToBlank(StrBuf *Buf) { @@ -1177,7 +1056,6 @@ void StrBufStripAllBut(StrBuf *Buf, char leftboundary, char rightboundary) const char *pRight; if ((Buf == NULL) || (Buf->buf == NULL)) { - StrBufCutAt(Buf, 0, Buf->buf); return; } @@ -1185,26 +1063,17 @@ void StrBufStripAllBut(StrBuf *Buf, char leftboundary, char rightboundary) if (pRight != NULL) { StrBufCutAt(Buf, 0, pRight); } - else { - StrBufCutAt(Buf, 0, Buf->buf); - return; - } pLeft = strrchr(ChrPtr(Buf), leftboundary); if (pLeft != NULL) { StrBufCutLeft(Buf, pLeft - Buf->buf + 1); } - else { - StrBufCutAt(Buf, 0, Buf->buf); - return; - } } /** - * @ingroup StrBuf_Filler - * @brief uppercase the contents of a buffer - * @param Buf the buffer to translate + * uppercase the contents of a buffer + * Buf the buffer to translate */ void StrBufUpCase(StrBuf *Buf) { @@ -1222,9 +1091,8 @@ void StrBufUpCase(StrBuf *Buf) /** - * @ingroup StrBuf_Filler - * @brief lowercase the contents of a buffer - * @param Buf the buffer to translate + * lowercase the contents of a buffer + * Buf the buffer to translate */ void StrBufLowerCase(StrBuf *Buf) { @@ -1246,13 +1114,12 @@ void StrBufLowerCase(StrBuf *Buf) *******************************************************************************/ /** - * @ingroup StrBuf_Tokenizer - * @brief Replace a token at a given place with a given length by another token with given length - * @param Buf String where to work on - * @param where where inside of the Buf is the search-token - * @param HowLong How long is the token to be replaced - * @param Repl Token to insert at 'where' - * @param ReplLen Length of repl + * Replace a token at a given place with a given length by another token with given length + * Buf String where to work on + * where where inside of the Buf is the search-token + * HowLong How long is the token to be replaced + * Repl Token to insert at 'where' + * ReplLen Length of repl * @returns -1 if fail else length of resulting Buf */ int StrBufReplaceToken(StrBuf *Buf, long where, long HowLong, @@ -1281,10 +1148,9 @@ int StrBufReplaceToken(StrBuf *Buf, long where, long HowLong, } /** - * @ingroup StrBuf_Tokenizer - * @brief Counts the numbmer of tokens in a buffer - * @param source String to count tokens in - * @param tok Tokenizer char to count + * Counts the numbmer of tokens in a buffer + * source String to count tokens in + * tok Tokenizer char to count * @returns numbers of tokenizer chars found */ int StrBufNum_tokens(const StrBuf *source, char tok) @@ -1308,11 +1174,10 @@ int StrBufNum_tokens(const StrBuf *source, char tok) } /** - * @ingroup StrBuf_Tokenizer - * @brief a string tokenizer - * @param Source StringBuffer to read into - * @param parmnum n'th Parameter to remove - * @param separator tokenizer character + * a string tokenizer + * Source StringBuffer to read into + * parmnum n'th Parameter to remove + * separator tokenizer character * @returns -1 if not found, else length of token. */ int StrBufRemove_token(StrBuf *Source, int parmnum, char separator) @@ -1321,7 +1186,7 @@ int StrBufRemove_token(StrBuf *Source, int parmnum, char separator) char *d, *s, *end; /* dest, source */ int count = 0; - /* Find desired @parameter */ + /* Find desired eter */ end = Source->buf + Source->BufUsed; d = Source->buf; while ((d <= end) && @@ -1340,7 +1205,7 @@ int StrBufRemove_token(StrBuf *Source, int parmnum, char separator) if ((d == NULL) || (d >= end)) return 0; /* @Parameter not found */ - /* Find next @parameter */ + /* Find next eter */ s = d; while ((s <= end) && (*s && *s != separator)) @@ -1396,12 +1261,11 @@ int StrBufExtract_tokenFromStr(StrBuf *dest, const char *Source, long SourceLen, } /** - * @ingroup StrBuf_Tokenizer - * @brief a string tokenizer - * @param dest Destination StringBuffer - * @param Source StringBuffer to read into - * @param parmnum n'th Parameter to extract - * @param separator tokenizer character + * a string tokenizer + * dest Destination StringBuffer + * Source StringBuffer to read into + * parmnum n'th Parameter to extract + * separator tokenizer character * @returns -1 if not found, else length of token. */ int StrBufExtract_token(StrBuf *dest, const StrBuf *Source, int parmnum, char separator) @@ -1464,11 +1328,10 @@ int StrBufExtract_token(StrBuf *dest, const StrBuf *Source, int parmnum, char se /** - * @ingroup StrBuf_Tokenizer - * @brief a string tokenizer to fetch an integer - * @param Source String containing tokens - * @param parmnum n'th Parameter to extract - * @param separator tokenizer character + * a string tokenizer to fetch an integer + * Source String containing tokens + * parmnum n'th Parameter to extract + * separator tokenizer character * @returns 0 if not found, else integer representation of the token */ int StrBufExtract_int(const StrBuf* Source, int parmnum, char separator) @@ -1488,11 +1351,10 @@ int StrBufExtract_int(const StrBuf* Source, int parmnum, char separator) } /** - * @ingroup StrBuf_Tokenizer - * @brief a string tokenizer to fetch a long integer - * @param Source String containing tokens - * @param parmnum n'th Parameter to extract - * @param separator tokenizer character + * a string tokenizer to fetch a long integer + * Source String containing tokens + * parmnum n'th Parameter to extract + * separator tokenizer character * @returns 0 if not found, else long integer representation of the token */ long StrBufExtract_long(const StrBuf* Source, int parmnum, char separator) @@ -1513,11 +1375,10 @@ long StrBufExtract_long(const StrBuf* Source, int parmnum, char separator) /** - * @ingroup StrBuf_Tokenizer - * @brief a string tokenizer to fetch an unsigned long - * @param Source String containing tokens - * @param parmnum n'th Parameter to extract - * @param separator tokenizer character + * a string tokenizer to fetch an unsigned long + * Source String containing tokens + * parmnum n'th Parameter to extract + * separator tokenizer character * @returns 0 if not found, else unsigned long representation of the token */ unsigned long StrBufExtract_unsigned_long(const StrBuf* Source, int parmnum, char separator) @@ -1544,11 +1405,10 @@ unsigned long StrBufExtract_unsigned_long(const StrBuf* Source, int parmnum, cha /** - * @ingroup StrBuf_NextTokenizer - * @brief a string tokenizer; Bounds checker + * a string tokenizer; Bounds checker * function to make shure whether StrBufExtract_NextToken and friends have reached the end of the string. - * @param Source our tokenbuffer - * @param pStart the token iterator pointer to inspect + * Source our tokenbuffer + * pStart the token iterator pointer to inspect * @returns whether the revolving pointer is inside of the search range */ int StrBufHaveNextToken(const StrBuf *Source, const char **pStart) @@ -1576,12 +1436,11 @@ int StrBufHaveNextToken(const StrBuf *Source, const char **pStart) } /** - * @ingroup StrBuf_NextTokenizer - * @brief a string tokenizer - * @param dest Destination StringBuffer - * @param Source StringBuffer to read into - * @param pStart pointer to the end of the last token. Feed with NULL on start. - * @param separator tokenizer + * a string tokenizer + * dest Destination StringBuffer + * Source StringBuffer to read into + * pStart pointer to the end of the last token. Feed with NULL on start. + * separator tokenizer * @returns -1 if not found, else length of token. */ int StrBufExtract_NextToken(StrBuf *dest, const StrBuf *Source, const char **pStart, char separator) @@ -1676,12 +1535,11 @@ int StrBufExtract_NextToken(StrBuf *dest, const StrBuf *Source, const char **pSt /** - * @ingroup StrBuf_NextTokenizer - * @brief a string tokenizer - * @param Source StringBuffer to read from - * @param pStart pointer to the end of the last token. Feed with NULL. - * @param separator tokenizer character - * @param nTokens number of tokens to fastforward over + * a string tokenizer + * Source StringBuffer to read from + * pStart pointer to the end of the last token. Feed with NULL. + * separator tokenizer character + * nTokens number of tokens to fastforward over * @returns -1 if not found, else length of token. */ int StrBufSkip_NTokenS(const StrBuf *Source, const char **pStart, char separator, int nTokens) @@ -1729,11 +1587,10 @@ int StrBufSkip_NTokenS(const StrBuf *Source, const char **pStart, char separator } /** - * @ingroup StrBuf_NextTokenizer - * @brief a string tokenizer to fetch an integer - * @param Source StringBuffer to read from - * @param pStart Cursor on the tokenstring - * @param separator tokenizer character + * a string tokenizer to fetch an integer + * Source StringBuffer to read from + * pStart Cursor on the tokenstring + * separator tokenizer character * @returns 0 if not found, else integer representation of the token */ int StrBufExtractNext_int(const StrBuf* Source, const char **pStart, char separator) @@ -1753,11 +1610,10 @@ int StrBufExtractNext_int(const StrBuf* Source, const char **pStart, char separa } /** - * @ingroup StrBuf_NextTokenizer - * @brief a string tokenizer to fetch a long integer - * @param Source StringBuffer to read from - * @param pStart Cursor on the tokenstring - * @param separator tokenizer character + * a string tokenizer to fetch a long integer + * Source StringBuffer to read from + * pStart Cursor on the tokenstring + * separator tokenizer character * @returns 0 if not found, else long integer representation of the token */ long StrBufExtractNext_long(const StrBuf* Source, const char **pStart, char separator) @@ -1778,11 +1634,10 @@ long StrBufExtractNext_long(const StrBuf* Source, const char **pStart, char sepa /** - * @ingroup StrBuf_NextTokenizer - * @brief a string tokenizer to fetch an unsigned long - * @param Source StringBuffer to read from - * @param pStart Cursor on the tokenstring - * @param separator tokenizer character + * a string tokenizer to fetch an unsigned long + * Source StringBuffer to read from + * pStart Cursor on the tokenstring + * separator tokenizer character * @returns 0 if not found, else unsigned long representation of the token */ unsigned long StrBufExtractNext_unsigned_long(const StrBuf* Source, const char **pStart, char separator) @@ -1815,11 +1670,10 @@ unsigned long StrBufExtractNext_unsigned_long(const StrBuf* Source, const char * *******************************************************************************/ /** - * @ingroup StrBuf_DeEnCoder - * @brief Escape a string for feeding out as a URL while appending it to a Buffer - * @param OutBuf the output buffer - * @param In Buffer to encode - * @param PlainIn way in from plain old c strings + * Escape a string for feeding out as a URL while appending it to a Buffer + * OutBuf the output buffer + * In Buffer to encode + * PlainIn way in from plain old c strings */ void StrBufUrlescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn) { @@ -1874,15 +1728,14 @@ void StrBufUrlescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn) *pt = '\0'; } -/** - * @ingroup StrBuf_DeEnCoder - * @brief Escape a string for feeding out as a the username/password part of an URL while appending it to a Buffer - * @param OutBuf the output buffer - * @param In Buffer to encode - * @param PlainIn way in from plain old c strings + +/* + * Escape a string for feeding out as a the username/password part of an URL while appending it to a Buffer + * OutBuf the output buffer + * In Buffer to encode + * PlainIn way in from plain old c strings */ -void StrBufUrlescUPAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn) -{ +void StrBufUrlescUPAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn) { const char *pch, *pche; char *pt, *pte; int len; @@ -1934,13 +1787,115 @@ void StrBufUrlescUPAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn) *pt = '\0'; } +/* + * append a string with characters having a special meaning in xml encoded to the buffer + * OutBuf the output buffer + * In Buffer to encode + * PlainIn way in from plain old c strings + * PlainInLen way in from plain old c strings; maybe you've got binary data or know the length? + * OverrideLowChars should chars < 0x20 be replaced by _ or escaped as xml entity? + */ +void StrBufXMLEscAppend(StrBuf *OutBuf, + const StrBuf *In, + const char *PlainIn, + long PlainInLen, + int OverrideLowChars) +{ + const char *pch, *pche; + char *pt, *pte; + int IsUtf8Sequence; + int len; + + if (((In == NULL) && (PlainIn == NULL)) || (OutBuf == NULL) ) + return; + if (PlainIn != NULL) { + if (PlainInLen < 0) + len = strlen((const char*)PlainIn); + else + len = PlainInLen; + pch = PlainIn; + pche = pch + len; + } + else { + pch = (const char*)In->buf; + pche = pch + In->BufUsed; + len = In->BufUsed; + } + + if (len == 0) + return; + + pt = OutBuf->buf + OutBuf->BufUsed; + /**< we max append 6 chars at once plus the \0 */ + pte = OutBuf->buf + OutBuf->BufSize - 6; + + while (pch < pche) { + if (pt >= pte) { + OutBuf->BufUsed = pt - OutBuf->buf; + IncreaseBuf(OutBuf, 1, -1); + pte = OutBuf->buf + OutBuf->BufSize - 6; + /**< we max append 3 chars at once plus the \0 */ + + pt = OutBuf->buf + OutBuf->BufUsed; + } + + if (*pch == '<') { + memcpy(pt, HKEY("<")); + pt += 4; + pch ++; + } + else if (*pch == '>') { + memcpy(pt, HKEY(">")); + pt += 4; + pch ++; + } + else if (*pch == '&') { + memcpy(pt, HKEY("&")); + pt += 5; + pch++; + } + else if ((*pch >= 0x20) && (*pch <= 0x7F)) { + *pt = *pch; + pt++; pch++; + } + else { + IsUtf8Sequence = Ctdl_GetUtf8SequenceLength(pch, pche); + if (IsUtf8Sequence) + { + while ((IsUtf8Sequence > 0) && + (pch < pche)) + { + *pt = *pch; + pt ++; + pch ++; + --IsUtf8Sequence; + } + } + else + { + *pt = '&'; + pt++; + *pt = HexList[*(unsigned char*)pch][0]; + pt ++; + *pt = HexList[*(unsigned char*)pch][1]; + pt ++; pch ++; + *pt = '&'; + pt++; + pch ++; + } + } + } + *pt = '\0'; + OutBuf->BufUsed = pt - OutBuf->buf; +} + + /** - * @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 - * @param PlainInLen way in from plain old c strings; maybe you've got binary data or know the length? + * append a string in hex encoding to the buffer + * OutBuf the output buffer + * In Buffer to encode + * PlainIn way in from plain old c strings + * 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 unsigned char *PlainIn, long PlainInLen) { @@ -1985,8 +1940,8 @@ void StrBufHexEscAppend(StrBuf *OutBuf, const StrBuf *In, const unsigned char *P *pt = '\0'; } -void StrBufBase64Append(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn, long PlainInLen, int linebreaks) -{ + +void StrBufBase64Append(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn, long PlainInLen, int linebreaks) { const char *pch; char *pt; int len; @@ -2024,27 +1979,23 @@ void StrBufBase64Append(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn, l *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) -{ + +// append a string in hex encoding to the buffer +// OutBuf the output buffer +// In Buffer to encode +// 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. +/* + * Append a string, escaping characters which have meaning in HTML. * - * @param Target target buffer - * @param Source source buffer; set to NULL if you just have a C-String - * @param PlainIn Plain-C string to append; set to NULL if unused - * @param nbsp If nonzero, spaces are converted to non-breaking spaces. - * @param nolinebreaks if set to 1, linebreaks are removed from the string. + * Target target buffer + * Source source buffer; set to NULL if you just have a C-String + * PlainIn Plain-C string to append; set to NULL if unused + * nbsp If nonzero, spaces are converted to non-breaking spaces. + * nolinebreaks if set to 1, linebreaks are removed from the string. * if set to 2, linebreaks are replaced by <br/> */ long StrEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn, int nbsp, int nolinebreaks) @@ -2151,12 +2102,11 @@ long StrEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn, int } /** - * @ingroup StrBuf_DeEnCoder - * @brief Append a string, escaping characters which have meaning in HTML. + * Append a string, escaping characters which have meaning in HTML. * Converts linebreaks into blanks; escapes single quotes - * @param Target target buffer - * @param Source source buffer; set to NULL if you just have a C-String - * @param PlainIn Plain-C string to append; set to NULL if unused + * Target target buffer + * Source source buffer; set to NULL if you just have a C-String + * PlainIn Plain-C string to append; set to NULL if unused */ void StrMsgEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn) { @@ -2218,12 +2168,11 @@ void StrMsgEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn) /** - * @ingroup StrBuf_DeEnCoder - * @brief Append a string, escaping characters which have meaning in ICAL. + * Append a string, escaping characters which have meaning in ICAL. * [\n,] - * @param Target target buffer - * @param Source source buffer; set to NULL if you just have a C-String - * @param PlainIn Plain-C string to append; set to NULL if unused + * Target target buffer + * Source source buffer; set to NULL if you just have a C-String + * PlainIn Plain-C string to append; set to NULL if unused */ void StrIcalEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn) { @@ -2288,12 +2237,11 @@ void StrIcalEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn) } /** - * @ingroup StrBuf_DeEnCoder - * @brief Append a string, escaping characters which have meaning in JavaScript strings . + * Append a string, escaping characters which have meaning in JavaScript strings . * - * @param Target target buffer - * @param Source source buffer; set to NULL if you just have a C-String - * @param PlainIn Plain-C string to append; set to NULL if unused + * Target target buffer + * Source source buffer; set to NULL if you just have a C-String + * PlainIn Plain-C string to append; set to NULL if unused * @returns size of result or -1 */ long StrECMAEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn) @@ -2408,14 +2356,13 @@ long StrECMAEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn) } /** - * @ingroup StrBuf_DeEnCoder - * @brief Append a string, escaping characters which have meaning in HTML + json. + * Append a string, escaping characters which have meaning in HTML + json. * - * @param Target target buffer - * @param Source source buffer; set to NULL if you just have a C-String - * @param PlainIn Plain-C string to append; set to NULL if unused - * @param nbsp If nonzero, spaces are converted to non-breaking spaces. - * @param nolinebreaks if set to 1, linebreaks are removed from the string. + * Target target buffer + * Source source buffer; set to NULL if you just have a C-String + * PlainIn Plain-C string to append; set to NULL if unused + * nbsp If nonzero, spaces are converted to non-breaking spaces. + * nolinebreaks if set to 1, linebreaks are removed from the string. * if set to 2, linebreaks are replaced by <br/> */ long StrHtmlEcmaEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn, int nbsp, int nolinebreaks) @@ -2582,14 +2529,12 @@ long StrHtmlEcmaEscAppend(StrBuf *Target, const StrBuf *Source, const char *Plai } -/** - * @ingroup StrBuf_DeEnCoder - * @brief replace all non-Ascii characters by another - * @param Buf buffer to inspect - * @param repl charater to stamp over non ascii chars +/* + * replace all non-Ascii characters by another + * Buf buffer to inspect + * repl charater to stamp over non ascii chars */ -void StrBufAsciify(StrBuf *Buf, const char repl) -{ +void StrBufAsciify(StrBuf *Buf, const char repl) { long offset; for (offset = 0; offset < Buf->BufUsed; offset ++) @@ -2598,19 +2543,16 @@ void StrBufAsciify(StrBuf *Buf, const char repl) } -/** - * @ingroup StrBuf_DeEnCoder - * @brief unhide special chars hidden to the HTML escaper - * @param target buffer to put the unescaped string in - * @param source buffer to unescape +/* + * unhide special chars hidden to the HTML escaper + * target buffer to put the unescaped string in + * source buffer to unescape */ -void StrBufEUid_unescapize(StrBuf *target, const StrBuf *source) -{ +void StrBufEUid_unescapize(StrBuf *target, const StrBuf *source) { int a, b, len; char hex[3]; - if ((source == NULL) || (target == NULL) || (target->buf == NULL)) - { + if ((source == NULL) || (target == NULL) || (target->buf == NULL)) { return; } @@ -2640,14 +2582,12 @@ void StrBufEUid_unescapize(StrBuf *target, const StrBuf *source) } -/** - * @ingroup StrBuf_DeEnCoder - * @brief hide special chars from the HTML escapers and friends - * @param target buffer to put the escaped string in - * @param source buffer to escape +/* + * hide special chars from the HTML escapers and friends + * target buffer to put the escaped string in + * source buffer to escape */ -void StrBufEUid_escapize(StrBuf *target, const StrBuf *source) -{ +void StrBufEUid_escapize(StrBuf *target, const StrBuf *source) { int i, len; if (target != NULL) @@ -2682,50 +2622,319 @@ void StrBufEUid_escapize(StrBuf *target, const StrBuf *source) * Quoted Printable de/encoding * *******************************************************************************/ -/** - * @ingroup StrBuf_DeEnCoder - * @brief decode a buffer from base 64 encoding; destroys original - * @param Buf Buffor to transform +/* + * decode a buffer from base 64 encoding; destroys original + * Buf Buffor to transform */ -int StrBufDecodeBase64(StrBuf *Buf) -{ +int StrBufDecodeBase64(StrBuf *Buf) { char *xferbuf; size_t siz; - if (Buf == NULL) + if (Buf == NULL) { return -1; + } xferbuf = (char*) malloc(Buf->BufSize); if (xferbuf == NULL) return -1; *xferbuf = '\0'; - siz = CtdlDecodeBase64(xferbuf, - Buf->buf, - Buf->BufUsed); + siz = CtdlDecodeBase64(xferbuf, Buf->buf, Buf->BufUsed); free(Buf->buf); Buf->buf = xferbuf; Buf->BufUsed = siz; + + Buf->buf[Buf->BufUsed] = '\0'; return siz; } -/** - * @ingroup StrBuf_DeEnCoder - * @brief decode a buffer from base 64 encoding; destroys original - * @param Buf Buffor to transform + +/* + * decode a buffer from base 64 encoding; expects targetbuffer + * BufIn Buffor to transform + * BufOut Buffer to put result into */ -int StrBufDecodeHex(StrBuf *Buf) -{ - unsigned int ch; - char *pch, *pche, *pchi; +int StrBufDecodeBase64To(const StrBuf *BufIn, StrBuf *BufOut) { + if ((BufIn == NULL) || (BufOut == NULL)) + return -1; - if (Buf == NULL) return -1; + if (BufOut->BufSize < BufIn->BufUsed) { + IncreaseBuf(BufOut, 0, BufIn->BufUsed); + } - pch = pchi = Buf->buf; - pche = pch + Buf->BufUsed; + BufOut->BufUsed = CtdlDecodeBase64(BufOut->buf, BufIn->buf, BufIn->BufUsed); + return BufOut->BufUsed; +} - while (pchi < pche){ - ch = decode_hex(pchi); +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; +} + +/** + * decode a buffer from base 64 encoding; destroys original + * Buf Buffor to transform + */ +int StrBufDecodeHex(StrBuf *Buf) { + unsigned int ch; + char *pch, *pche, *pchi; + + if (Buf == NULL) return -1; + + pch = pchi = Buf->buf; + pche = pch + Buf->BufUsed; + + while (pchi < pche){ + ch = decode_hex(pchi); *pch = ch; pch ++; pchi += 2; @@ -2737,10 +2946,9 @@ int StrBufDecodeHex(StrBuf *Buf) } /** - * @ingroup StrBuf_DeEnCoder - * @brief replace all chars >0x20 && < 0x7F with Mute - * @param Mute char to put over invalid chars - * @param Buf Buffor to transform + * replace all chars >0x20 && < 0x7F with Mute + * Mute char to put over invalid chars + * Buf Buffor to transform */ int StrBufSanitizeAscii(StrBuf *Buf, const char Mute) { @@ -2758,10 +2966,9 @@ int StrBufSanitizeAscii(StrBuf *Buf, const char Mute) /** - * @ingroup StrBuf_DeEnCoder - * @brief remove escaped strings from i.e. the url string (like %20 for blanks) - * @param Buf Buffer to translate - * @param StripBlanks Reduce several blanks to one? + * remove escaped strings from i.e. the url string (like %20 for blanks) + * Buf Buffer to translate + * StripBlanks Reduce several blanks to one? */ long StrBufUnescape(StrBuf *Buf, int StripBlanks) { @@ -2808,13 +3015,12 @@ long StrBufUnescape(StrBuf *Buf, int StripBlanks) /** - * @ingroup StrBuf_DeEnCoder - * @brief RFC2047-encode a header field if necessary. + * RFC2047-encode a header field if necessary. * If no non-ASCII characters are found, the string * will be copied verbatim without encoding. * - * @param target Target buffer. - * @param source Source string to be encoded. + * target Target buffer. + * source Source string to be encoded. * @returns encoded length; -1 if non success. */ int StrBufRFC2047encode(StrBuf **target, const StrBuf *source) @@ -2863,7 +3069,6 @@ int StrBufRFC2047encode(StrBuf **target, const StrBuf *source) ch = (unsigned char) source->buf[i]; if ((ch < 32) || (ch > 126) || - (ch == 61) || (ch == '=') || (ch == '?') || (ch == '_') || @@ -2891,13 +3096,86 @@ int StrBufRFC2047encode(StrBuf **target, const StrBuf *source) return (*target)->BufUsed;; } +// Quoted-Printable encode a message; make it < 80 columns width. +// source Source string to be encoded. +// returns buffer with encoded message. +StrBuf *StrBufQuotedPrintableEncode(const StrBuf *EncodeMe) { + StrBuf *OutBuf; + char *Optr, *OEptr; + const char *ptr, *eptr; + unsigned char ch; + int LinePos; + + OutBuf = NewStrBufPlain(NULL, StrLength(EncodeMe) * 4); + Optr = OutBuf->buf; + OEptr = OutBuf->buf + OutBuf->BufSize; + ptr = EncodeMe->buf; + eptr = EncodeMe->buf + EncodeMe->BufUsed; + LinePos = 0; + + while (ptr < eptr) { + if (Optr + 4 >= OEptr) { + long Offset; + Offset = Optr - OutBuf->buf; + OutBuf->BufUsed = Optr - OutBuf->buf; + IncreaseBuf(OutBuf, 1, 0); + Optr = OutBuf->buf + Offset; + OEptr = OutBuf->buf + OutBuf->BufSize; + } + if (*ptr == '\r') { // ignore carriage returns + ptr ++; + } + else if (*ptr == '\n') { // hard line break + memcpy(Optr, HKEY("=0A")); + Optr += 3; + LinePos += 3; + ptr ++; + } + else if (( (*ptr >= 32) && (*ptr <= 60) ) || ( (*ptr >= 62) && (*ptr <= 126) )) { + *Optr = *ptr; + Optr ++; + ptr ++; + LinePos ++; + } + else { + ch = *ptr; + *Optr = '='; + Optr ++; + *Optr = HexList[ch][0]; + Optr ++; + *Optr = HexList[ch][1]; + Optr ++; + LinePos += 3; + ptr ++; + } + if (LinePos > 72) { // soft line break + if (isspace(*(Optr - 1))) { + ch = *(Optr - 1); + Optr --; + *Optr = '='; + Optr ++; + *Optr = HexList[ch][0]; + Optr ++; + *Optr = HexList[ch][1]; + Optr ++; + LinePos += 3; + } + *Optr = '='; + Optr ++; + *Optr = '\n'; + Optr ++; + LinePos = 0; + } + } + *Optr = '\0'; + OutBuf->BufUsed = Optr - OutBuf->buf; -static void AddRecipient(StrBuf *Target, - StrBuf *UserName, - StrBuf *EmailAddress, - StrBuf *EncBuf) -{ + return OutBuf; +} + + +static void AddRecipient(StrBuf *Target, StrBuf *UserName, StrBuf *EmailAddress, StrBuf *EncBuf) { int QuoteMe = 0; if (StrLength(Target) > 0) StrBufAppendBufPlain(Target, HKEY(", "), 0); @@ -2925,11 +3203,7 @@ static void AddRecipient(StrBuf *Target, * \param EncBuf Temporary buffer for internal use; Please provide valid buffer. * \returns encoded & sanitized buffer with the contents of Recp; Caller owns this memory. */ -StrBuf *StrBufSanitizeEmailRecipientVector(const StrBuf *Recp, - StrBuf *UserName, - StrBuf *EmailAddress, - StrBuf *EncBuf) -{ +StrBuf *StrBufSanitizeEmailRecipientVector(const StrBuf *Recp, StrBuf *UserName, StrBuf *EmailAddress, StrBuf *EncBuf) { StrBuf *Target; const char *pch, *pche; const char *UserStart, *UserEnd, *EmailStart, *EmailEnd, *At; @@ -3063,14 +3337,12 @@ StrBuf *StrBufSanitizeEmailRecipientVector(const StrBuf *Recp, /** - * @ingroup StrBuf - * @brief replaces all occurances of 'search' by 'replace' - * @param buf Buffer to modify - * @param search character to search - * @param replace character to replace search by + * replaces all occurances of 'search' by 'replace' + * buf Buffer to modify + * search character to search + * replace character to replace search by */ -void StrBufReplaceChars(StrBuf *buf, char search, char replace) -{ +void StrBufReplaceChars(StrBuf *buf, char search, char replace) { long i; if (buf == NULL) return; @@ -3081,9 +3353,8 @@ void StrBufReplaceChars(StrBuf *buf, char search, char replace) } /** - * @ingroup StrBuf - * @brief removes all \\r s from the string, or replaces them with \n if its not a combination of both. - * @param buf Buffer to modify + * removes all \\r s from the string, or replaces them with \n if its not a combination of both. + * buf Buffer to modify */ void StrBufToUnixLF(StrBuf *buf) { @@ -3116,14 +3387,13 @@ void StrBufToUnixLF(StrBuf *buf) *******************************************************************************/ /** - * @ingroup StrBuf_DeEnCoder - * @brief Wrapper around iconv_open() + * Wrapper around iconv_open() * Our version adds aliases for non-standard Microsoft charsets * such as 'MS950', aliasing them to names like 'CP950' * - * @param tocode Target encoding - * @param fromcode Source encoding - * @param pic anonimized pointer to iconv struct + * tocode Target encoding + * fromcode Source encoding + * pic anonimized pointer to iconv struct */ void ctdl_iconv_open(const char *tocode, const char *fromcode, void *pic) { @@ -3145,10 +3415,9 @@ void ctdl_iconv_open(const char *tocode, const char *fromcode, void *pic) /** - * @ingroup StrBuf_DeEnCoder - * @brief find one chunk of a RFC822 encoded string - * @param Buffer where to search - * @param bptr where to start searching + * find one chunk of a RFC822 encoded string + * Buffer where to search + * bptr where to start searching * @returns found position, NULL if none. */ static inline const char *FindNextEnd (const StrBuf *Buf, const char *bptr) @@ -3179,11 +3448,10 @@ static inline const char *FindNextEnd (const StrBuf *Buf, const char *bptr) /** - * @ingroup StrBuf_DeEnCoder - * @brief convert one buffer according to the preselected iconv pointer PIC - * @param ConvertBuf buffer we need to translate - * @param TmpBuf To share a workbuffer over several iterations. prepare to have it filled with useless stuff afterwards. - * @param pic Pointer to the iconv-session Object + * convert one buffer according to the preselected iconv pointer PIC + * ConvertBuf buffer we need to translate + * TmpBuf To share a workbuffer over several iterations. prepare to have it filled with useless stuff afterwards. + * pic Pointer to the iconv-session Object */ void StrBufConvert(StrBuf *ConvertBuf, StrBuf *TmpBuf, void *pic) { @@ -3235,7 +3503,7 @@ TRYAGAIN: TmpBuf->buf[TmpBuf->BufUsed] = '\0'; /* little card game: wheres the red lady? */ - SwapBuffers(ConvertBuf, TmpBuf); + iSwapBuffers(ConvertBuf, TmpBuf); FlushStrBuf(TmpBuf); } #endif @@ -3243,15 +3511,14 @@ TRYAGAIN: /** - * @ingroup StrBuf_DeEnCoder - * @brief catches one RFC822 encoded segment, and decodes it. - * @param Target buffer to fill with result - * @param DecodeMe buffer with stuff to process - * @param SegmentStart points to our current segment in DecodeMe - * @param SegmentEnd Points to the end of our current segment in DecodeMe - * @param ConvertBuf Workbuffer shared between several iterations. Random content; needs to be valid - * @param ConvertBuf2 Workbuffer shared between several iterations. Random content; needs to be valid - * @param FoundCharset Characterset to default decoding to; if we find another we will overwrite it. + * catches one RFC822 encoded segment, and decodes it. + * Target buffer to fill with result + * DecodeMe buffer with stuff to process + * SegmentStart points to our current segment in DecodeMe + * SegmentEnd Points to the end of our current segment in DecodeMe + * ConvertBuf Workbuffer shared between several iterations. Random content; needs to be valid + * ConvertBuf2 Workbuffer shared between several iterations. Random content; needs to be valid + * FoundCharset Characterset to default decoding to; if we find another we will overwrite it. */ inline static void DecodeSegment(StrBuf *Target, const StrBuf *DecodeMe, @@ -3329,13 +3596,12 @@ inline static void DecodeSegment(StrBuf *Target, } /** - * @ingroup StrBuf_DeEnCoder - * @brief Handle subjects with RFC2047 encoding such as: [deprecated old syntax!] + * Handle subjects with RFC2047 encoding such as: [deprecated old syntax!] * =?koi8-r?B?78bP0s3Mxc7JxSDXz9rE1dvO2c3JINvB0sHNySDP?= - * @param Target where to put the decoded string to - * @param DecodeMe buffer with encoded string - * @param DefaultCharset if we don't find one, which should we use? - * @param FoundCharset overrides DefaultCharset if non-empty; If we find a charset inside of the string, + * Target where to put the decoded string to + * DecodeMe buffer with encoded string + * DefaultCharset if we don't find one, which should we use? + * FoundCharset overrides DefaultCharset if non-empty; If we find a charset inside of the string, * put it here for later use where no string might be known. */ void StrBuf_RFC822_to_Utf8(StrBuf *Target, const StrBuf *DecodeMe, const StrBuf* DefaultCharset, StrBuf *FoundCharset) @@ -3356,16 +3622,15 @@ void StrBuf_RFC822_to_Utf8(StrBuf *Target, const StrBuf *DecodeMe, const StrBuf* } /** - * @ingroup StrBuf_DeEnCoder - * @brief Handle subjects with RFC2047 encoding such as: + * Handle subjects with RFC2047 encoding such as: * =?koi8-r?B?78bP0s3Mxc7JxSDXz9rE1dvO2c3JINvB0sHNySDP?= - * @param Target where to put the decoded string to - * @param DecodeMe buffer with encoded string - * @param DefaultCharset if we don't find one, which should we use? - * @param FoundCharset overrides DefaultCharset if non-empty; If we find a charset inside of the string, + * Target where to put the decoded string to + * DecodeMe buffer with encoded string + * DefaultCharset if we don't find one, which should we use? + * FoundCharset overrides DefaultCharset if non-empty; If we find a charset inside of the string, * put it here for later use where no string might be known. - * @param ConvertBuf workbuffer. feed in, you shouldn't care about its content. - * @param ConvertBuf2 workbuffer. feed in, you shouldn't care about its content. + * ConvertBuf workbuffer. feed in, you shouldn't care about its content. + * ConvertBuf2 workbuffer. feed in, you shouldn't care about its content. */ void StrBuf_RFC822_2_Utf8(StrBuf *Target, const StrBuf *DecodeMe, @@ -3514,9 +3779,8 @@ void StrBuf_RFC822_2_Utf8(StrBuf *Target, *******************************************************************************/ /** - * @ingroup StrBuf - * @brief evaluate the length of an utf8 special character sequence - * @param Char the character to examine + * evaluate the length of an utf8 special character sequence + * Char the character to examine * @returns width of utf8 chars in bytes; if the sequence is broken 0 is returned; 1 if its simply ASCII. */ static inline int Ctdl_GetUtf8SequenceLength(const char *CharS, const char *CharE) @@ -3539,9 +3803,8 @@ static inline int Ctdl_GetUtf8SequenceLength(const char *CharS, const char *Char } /** - * @ingroup StrBuf - * @brief detect whether this char starts an utf-8 encoded char - * @param Char character to inspect + * detect whether this char starts an utf-8 encoded char + * Char character to inspect * @returns yes or no */ static inline int Ctdl_IsUtf8SequenceStart(const char Char) @@ -3551,9 +3814,8 @@ static inline int Ctdl_IsUtf8SequenceStart(const char Char) } /** - * @ingroup StrBuf - * @brief measure the number of glyphs in an UTF8 string... - * @param Buf string to measure + * measure the number of glyphs in an UTF8 string... + * Buf string to measure * @returns the number of glyphs in Buf */ long StrBuf_Utf8StrLen(StrBuf *Buf) @@ -3581,10 +3843,9 @@ long StrBuf_Utf8StrLen(StrBuf *Buf) } /** - * @ingroup StrBuf - * @brief cuts a string after maxlen glyphs - * @param Buf string to cut to maxlen glyphs - * @param maxlen how long may the string become? + * cuts a string after maxlen glyphs + * Buf string to cut to maxlen glyphs + * maxlen how long may the string become? * @returns current length of the string */ long StrBuf_Utf8StrCut(StrBuf *Buf, int maxlen) @@ -3604,11 +3865,11 @@ long StrBuf_Utf8StrCut(StrBuf *Buf, int maxlen) n++; aptr++; } - if (n > maxlen) { + if (n >= maxlen) { *aptr = '\0'; Buf->BufUsed = aptr - Buf->buf; return Buf->BufUsed; - } + } } return Buf->BufUsed; @@ -3622,28 +3883,22 @@ long StrBuf_Utf8StrCut(StrBuf *Buf, int maxlen) * wrapping ZLib * *******************************************************************************/ -#ifdef HAVE_ZLIB -#define DEF_MEM_LEVEL 8 /*< memlevel??? */ -#define OS_CODE 0x03 /*< unix */ - /** - * @ingroup StrBuf_DeEnCoder - * @brief uses the same calling syntax as compress2(), but it + * uses the same calling syntax as compress2(), but it * creates a stream compatible with HTTP "Content-encoding: gzip" - * @param dest compressed buffer - * @param destLen length of the compresed data - * @param source source to encode - * @param sourceLen length of source to encode - * @param level compression level + * dest compressed buffer + * destLen length of the compresed data + * source source to encode + * sourceLen length of source to encode + * level compression level */ +#ifdef HAVE_ZLIB int ZEXPORT compress_gzip(Bytef * dest, size_t * destLen, const Bytef * source, uLong sourceLen, int level) { - const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */ - /* write gzip header */ snprintf((char *) dest, *destLen, "%c%c%c%c%c%c%c%c%c%c", @@ -3696,10 +3951,9 @@ int ZEXPORT compress_gzip(Bytef * dest, /** - * @ingroup StrBuf_DeEnCoder - * @brief compress the buffer with gzip + * compress the buffer with gzip * Attention! If you feed this a Const String, you must maintain the uncompressed buffer yourself! - * @param Buf buffer whose content is to be gzipped + * Buf buffer whose content is to be gzipped */ int CompressBuffer(StrBuf *Buf) { @@ -3861,11 +4115,10 @@ int StrBuf_write_one_chunk_callback(int fd, short event, IOBuffer *FB) } /** - * @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 + * extract a "next line" from Buf; Ptr to persist across several iterations + * LineBuf your line will be copied here. + * FB BLOB with lines of text... + * 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 */ @@ -3946,9 +4199,8 @@ eReadState StrBufChunkSipLine(StrBuf *LineBuf, IOBuffer *FB) } /** - * @ingroup StrBuf_CHUNKED_IO - * @brief check whether the chunk-buffer has more data waiting or not. - * @param FB Chunk-Buffer to inspect + * check whether the chunk-buffer has more data waiting or not. + * FB Chunk-Buffer to inspect */ eReadState StrBufCheckBuffer(IOBuffer *FB) { @@ -3973,335 +4225,18 @@ long IOBufferStrLength(IOBuffer *FB) return StrLength(FB->Buf) - (FB->ReadWritePointer - FB->Buf->buf); } -inline static void FDIOBufferFlush(FDIOBuffer *FDB) -{ - memset(FDB, 0, sizeof(FDIOBuffer)); - FDB->OtherFD = -1; - FDB->SplicePipe[0] = -1; - FDB->SplicePipe[1] = -1; -} - -void FDIOBufferInit(FDIOBuffer *FDB, IOBuffer *IO, int FD, long TotalSendSize) -{ - FDIOBufferFlush(FDB); - FDB->ChunkSize = - FDB->TotalSendSize = TotalSendSize; - FDB->IOB = IO; -#ifdef LINUX_SPLICE - if (EnableSplice) - pipe(FDB->SplicePipe); - else -#endif - FDB->ChunkBuffer = NewStrBufPlain(NULL, TotalSendSize + 1); - - FDB->OtherFD = FD; -} - -void FDIOBufferDelete(FDIOBuffer *FDB) -{ -#ifdef LINUX_SPLICE - if (EnableSplice) - { - if (FDB->SplicePipe[0] > 0) - close(FDB->SplicePipe[0]); - if (FDB->SplicePipe[1] > 0) - close(FDB->SplicePipe[1]); - } - else -#endif - FreeStrBuf(&FDB->ChunkBuffer); - - if (FDB->OtherFD > 0) - close(FDB->OtherFD); - FDIOBufferFlush(FDB); -} - -int FileSendChunked(FDIOBuffer *FDB, const char **Err) -{ - ssize_t sent, pipesize; -#ifdef LINUX_SPLICE - if (EnableSplice) - { - if (FDB->PipeSize == 0) - { - pipesize = splice(FDB->OtherFD, - &FDB->TotalSentAlready, - FDB->SplicePipe[1], - NULL, - FDB->ChunkSendRemain, - SPLICE_F_MOVE); - - if (pipesize == -1) - { - *Err = strerror(errno); - return pipesize; - } - FDB->PipeSize = pipesize; - } - sent = splice(FDB->SplicePipe[0], - NULL, - FDB->IOB->fd, - NULL, - FDB->PipeSize, - SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK); - if (sent == -1) - { - *Err = strerror(errno); - return sent; - } - FDB->PipeSize -= sent; - FDB->ChunkSendRemain -= sent; - return sent; - } - else -#endif - { - char *pRead; - long nRead = 0; - - pRead = FDB->ChunkBuffer->buf; - while ((FDB->ChunkBuffer->BufUsed < FDB->TotalSendSize) && (nRead >= 0)) - { - nRead = read(FDB->OtherFD, pRead, FDB->TotalSendSize - FDB->ChunkBuffer->BufUsed); - if (nRead > 0) { - FDB->ChunkBuffer->BufUsed += nRead; - FDB->ChunkBuffer->buf[FDB->ChunkBuffer->BufUsed] = '\0'; - } - else if (nRead == 0) {} - else return nRead; - - } - - nRead = write(FDB->IOB->fd, FDB->ChunkBuffer->buf + FDB->TotalSentAlready, FDB->ChunkSendRemain); - - if (nRead >= 0) { - FDB->TotalSentAlready += nRead; - FDB->ChunkSendRemain -= nRead; - return FDB->ChunkSendRemain; - } - else { - return nRead; - } - } -} - -int FileRecvChunked(FDIOBuffer *FDB, const char **Err) -{ - ssize_t sent, pipesize; - -#ifdef LINUX_SPLICE - if (EnableSplice) - { - if (FDB->PipeSize == 0) - { - pipesize = splice(FDB->IOB->fd, - NULL, - FDB->SplicePipe[1], - NULL, - FDB->ChunkSendRemain, - SPLICE_F_MORE | SPLICE_F_MOVE|SPLICE_F_NONBLOCK); - - if (pipesize == -1) - { - *Err = strerror(errno); - return pipesize; - } - FDB->PipeSize = pipesize; - } - - sent = splice(FDB->SplicePipe[0], - NULL, - FDB->OtherFD, - &FDB->TotalSentAlready, - FDB->PipeSize, - SPLICE_F_MORE | SPLICE_F_MOVE); - - if (sent == -1) - { - *Err = strerror(errno); - return sent; - } - FDB->PipeSize -= sent; - FDB->ChunkSendRemain -= sent; - return sent; - } - else -#endif - { - sent = read(FDB->IOB->fd, FDB->ChunkBuffer->buf, FDB->ChunkSendRemain); - if (sent > 0) { - int nWritten = 0; - int rc; - - FDB->ChunkBuffer->BufUsed = sent; - - while (nWritten < FDB->ChunkBuffer->BufUsed) { - rc = write(FDB->OtherFD, FDB->ChunkBuffer->buf + nWritten, FDB->ChunkBuffer->BufUsed - nWritten); - if (rc < 0) { - *Err = strerror(errno); - return rc; - } - nWritten += rc; - - } - FDB->ChunkBuffer->BufUsed = 0; - FDB->TotalSentAlready += sent; - FDB->ChunkSendRemain -= sent; - return FDB->ChunkSendRemain; - } - else if (sent < 0) { - *Err = strerror(errno); - return sent; - } - return 0; - } -} - -int FileMoveChunked(FDIOBuffer *FDB, const char **Err) -{ - ssize_t sent, pipesize; - -#ifdef LINUX_SPLICE - if (EnableSplice) - { - if (FDB->PipeSize == 0) - { - pipesize = splice(FDB->IOB->fd, - &FDB->TotalReadAlready, - FDB->SplicePipe[1], - NULL, - FDB->ChunkSendRemain, - SPLICE_F_MORE | SPLICE_F_MOVE|SPLICE_F_NONBLOCK); - - if (pipesize == -1) - { - *Err = strerror(errno); - return pipesize; - } - FDB->PipeSize = pipesize; - } - - sent = splice(FDB->SplicePipe[0], - NULL, - FDB->OtherFD, - &FDB->TotalSentAlready, - FDB->PipeSize, - SPLICE_F_MORE | SPLICE_F_MOVE); - - if (sent == -1) - { - *Err = strerror(errno); - return sent; - } - FDB->PipeSize -= sent; - FDB->ChunkSendRemain -= sent; - return sent; - } - else -#endif - { - sent = read(FDB->IOB->fd, FDB->ChunkBuffer->buf, FDB->ChunkSendRemain); - if (sent > 0) { - int nWritten = 0; - int rc; - - FDB->ChunkBuffer->BufUsed = sent; - - while (nWritten < FDB->ChunkBuffer->BufUsed) { - rc = write(FDB->OtherFD, FDB->ChunkBuffer->buf + nWritten, FDB->ChunkBuffer->BufUsed - nWritten); - if (rc < 0) { - *Err = strerror(errno); - return rc; - } - nWritten += rc; - - } - FDB->ChunkBuffer->BufUsed = 0; - FDB->TotalSentAlready += sent; - FDB->ChunkSendRemain -= sent; - return FDB->ChunkSendRemain; - } - else if (sent < 0) { - *Err = strerror(errno); - return sent; - } - return 0; - } -} - -eReadState WriteIOBAlreadyRead(FDIOBuffer *FDB, const char **Error) -{ - int IsNonBlock; - int fdflags; - long rlen; - long should_write; - int nSuccessLess = 0; - struct timeval tv; - fd_set rfds; - - fdflags = fcntl(FDB->OtherFD, F_GETFL); - IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK; - - while ((FDB->IOB->ReadWritePointer - FDB->IOB->Buf->buf < FDB->IOB->Buf->BufUsed) && - (FDB->ChunkSendRemain > 0)) - { - if (IsNonBlock){ - tv.tv_sec = 1; /* selectresolution; */ - tv.tv_usec = 0; - - FD_ZERO(&rfds); - FD_SET(FDB->OtherFD, &rfds); - if (select(FDB->OtherFD + 1, NULL, &rfds, NULL, &tv) == -1) { - *Error = strerror(errno); - return eReadFail; - } - } - if (IsNonBlock && ! FD_ISSET(FDB->OtherFD, &rfds)) { - nSuccessLess ++; - continue; - } - - should_write = FDB->IOB->Buf->BufUsed - - (FDB->IOB->ReadWritePointer - FDB->IOB->Buf->buf); - if (should_write > FDB->ChunkSendRemain) - should_write = FDB->ChunkSendRemain; - - rlen = write(FDB->OtherFD, - FDB->IOB->ReadWritePointer, - should_write); - if (rlen < 1) { - *Error = strerror(errno); - - return eReadFail; - } - FDB->TotalSentAlready += rlen; - FDB->IOB->ReadWritePointer += rlen; - FDB->ChunkSendRemain -= rlen; - } - if (FDB->IOB->ReadWritePointer >= FDB->IOB->Buf->buf + FDB->IOB->Buf->BufUsed) - { - FlushStrBuf(FDB->IOB->Buf); - FDB->IOB->ReadWritePointer = NULL; - } - - if (FDB->ChunkSendRemain == 0) - return eReadSuccess; - else - return eMustReadMore; -} /******************************************************************************* * File I/O; Prefer buffered read since its faster! * *******************************************************************************/ /** - * @ingroup StrBuf_IO - * @brief Read a line from socket + * Read a line from socket * flushes and closes the FD on error - * @param buf the buffer to get the input to - * @param fd pointer to the filedescriptor to read - * @param append Append to an existing string or replace? - * @param Error strerror() on error + * buf the buffer to get the input to + * fd pointer to the filedescriptor to read + * append Append to an existing string or replace? + * Error strerror() on error * @returns numbers of chars read */ int StrBufTCP_read_line(StrBuf *buf, int *fd, int append, const char **Error) @@ -4342,16 +4277,16 @@ int StrBufTCP_read_line(StrBuf *buf, int *fd, int append, const char **Error) return len - slen; } + /** - * @ingroup StrBuf_BufferedIO - * @brief Read a line from socket + * Read a line from socket * flushes and closes the FD on error - * @param Line the line to read from the fd / I/O Buffer - * @param buf the buffer to get the input to - * @param fd pointer to the filedescriptor to read - * @param timeout number of successless selects until we bail out - * @param selectresolution how long to wait on each select - * @param Error strerror() on error + * Line the line to read from the fd / I/O Buffer + * buf the buffer to get the input to + * fd pointer to the filedescriptor to read + * timeout number of successless selects until we bail out + * selectresolution how long to wait on each select + * Error strerror() on error * @returns numbers of chars read */ int StrBufTCP_read_buffered_line(StrBuf *Line, @@ -4445,16 +4380,15 @@ static const char *ErrRBLF_PreConditionFailed="StrBufTCP_read_buffered_line_fast static const char *ErrRBLF_SelectFailed="StrBufTCP_read_buffered_line_fast: Select failed without reason"; static const char *ErrRBLF_NotEnoughSentFromServer="StrBufTCP_read_buffered_line_fast: No complete line was sent from peer"; /** - * @ingroup StrBuf_BufferedIO - * @brief Read a line from socket + * Read a line from socket * flushes and closes the FD on error - * @param Line where to append our Line read from the fd / I/O Buffer; - * @param IOBuf the buffer to get the input to; lifetime pair to FD - * @param Pos pointer to the current read position, should be NULL initialized on opening the FD it belongs to.! - * @param fd pointer to the filedescriptor to read - * @param timeout number of successless selects until we bail out - * @param selectresolution how long to wait on each select - * @param Error strerror() on error + * Line where to append our Line read from the fd / I/O Buffer; + * IOBuf the buffer to get the input to; lifetime pair to FD + * Pos pointer to the current read position, should be NULL initialized on opening the FD it belongs to.! + * fd pointer to the filedescriptor to read + * timeout number of successless selects until we bail out + * selectresolution how long to wait on each select + * Error strerror() on error * @returns numbers of chars read or -1 in case of error. "\n" will become 0 */ int StrBufTCP_read_buffered_line_fast(StrBuf *Line, @@ -4640,14 +4574,13 @@ int StrBufTCP_read_buffered_line_fast(StrBuf *Line, static const char *ErrRBLF_BLOBPreConditionFailed="StrBufReadBLOB: Wrong arguments or invalid Filedescriptor"; /** - * @ingroup StrBuf_IO - * @brief Input binary data from socket + * Input binary data from socket * flushes and closes the FD on error - * @param Buf the buffer to get the input to - * @param fd pointer to the filedescriptor to read - * @param append Append to an existing string or replace? - * @param nBytes the maximal number of bytes to read - * @param Error strerror() on error + * Buf the buffer to get the input to + * fd pointer to the filedescriptor to read + * append Append to an existing string or replace? + * nBytes the maximal number of bytes to read + * Error strerror() on error * @returns numbers of chars read */ int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **Error) @@ -4719,17 +4652,16 @@ int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **E const char *ErrRBB_BLOBFPreConditionFailed = "StrBufReadBLOBBuffered: to many selects; aborting."; const char *ErrRBB_too_many_selects = "StrBufReadBLOBBuffered: to many selects; aborting."; /** - * @ingroup StrBuf_BufferedIO - * @brief Input binary data from socket + * Input binary data from socket * flushes and closes the FD on error - * @param Blob put binary thing here - * @param IOBuf the buffer to get the input to - * @param Pos offset inside of IOBuf - * @param fd pointer to the filedescriptor to read - * @param append Append to an existing string or replace? - * @param nBytes the maximal number of bytes to read - * @param check whether we should search for '000\n' terminators in case of timeouts - * @param Error strerror() on error + * Blob put binary thing here + * IOBuf the buffer to get the input to + * Pos offset inside of IOBuf + * fd pointer to the filedescriptor to read + * append Append to an existing string or replace? + * nBytes the maximal number of bytes to read + * check whether we should search for '000\n' terminators in case of timeouts + * Error strerror() on error * @returns numbers of chars read */ int StrBufReadBLOBBuffered(StrBuf *Blob, @@ -4771,14 +4703,13 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, pos = *Pos; - if (pos != NULL) + if (pos != NULL) { rlen = pos - IOBuf->buf; + } rlen = IOBuf->BufUsed - rlen; - if ((IOBuf->BufUsed > 0) && - (pos != NULL) && - (pos < IOBuf->buf + IOBuf->BufUsed)) + if ((IOBuf->BufUsed > 0) && (pos != NULL) && (pos < IOBuf->buf + IOBuf->BufUsed)) { if (rlen < nBytes) { memcpy(Blob->buf + Blob->BufUsed, pos, rlen); @@ -4803,8 +4734,9 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, FlushStrBuf(IOBuf); *Pos = NULL; - if (IOBuf->BufSize < nBytes - nRead) + if (IOBuf->BufSize < nBytes - nRead) { IncreaseBuf(IOBuf, 0, nBytes - nRead); + } ptr = IOBuf->buf; fdflags = fcntl(*fd, F_GETFL); @@ -4816,11 +4748,8 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, nBytes -= nRead; nRead = 0; - while ((nSuccessLess < MaxTries) && - (nRead < nBytes) && - (*fd != -1)) { - if (IsNonBlock) - { + while ((nSuccessLess < MaxTries) && (nRead < nBytes) && (*fd != -1)) { + if (IsNonBlock) { tv.tv_sec = 1; tv.tv_usec = 0; @@ -4830,8 +4759,9 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, *Error = strerror(errno); close (*fd); *fd = -1; - if (*Error == NULL) + if (*Error == NULL) { *Error = ErrRBLF_SelectFailed; + } return -1; } if (! FD_ISSET(*fd, &rfds) != 0) { @@ -4839,20 +4769,16 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, continue; } } - rlen = read(*fd, - ptr, - IOBuf->BufSize - (ptr - IOBuf->buf)); - if (rlen == -1) { + rlen = read(*fd, ptr, IOBuf->BufSize - (ptr - IOBuf->buf)); + // if (rlen == -1) { 2021feb27 ajc changed this, apparently we will always get at least 1 byte unless the connection is broken + if (rlen < 1) { close(*fd); *fd = -1; *Error = strerror(errno); return rlen; } else if (rlen == 0){ - if ((check == NNN_TERM) && - (nRead > 5) && - (strncmp(IOBuf->buf + IOBuf->BufUsed - 5, "\n000\n", 5) == 0)) - { + if ((check == NNN_TERM) && (nRead > 5) && (strncmp(IOBuf->buf + IOBuf->BufUsed - 5, "\n000\n", 5) == 0)) { StrBufPlain(Blob, HKEY("\n000\n")); StrBufCutRight(Blob, 5); return Blob->BufUsed; @@ -4890,11 +4816,10 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, } /** - * @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 Buf BLOB with lines of text... - * @param Ptr moved arround to keep the next-line across several iterations + * extract a "next line" from Buf; Ptr to persist across several iterations + * LineBuf your line will be copied here. + * Buf BLOB with lines of text... + * 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 remaining buffer */ @@ -4957,10 +4882,9 @@ int StrBufSipLine(StrBuf *LineBuf, const StrBuf *Buf, const char **Ptr) /** - * @ingroup StrBuf_IO - * @brief removes double slashes from pathnames - * @param Dir directory string to filter - * @param RemoveTrailingSlash allows / disallows trailing slashes + * removes double slashes from pathnames + * Dir directory string to filter + * RemoveTrailingSlash allows / disallows trailing slashes */ void StrBufStripSlashes(StrBuf *Dir, int RemoveTrailingSlash) { @@ -4990,3 +4914,44 @@ void StrBufStripSlashes(StrBuf *Dir, int RemoveTrailingSlash) } +/* + * Decode a quoted-printable encoded StrBuf buffer "in place" + * This is possible because the decoded will always be shorter than the encoded + * so we don't have to worry about the buffer being to small. + */ +void StrBufDecodeQP(StrBuf *Buf) +{ + if (!Buf) { // sanity check #1 + return; + } + + int source_len = StrLength(Buf); + if (source_len < 1) { // sanity check #2 + return; + } + + int spos = 0; // source position + int tpos = 0; // target position + + while (spos < source_len) { + if (!strncmp(&Buf->buf[spos], "=\r\n", 3)) { + spos += 3; + } + else if (!strncmp(&Buf->buf[spos], "=\n", 2)) { + spos += 2; + } + else if (Buf->buf[spos] == '=') { + ++spos; + int ch; + sscanf(&Buf->buf[spos], "%02x", &ch); + Buf->buf[tpos++] = ch; + spos +=2; + } + else { + Buf->buf[tpos++] = Buf->buf[spos++]; + } + } + + Buf->buf[tpos] = 0; + Buf->BufUsed = tpos; +}