LCOV - code coverage report
Current view: top level - lib - stringbuf.c (source / functions) Hit Total Coverage
Test: libcitadel.info Lines: 418 1820 23.0 %
Date: 2010-12-07 Functions: 28 87 32.2 %
Branches: 193 1234 15.6 %

           Branch data     Line data    Source code
       1                 :            : #include "sysdep.h"
       2                 :            : #include <ctype.h>
       3                 :            : #include <errno.h>
       4                 :            : #include <string.h>
       5                 :            : #include <unistd.h>
       6                 :            : #include <string.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <sys/select.h>
       9                 :            : #include <fcntl.h>
      10                 :            : #include <sys/types.h>
      11                 :            : #define SHOW_ME_VAPPEND_PRINTF
      12                 :            : #include <stdarg.h>
      13                 :            : #include "libcitadel.h"
      14                 :            : 
      15                 :            : #ifdef HAVE_ICONV
      16                 :            : #include <iconv.h>
      17                 :            : #endif
      18                 :            : 
      19                 :            : #ifdef HAVE_BACKTRACE
      20                 :            : #include <execinfo.h>
      21                 :            : #endif
      22                 :            : 
      23                 :            : #ifdef HAVE_ZLIB
      24                 :            : #include <zlib.h>
      25                 :            : int ZEXPORT compress_gzip(Bytef * dest, size_t * destLen,
      26                 :            :                           const Bytef * source, uLong sourceLen, int level);
      27                 :            : #endif
      28                 :            : int BaseStrBufSize = 64;
      29                 :            : 
      30                 :            : const char *StrBufNOTNULL = ((char*) NULL) - 1;
      31                 :            : 
      32                 :            : const char HexList[256][3] = {
      33                 :            :         "00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
      34                 :            :         "10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
      35                 :            :         "20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
      36                 :            :         "30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
      37                 :            :         "40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
      38                 :            :         "50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
      39                 :            :         "60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
      40                 :            :         "70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
      41                 :            :         "80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
      42                 :            :         "90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
      43                 :            :         "A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
      44                 :            :         "B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
      45                 :            :         "C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
      46                 :            :         "D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
      47                 :            :         "E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
      48                 :            :         "F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"};
      49                 :            : 
      50                 :            : /**
      51                 :            :  * @defgroup StrBuf Stringbuffer, A class for manipulating strings with dynamic buffers
      52                 :            :  * StrBuf is a versatile class, aiding the handling of dynamic strings
      53                 :            :  *  * reduce de/reallocations
      54                 :            :  *  * reduce the need to remeasure it
      55                 :            :  *  * reduce scanning over the string (in @ref StrBuf_NextTokenizer "Tokenizers")
      56                 :            :  *  * allow asyncroneous IO for line and Blob based operations
      57                 :            :  *  * reduce the use of memove in those
      58                 :            :  *  * Quick filling in several operations with append functions
      59                 :            :  */
      60                 :            : 
      61                 :            : /**
      62                 :            :  * @defgroup StrBuf_DeConstructors Create/Destroy StrBufs
      63                 :            :  * @ingroup StrBuf
      64                 :            :  */
      65                 :            : 
      66                 :            : /**
      67                 :            :  * @defgroup StrBuf_Cast Cast operators to interact with char* based code
      68                 :            :  * @ingroup StrBuf
      69                 :            :  * use these operators to interfere with code demanding char*; 
      70                 :            :  * if you need to own the content, smash me. Avoid, since we loose the length information.
      71                 :            :  */
      72                 :            : 
      73                 :            : /**
      74                 :            :  * @defgroup StrBuf_Filler Create/Replace/Append Content into a StrBuf
      75                 :            :  * @ingroup StrBuf
      76                 :            :  * operations to get your Strings into a StrBuf, manipulating them, or appending
      77                 :            :  */
      78                 :            : /**
      79                 :            :  * @defgroup StrBuf_NextTokenizer Fast tokenizer to pull tokens in sequence 
      80                 :            :  * @ingroup StrBuf
      81                 :            :  * Quick tokenizer; demands of the user to pull its tokens in sequence
      82                 :            :  */
      83                 :            : 
      84                 :            : /**
      85                 :            :  * @defgroup StrBuf_Tokenizer tokenizer Functions; Slow ones.
      86                 :            :  * @ingroup StrBuf
      87                 :            :  * versatile tokenizer; random access to tokens, but slower; Prefer the @ref StrBuf_NextTokenizer "Next Tokenizer"
      88                 :            :  */
      89                 :            : 
      90                 :            : /**
      91                 :            :  * @defgroup StrBuf_BufferedIO Buffered IO with Asynchroneous reads and no unneeded memmoves (the fast ones)
      92                 :            :  * @ingroup StrBuf
      93                 :            :  * File IO to fill StrBufs; Works with work-buffer shared across several calls;
      94                 :            :  * External Cursor to maintain the current read position inside of the buffer
      95                 :            :  * the non-fast ones will use memove to keep the start of the buffer the read buffer (which is slower) 
      96                 :            :  */
      97                 :            : 
      98                 :            : /**
      99                 :            :  * @defgroup StrBuf_IO FileIO; Prefer @ref StrBuf_BufferedIO
     100                 :            :  * @ingroup StrBuf
     101                 :            :  * Slow I/O; avoid.
     102                 :            :  */
     103                 :            : 
     104                 :            : /**
     105                 :            :  * @defgroup StrBuf_DeEnCoder functions to translate the contents of a buffer
     106                 :            :  * @ingroup StrBuf
     107                 :            :  * these functions translate the content of a buffer into another representation;
     108                 :            :  * some are combined Fillers and encoders
     109                 :            :  */
     110                 :            : 
     111                 :            : /**
     112                 :            :  * Private Structure for the Stringbuffer
     113                 :            :  */
     114                 :            : struct StrBuf {
     115                 :            :         char *buf;         /**< the pointer to the dynamic buffer */
     116                 :            :         long BufSize;      /**< how many spcae do we optain */
     117                 :            :         long BufUsed;      /**< StNumber of Chars used excluding the trailing \\0 */
     118                 :            :         int ConstBuf;      /**< are we just a wrapper arround a static buffer and musn't we be changed? */
     119                 :            : #ifdef SIZE_DEBUG
     120                 :            :         long nIncreases;   /**< for profiling; cound how many times we needed more */
     121                 :            :         char bt [SIZ];     /**< Stacktrace of last increase */
     122                 :            :         char bt_lastinc [SIZ]; /**< How much did we increase last time? */
     123                 :            : #endif
     124                 :            : };
     125                 :            : 
     126                 :            : 
     127                 :            : static inline int Ctdl_GetUtf8SequenceLength(const char *CharS, const char *CharE);
     128                 :            : static inline int Ctdl_IsUtf8SequenceStart(const char Char);
     129                 :            : 
     130                 :            : #ifdef SIZE_DEBUG
     131                 :            : #ifdef HAVE_BACKTRACE
     132                 :            : static void StrBufBacktrace(StrBuf *Buf, int which)
     133                 :            : {
     134                 :            :         int n;
     135                 :            :         char *pstart, *pch;
     136                 :            :         void *stack_frames[50];
     137                 :            :         size_t size, i;
     138                 :            :         char **strings;
     139                 :            : 
     140                 :            :         if (which)
     141                 :            :                 pstart = pch = Buf->bt;
     142                 :            :         else
     143                 :            :                 pstart = pch = Buf->bt_lastinc;
     144                 :            :         size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
     145                 :            :         strings = backtrace_symbols(stack_frames, size);
     146                 :            :         for (i = 0; i < size; i++) {
     147                 :            :                 if (strings != NULL)
     148                 :            :                         n = snprintf(pch, SIZ - (pch - pstart), "%s\\n", strings[i]);
     149                 :            :                 else
     150                 :            :                         n = snprintf(pch, SIZ - (pch - pstart), "%p\\n", stack_frames[i]);
     151                 :            :                 pch += n;
     152                 :            :         }
     153                 :            :         free(strings);
     154                 :            : 
     155                 :            : 
     156                 :            : }
     157                 :            : #endif
     158                 :            : 
     159                 :            : void dbg_FreeStrBuf(StrBuf *FreeMe, char *FromWhere)
     160                 :            : {
     161                 :            :         if (hFreeDbglog == -1){
     162                 :            :                 pid_t pid = getpid();
     163                 :            :                 char path [SIZ];
     164                 :            :                 snprintf(path, SIZ, "/tmp/libcitadel_strbuf_realloc.log.%d", pid);
     165                 :            :                 hFreeDbglog = open(path, O_APPEND|O_CREAT|O_WRONLY);
     166                 :            :         }
     167                 :            :         if ((*FreeMe)->nIncreases > 0)
     168                 :            :         {
     169                 :            :                 char buf[SIZ * 3];
     170                 :            :                 long n;
     171                 :            :                 n = snprintf(buf, SIZ * 3, "%c+|%ld|%ld|%ld|%s|%s|\n",
     172                 :            :                              FromWhere,
     173                 :            :                              (*FreeMe)->nIncreases,
     174                 :            :                              (*FreeMe)->BufUsed,
     175                 :            :                              (*FreeMe)->BufSize,
     176                 :            :                              (*FreeMe)->bt,
     177                 :            :                              (*FreeMe)->bt_lastinc);
     178                 :            :                 n = write(hFreeDbglog, buf, n);
     179                 :            :         }
     180                 :            :         else
     181                 :            :         {
     182                 :            :                 char buf[128];
     183                 :            :                 long n;
     184                 :            :                 n = snprintf(buf, 128, "%c_|0|%ld%ld|\n",
     185                 :            :                              FromWhere,
     186                 :            :                              (*FreeMe)->BufUsed,
     187                 :            :                              (*FreeMe)->BufSize);
     188                 :            :                 n = write(hFreeDbglog, buf, n);
     189                 :            :         }
     190                 :            : }
     191                 :            : 
     192                 :            : void dbg_IncreaseBuf(StrBuf *IncMe)
     193                 :            : {
     194                 :            :         Buf->nIncreases++;
     195                 :            : #ifdef HAVE_BACKTRACE
     196                 :            :         StrBufBacktrace(Buf, 1);
     197                 :            : #endif
     198                 :            : }
     199                 :            : 
     200                 :            : void dbg_Init(StrBuf *Buf)
     201                 :            : {
     202                 :            :         Buf->nIncreases = 0;
     203                 :            :         Buf->bt[0] = '\0';
     204                 :            :         Buf->bt_lastinc[0] = '\0';
     205                 :            : #ifdef HAVE_BACKTRACE
     206                 :            :         StrBufBacktrace(Buf, 0);
     207                 :            : #endif
     208                 :            : }
     209                 :            : 
     210                 :            : #else
     211                 :            : /* void it... */
     212                 :            : #define dbg_FreeStrBuf(a, b)
     213                 :            : #define dbg_IncreaseBuf(a)
     214                 :            : #define dbg_Init(a)
     215                 :            : 
     216                 :            : #endif
     217                 :            : 
     218                 :            : /**
     219                 :            :  * @ingroup StrBuf
     220                 :            :  * @brief swaps the contents of two StrBufs
     221                 :            :  * this is to be used to have cheap switched between a work-buffer and a target buffer 
     222                 :            :  * @param A First one
     223                 :            :  * @param B second one
     224                 :            :  */
     225                 :         25 : static inline void SwapBuffers(StrBuf *A, StrBuf *B)
     226                 :            : {
     227                 :            :         StrBuf C;
     228                 :            : 
     229                 :         25 :         memcpy(&C, A, sizeof(*A));
     230                 :         25 :         memcpy(A, B, sizeof(*B));
     231                 :         25 :         memcpy(B, &C, sizeof(C));
     232                 :            : 
     233                 :         25 : }
     234                 :            : 
     235                 :            : /** 
     236                 :            :  * @ingroup StrBuf_Cast
     237                 :            :  * @brief Cast operator to Plain String 
     238                 :            :  * @note if the buffer is altered by StrBuf operations, this pointer may become 
     239                 :            :  *  invalid. So don't lean on it after altering the buffer!
     240                 :            :  *  Since this operation is considered cheap, rather call it often than risking
     241                 :            :  *  your pointer to become invalid!
     242                 :            :  * @param Str the string we want to get the c-string representation for
     243                 :            :  * @returns the Pointer to the Content. Don't mess with it!
     244                 :            :  */
     245                 :        298 : inline const char *ChrPtr(const StrBuf *Str)
     246                 :            : {
     247         [ -  + ]:        298 :         if (Str == NULL)
     248                 :          0 :                 return "";
     249                 :        298 :         return Str->buf;
     250                 :            : }
     251                 :            : 
     252                 :            : /**
     253                 :            :  * @ingroup StrBuf_Cast
     254                 :            :  * @brief since we know strlen()'s result, provide it here.
     255                 :            :  * @param Str the string to return the length to
     256                 :            :  * @returns contentlength of the buffer
     257                 :            :  */
     258                 :        484 : inline int StrLength(const StrBuf *Str)
     259                 :            : {
     260         [ +  - ]:        484 :         return (Str != NULL) ? Str->BufUsed : 0;
     261                 :            : }
     262                 :            : 
     263                 :            : /**
     264                 :            :  * @ingroup StrBuf_DeConstructors
     265                 :            :  * @brief local utility function to resize the buffer
     266                 :            :  * @param Buf the buffer whichs storage we should increase
     267                 :            :  * @param KeepOriginal should we copy the original buffer or just start over with a new one
     268                 :            :  * @param DestSize what should fit in after?
     269                 :            :  */
     270                 :         92 : static int IncreaseBuf(StrBuf *Buf, int KeepOriginal, int DestSize)
     271                 :            : {
     272                 :            :         char *NewBuf;
     273                 :         92 :         size_t NewSize = Buf->BufSize * 2;
     274                 :            : 
     275         [ -  + ]:         92 :         if (Buf->ConstBuf)
     276                 :          0 :                 return -1;
     277                 :            :                 
     278         [ +  + ]:         92 :         if (DestSize > 0)
     279         [ +  + ]:        126 :                 while (NewSize <= DestSize)
     280                 :         65 :                         NewSize *= 2;
     281                 :            : 
     282                 :         92 :         NewBuf= (char*) malloc(NewSize);
     283         [ -  + ]:         92 :         if (NewBuf == NULL)
     284                 :          0 :                 return -1;
     285                 :            : 
     286 [ +  + ][ +  + ]:         92 :         if (KeepOriginal && (Buf->BufUsed > 0))
     287                 :            :         {
     288                 :         27 :                 memcpy(NewBuf, Buf->buf, Buf->BufUsed);
     289                 :            :         }
     290                 :            :         else
     291                 :            :         {
     292                 :         65 :                 NewBuf[0] = '\0';
     293                 :         65 :                 Buf->BufUsed = 0;
     294                 :            :         }
     295                 :         92 :         free (Buf->buf);
     296                 :         92 :         Buf->buf = NewBuf;
     297                 :         92 :         Buf->BufSize = NewSize;
     298                 :            : 
     299                 :            :         dbg_IncreaseBuf(Buf);
     300                 :            : 
     301                 :         92 :         return Buf->BufSize;
     302                 :            : }
     303                 :            : 
     304                 :            : /**
     305                 :            :  * @ingroup StrBuf_DeConstructors
     306                 :            :  * @brief shrink / increase an _EMPTY_ buffer to NewSize. Buffercontent is thoroughly ignored and flushed.
     307                 :            :  * @param Buf Buffer to shrink (has to be empty)
     308                 :            :  * @param ThreshHold if the buffer is bigger then this, its readjusted
     309                 :            :  * @param NewSize if we Shrink it, how big are we going to be afterwards?
     310                 :            :  */
     311                 :          0 : void ReAdjustEmptyBuf(StrBuf *Buf, long ThreshHold, long NewSize)
     312                 :            : {
     313 [ #  # ][ #  # ]:          0 :         if ((Buf != NULL) && 
                 [ #  # ]
     314                 :          0 :             (Buf->BufUsed == 0) &&
     315                 :          0 :             (Buf->BufSize < ThreshHold)) {
     316                 :          0 :                 free(Buf->buf);
     317                 :          0 :                 Buf->buf = (char*) malloc(NewSize);
     318                 :          0 :                 Buf->BufUsed = 0;
     319                 :          0 :                 Buf->BufSize = NewSize;
     320                 :            :         }
     321                 :          0 : }
     322                 :            : 
     323                 :            : /**
     324                 :            :  * @ingroup StrBuf_DeConstructors
     325                 :            :  * @brief shrink long term buffers to their real size so they don't waste memory
     326                 :            :  * @param Buf buffer to shrink
     327                 :            :  * @param Force if not set, will just executed if the buffer is much to big; set for lifetime strings
     328                 :            :  * @returns physical size of the buffer
     329                 :            :  */
     330                 :          0 : long StrBufShrinkToFit(StrBuf *Buf, int Force)
     331                 :            : {
     332         [ #  # ]:          0 :         if (Buf == NULL)
     333                 :          0 :                 return -1;
     334 [ #  # ][ #  # ]:          0 :         if (Force || 
     335                 :          0 :             (Buf->BufUsed + (Buf->BufUsed / 3) > Buf->BufSize))
     336                 :            :         {
     337                 :          0 :                 char *TmpBuf = (char*) malloc(Buf->BufUsed + 1);
     338                 :          0 :                 memcpy (TmpBuf, Buf->buf, Buf->BufUsed + 1);
     339                 :          0 :                 Buf->BufSize = Buf->BufUsed + 1;
     340                 :          0 :                 free(Buf->buf);
     341                 :          0 :                 Buf->buf = TmpBuf;
     342                 :            :         }
     343                 :          0 :         return Buf->BufUsed;
     344                 :            : }
     345                 :            : 
     346                 :            : /**
     347                 :            :  * @ingroup StrBuf_DeConstructors
     348                 :            :  * @brief Allocate a new buffer with default buffer size
     349                 :            :  * @returns the new stringbuffer
     350                 :            :  */
     351                 :         79 : StrBuf* NewStrBuf(void)
     352                 :            : {
     353                 :            :         StrBuf *NewBuf;
     354                 :            : 
     355                 :         79 :         NewBuf = (StrBuf*) malloc(sizeof(StrBuf));
     356                 :         79 :         NewBuf->buf = (char*) malloc(BaseStrBufSize);
     357                 :         79 :         NewBuf->buf[0] = '\0';
     358                 :         79 :         NewBuf->BufSize = BaseStrBufSize;
     359                 :         79 :         NewBuf->BufUsed = 0;
     360                 :         79 :         NewBuf->ConstBuf = 0;
     361                 :            : 
     362                 :            :         dbg_Init (NewBuf);
     363                 :            : 
     364                 :         79 :         return NewBuf;
     365                 :            : }
     366                 :            : 
     367                 :            : /** 
     368                 :            :  * @ingroup StrBuf_DeConstructors
     369                 :            :  * @brief Copy Constructor; returns a duplicate of CopyMe
     370                 :            :  * @param CopyMe Buffer to faxmilate
     371                 :            :  * @returns the new stringbuffer
     372                 :            :  */
     373                 :         48 : StrBuf* NewStrBufDup(const StrBuf *CopyMe)
     374                 :            : {
     375                 :            :         StrBuf *NewBuf;
     376                 :            :         
     377         [ -  + ]:         48 :         if (CopyMe == NULL)
     378                 :          0 :                 return NewStrBuf();
     379                 :            : 
     380                 :         48 :         NewBuf = (StrBuf*) malloc(sizeof(StrBuf));
     381                 :         48 :         NewBuf->buf = (char*) malloc(CopyMe->BufSize);
     382                 :         48 :         memcpy(NewBuf->buf, CopyMe->buf, CopyMe->BufUsed + 1);
     383                 :         48 :         NewBuf->BufUsed = CopyMe->BufUsed;
     384                 :         48 :         NewBuf->BufSize = CopyMe->BufSize;
     385                 :         48 :         NewBuf->ConstBuf = 0;
     386                 :            : 
     387                 :            :         dbg_Init(NewBuf);
     388                 :            : 
     389                 :         48 :         return NewBuf;
     390                 :            : }
     391                 :            : 
     392                 :            : /** 
     393                 :            :  * @ingroup StrBuf_DeConstructors
     394                 :            :  * @brief Copy Constructor; CreateRelpaceMe will contain CopyFlushMe afterwards.
     395                 :            :  * @param NoMe if non-NULL, we will use that buffer as value; KeepOriginal will abused as len.
     396                 :            :  * @param CopyFlushMe Buffer to faxmilate if KeepOriginal, or to move into CreateRelpaceMe if !KeepOriginal.
     397                 :            :  * @param CreateRelpaceMe If NULL, will be created, else Flushed and filled CopyFlushMe 
     398                 :            :  * @param KeepOriginal should CopyFlushMe remain intact? or may we Steal its buffer?
     399                 :            :  * @returns the new stringbuffer
     400                 :            :  */
     401                 :          0 : void NewStrBufDupAppendFlush(StrBuf **CreateRelpaceMe, StrBuf *CopyFlushMe, const char *NoMe, int KeepOriginal)
     402                 :            : {
     403                 :            :         StrBuf *NewBuf;
     404                 :            :         
     405         [ #  # ]:          0 :         if (CreateRelpaceMe == NULL)
     406                 :          0 :                 return;
     407                 :            : 
     408         [ #  # ]:          0 :         if (NoMe != NULL)
     409                 :            :         {
     410         [ #  # ]:          0 :                 if (*CreateRelpaceMe != NULL)
     411                 :          0 :                         StrBufPlain(*CreateRelpaceMe, NoMe, KeepOriginal);
     412                 :            :                 else 
     413                 :          0 :                         *CreateRelpaceMe = NewStrBufPlain(NoMe, KeepOriginal);
     414                 :          0 :                 return;
     415                 :            :         }
     416                 :            : 
     417         [ #  # ]:          0 :         if (CopyFlushMe == NULL)
     418                 :            :         {
     419         [ #  # ]:          0 :                 if (*CreateRelpaceMe != NULL)
     420                 :          0 :                         FlushStrBuf(*CreateRelpaceMe);
     421                 :            :                 else 
     422                 :          0 :                         *CreateRelpaceMe = NewStrBuf();
     423                 :          0 :                 return;
     424                 :            :         }
     425                 :            : 
     426                 :            :         /* 
     427                 :            :          * Randomly Chosen: bigger than 64 chars is cheaper to swap the buffers instead of copying.
     428                 :            :          * else *CreateRelpaceMe may use more memory than needed in a longer term, CopyFlushMe might
     429                 :            :          * be a big IO-Buffer...
     430                 :            :          */
     431 [ #  # ][ #  # ]:          0 :         if (KeepOriginal || (StrLength(CopyFlushMe) < 256))
     432                 :            :         {
     433         [ #  # ]:          0 :                 if (*CreateRelpaceMe == NULL)
     434                 :            :                 {
     435                 :          0 :                         *CreateRelpaceMe = NewBuf = NewStrBufPlain(NULL, CopyFlushMe->BufUsed);
     436                 :            :                         dbg_Init(NewBuf);
     437                 :            :                 }
     438                 :            :                 else 
     439                 :            :                 {
     440                 :          0 :                         NewBuf = *CreateRelpaceMe;
     441                 :          0 :                         FlushStrBuf(NewBuf);
     442                 :            :                 }
     443                 :          0 :                 StrBufAppendBuf(NewBuf, CopyFlushMe, 0);
     444                 :            :         }
     445                 :            :         else
     446                 :            :         {
     447         [ #  # ]:          0 :                 if (*CreateRelpaceMe == NULL)
     448                 :            :                 {
     449                 :          0 :                         *CreateRelpaceMe = NewBuf = NewStrBufPlain(NULL, CopyFlushMe->BufUsed);
     450                 :            :                         dbg_Init(NewBuf);
     451                 :            :                 }
     452                 :            :                 else 
     453                 :          0 :                         NewBuf = *CreateRelpaceMe;
     454                 :          0 :                 SwapBuffers (NewBuf, CopyFlushMe);
     455                 :            :         }
     456         [ #  # ]:          0 :         if (!KeepOriginal)
     457                 :          0 :                 FlushStrBuf(CopyFlushMe);
     458                 :          0 :         return;
     459                 :            : }
     460                 :            : 
     461                 :            : /**
     462                 :            :  * @ingroup StrBuf_DeConstructors
     463                 :            :  * @brief create a new Buffer using an existing c-string
     464                 :            :  * this function should also be used if you want to pre-suggest
     465                 :            :  * the buffer size to allocate in conjunction with ptr == NULL
     466                 :            :  * @param ptr the c-string to copy; may be NULL to create a blank instance
     467                 :            :  * @param nChars How many chars should we copy; -1 if we should measure the length ourselves
     468                 :            :  * @returns the new stringbuffer
     469                 :            :  */
     470                 :        502 : StrBuf* NewStrBufPlain(const char* ptr, int nChars)
     471                 :            : {
     472                 :            :         StrBuf *NewBuf;
     473                 :        502 :         size_t Siz = BaseStrBufSize;
     474                 :            :         size_t CopySize;
     475                 :            : 
     476                 :        502 :         NewBuf = (StrBuf*) malloc(sizeof(StrBuf));
     477         [ -  + ]:        502 :         if (nChars < 0)
     478         [ #  # ]:          0 :                 CopySize = strlen((ptr != NULL)?ptr:"");
     479                 :            :         else
     480                 :        502 :                 CopySize = nChars;
     481                 :            : 
     482         [ +  + ]:       3532 :         while (Siz <= CopySize)
     483                 :       3030 :                 Siz *= 2;
     484                 :            : 
     485                 :        502 :         NewBuf->buf = (char*) malloc(Siz);
     486         [ -  + ]:        502 :         if (NewBuf->buf == NULL)
     487                 :            :         {
     488                 :          0 :                 free(NewBuf);
     489                 :          0 :                 return NULL;
     490                 :            :         }
     491                 :        502 :         NewBuf->BufSize = Siz;
     492         [ +  + ]:        502 :         if (ptr != NULL) {
     493                 :        221 :                 memcpy(NewBuf->buf, ptr, CopySize);
     494                 :        221 :                 NewBuf->buf[CopySize] = '\0';
     495                 :        221 :                 NewBuf->BufUsed = CopySize;
     496                 :            :         }
     497                 :            :         else {
     498                 :        281 :                 NewBuf->buf[0] = '\0';
     499                 :        281 :                 NewBuf->BufUsed = 0;
     500                 :            :         }
     501                 :        502 :         NewBuf->ConstBuf = 0;
     502                 :            : 
     503                 :            :         dbg_Init(NewBuf);
     504                 :            : 
     505                 :        502 :         return NewBuf;
     506                 :            : }
     507                 :            : 
     508                 :            : /**
     509                 :            :  * @ingroup StrBuf_DeConstructors
     510                 :            :  * @brief Set an existing buffer from a c-string
     511                 :            :  * @param Buf buffer to load
     512                 :            :  * @param ptr c-string to put into 
     513                 :            :  * @param nChars set to -1 if we should work 0-terminated
     514                 :            :  * @returns the new length of the string
     515                 :            :  */
     516                 :          4 : int StrBufPlain(StrBuf *Buf, const char* ptr, int nChars)
     517                 :            : {
     518                 :            :         size_t Siz;
     519                 :            :         size_t CopySize;
     520                 :            : 
     521         [ -  + ]:          4 :         if (Buf == NULL)
     522                 :          0 :                 return -1;
     523         [ -  + ]:          4 :         if (ptr == NULL) {
     524                 :          0 :                 FlushStrBuf(Buf);
     525                 :          0 :                 return -1;
     526                 :            :         }
     527                 :            : 
     528                 :          4 :         Siz = Buf->BufSize;
     529                 :            : 
     530         [ +  - ]:          4 :         if (nChars < 0)
     531                 :          4 :                 CopySize = strlen(ptr);
     532                 :            :         else
     533                 :          0 :                 CopySize = nChars;
     534                 :            : 
     535         [ +  + ]:          5 :         while (Siz <= CopySize)
     536                 :          1 :                 Siz *= 2;
     537                 :            : 
     538         [ +  + ]:          4 :         if (Siz != Buf->BufSize)
     539                 :          1 :                 IncreaseBuf(Buf, 0, Siz);
     540                 :          4 :         memcpy(Buf->buf, ptr, CopySize);
     541                 :          4 :         Buf->buf[CopySize] = '\0';
     542                 :          4 :         Buf->BufUsed = CopySize;
     543                 :          4 :         Buf->ConstBuf = 0;
     544                 :          4 :         return CopySize;
     545                 :            : }
     546                 :            : 
     547                 :            : 
     548                 :            : /**
     549                 :            :  * @ingroup StrBuf_DeConstructors
     550                 :            :  * @brief use strbuf as wrapper for a string constant for easy handling
     551                 :            :  * @param StringConstant a string to wrap
     552                 :            :  * @param SizeOfStrConstant should be sizeof(StringConstant)-1
     553                 :            :  */
     554                 :          0 : StrBuf* _NewConstStrBuf(const char* StringConstant, size_t SizeOfStrConstant)
     555                 :            : {
     556                 :            :         StrBuf *NewBuf;
     557                 :            : 
     558                 :          0 :         NewBuf = (StrBuf*) malloc(sizeof(StrBuf));
     559                 :          0 :         NewBuf->buf = (char*) StringConstant;
     560                 :          0 :         NewBuf->BufSize = SizeOfStrConstant;
     561                 :          0 :         NewBuf->BufUsed = SizeOfStrConstant;
     562                 :          0 :         NewBuf->ConstBuf = 1;
     563                 :            : 
     564                 :            :         dbg_Init(NewBuf);
     565                 :            : 
     566                 :          0 :         return NewBuf;
     567                 :            : }
     568                 :            : 
     569                 :            : 
     570                 :            : /**
     571                 :            :  * @ingroup StrBuf_DeConstructors
     572                 :            :  * @brief flush the content of a Buf; keep its struct
     573                 :            :  * @param buf Buffer to flush
     574                 :            :  */
     575                 :        176 : int FlushStrBuf(StrBuf *buf)
     576                 :            : {
     577         [ -  + ]:        176 :         if (buf == NULL)
     578                 :          0 :                 return -1;
     579         [ -  + ]:        176 :         if (buf->ConstBuf)
     580                 :          0 :                 return -1;       
     581                 :        176 :         buf->buf[0] ='\0';
     582                 :        176 :         buf->BufUsed = 0;
     583                 :        176 :         return 0;
     584                 :            : }
     585                 :            : 
     586                 :            : /**
     587                 :            :  * @ingroup StrBuf_DeConstructors
     588                 :            :  * @brief wipe the content of a Buf thoroughly (overwrite it -> expensive); keep its struct
     589                 :            :  * @param buf Buffer to wipe
     590                 :            :  */
     591                 :          0 : int FLUSHStrBuf(StrBuf *buf)
     592                 :            : {
     593         [ #  # ]:          0 :         if (buf == NULL)
     594                 :          0 :                 return -1;
     595         [ #  # ]:          0 :         if (buf->ConstBuf)
     596                 :          0 :                 return -1;
     597         [ #  # ]:          0 :         if (buf->BufUsed > 0) {
     598                 :          0 :                 memset(buf->buf, 0, buf->BufUsed);
     599                 :          0 :                 buf->BufUsed = 0;
     600                 :            :         }
     601                 :          0 :         return 0;
     602                 :            : }
     603                 :            : 
     604                 :            : #ifdef SIZE_DEBUG
     605                 :            : int hFreeDbglog = -1;
     606                 :            : #endif
     607                 :            : /**
     608                 :            :  * @ingroup StrBuf_DeConstructors
     609                 :            :  * @brief Release a Buffer
     610                 :            :  * Its a double pointer, so it can NULL your pointer
     611                 :            :  * so fancy SIG11 appear instead of random results
     612                 :            :  * @param FreeMe Pointer Pointer to the buffer to free
     613                 :            :  */
     614                 :        593 : void FreeStrBuf (StrBuf **FreeMe)
     615                 :            : {
     616         [ +  + ]:        593 :         if (*FreeMe == NULL)
     617                 :        161 :                 return;
     618                 :            : 
     619                 :            :         dbg_FreeStrBuf(FreeMe, 'F');
     620                 :            : 
     621         [ +  - ]:        432 :         if (!(*FreeMe)->ConstBuf) 
     622                 :        432 :                 free((*FreeMe)->buf);
     623                 :        432 :         free(*FreeMe);
     624                 :        593 :         *FreeMe = NULL;
     625                 :            : }
     626                 :            : 
     627                 :            : /**
     628                 :            :  * @ingroup StrBuf_DeConstructors
     629                 :            :  * @brief flatten a Buffer to the Char * we return 
     630                 :            :  * Its a double pointer, so it can NULL your pointer
     631                 :            :  * so fancy SIG11 appear instead of random results
     632                 :            :  * The Callee then owns the buffer and is responsible for freeing it.
     633                 :            :  * @param SmashMe Pointer Pointer to the buffer to release Buf from and free
     634                 :            :  * @returns the pointer of the buffer; Callee owns the memory thereafter.
     635                 :            :  */
     636                 :        194 : char *SmashStrBuf (StrBuf **SmashMe)
     637                 :            : {
     638                 :            :         char *Ret;
     639                 :            : 
     640 [ +  - ][ -  + ]:        194 :         if ((SmashMe == NULL) || (*SmashMe == NULL))
     641                 :          0 :                 return NULL;
     642                 :            :         
     643                 :            :         dbg_FreeStrBuf(SmashMe, 'S');
     644                 :            : 
     645                 :        194 :         Ret = (*SmashMe)->buf;
     646                 :        194 :         free(*SmashMe);
     647                 :        194 :         *SmashMe = NULL;
     648                 :        194 :         return Ret;
     649                 :            : }
     650                 :            : 
     651                 :            : /**
     652                 :            :  * @ingroup StrBuf_DeConstructors
     653                 :            :  * @brief Release the buffer
     654                 :            :  * If you want put your StrBuf into a Hash, use this as Destructor.
     655                 :            :  * @param VFreeMe untyped pointer to a StrBuf. be shure to do the right thing [TM]
     656                 :            :  */
     657                 :          0 : void HFreeStrBuf (void *VFreeMe)
     658                 :            : {
     659                 :          0 :         StrBuf *FreeMe = (StrBuf*)VFreeMe;
     660         [ #  # ]:          0 :         if (FreeMe == NULL)
     661                 :          0 :                 return;
     662                 :            : 
     663                 :            :         dbg_FreeStrBuf(SmashMe, 'H');
     664                 :            : 
     665         [ #  # ]:          0 :         if (!FreeMe->ConstBuf) 
     666                 :          0 :                 free(FreeMe->buf);
     667                 :          0 :         free(FreeMe);
     668                 :            : }
     669                 :            : 
     670                 :            : 
     671                 :            : /*******************************************************************************
     672                 :            :  *                      Simple string transformations                          *
     673                 :            :  *******************************************************************************/
     674                 :            : 
     675                 :            : /**
     676                 :            :  * @ingroup StrBuf
     677                 :            :  * @brief Wrapper around atol
     678                 :            :  */
     679                 :          0 : long StrTol(const StrBuf *Buf)
     680                 :            : {
     681         [ #  # ]:          0 :         if (Buf == NULL)
     682                 :          0 :                 return 0;
     683         [ #  # ]:          0 :         if(Buf->BufUsed > 0)
     684                 :          0 :                 return atol(Buf->buf);
     685                 :            :         else
     686                 :          0 :                 return 0;
     687                 :            : }
     688                 :            : 
     689                 :            : /**
     690                 :            :  * @ingroup StrBuf
     691                 :            :  * @brief Wrapper around atoi
     692                 :            :  */
     693                 :          0 : int StrToi(const StrBuf *Buf)
     694                 :            : {
     695         [ #  # ]:          0 :         if (Buf == NULL)
     696                 :          0 :                 return 0;
     697         [ #  # ]:          0 :         if (Buf->BufUsed > 0)
     698                 :          0 :                 return atoi(Buf->buf);
     699                 :            :         else
     700                 :          0 :                 return 0;
     701                 :            : }
     702                 :            : 
     703                 :            : /**
     704                 :            :  * @ingroup StrBuf
     705                 :            :  * @brief Checks to see if the string is a pure number 
     706                 :            :  * @param Buf The buffer to inspect
     707                 :            :  * @returns 1 if its a pure number, 0, if not.
     708                 :            :  */
     709                 :          0 : int StrBufIsNumber(const StrBuf *Buf) {
     710                 :            :         char * pEnd;
     711 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (Buf->BufUsed == 0)) {
     712                 :          0 :                 return 0;
     713                 :            :         }
     714                 :          0 :         strtoll(Buf->buf, &pEnd, 10);
     715         [ #  # ]:          0 :         if (pEnd == Buf->buf)
     716                 :          0 :                 return 0;
     717 [ #  # ][ #  # ]:          0 :         if ((pEnd != NULL) && (pEnd == Buf->buf + Buf->BufUsed))
     718                 :          0 :                 return 1;
     719         [ #  # ]:          0 :         if (Buf->buf == pEnd)
     720                 :          0 :                 return 0;
     721                 :          0 :         return 0;
     722                 :            : } 
     723                 :            : 
     724                 :            : /**
     725                 :            :  * @ingroup StrBuf_Filler
     726                 :            :  * @brief modifies a Single char of the Buf
     727                 :            :  * You can point to it via char* or a zero-based integer
     728                 :            :  * @param Buf The buffer to manipulate
     729                 :            :  * @param ptr char* to zero; use NULL if unused
     730                 :            :  * @param nThChar zero based pointer into the string; use -1 if unused
     731                 :            :  * @param PeekValue The Character to place into the position
     732                 :            :  */
     733                 :          0 : long StrBufPeek(StrBuf *Buf, const char* ptr, long nThChar, char PeekValue)
     734                 :            : {
     735         [ #  # ]:          0 :         if (Buf == NULL)
     736                 :          0 :                 return -1;
     737         [ #  # ]:          0 :         if (ptr != NULL)
     738                 :          0 :                 nThChar = ptr - Buf->buf;
     739 [ #  # ][ #  # ]:          0 :         if ((nThChar < 0) || (nThChar > Buf->BufUsed))
     740                 :          0 :                 return -1;
     741                 :          0 :         Buf->buf[nThChar] = PeekValue;
     742                 :          0 :         return nThChar;
     743                 :            : }
     744                 :            : 
     745                 :            : /**
     746                 :            :  * @ingroup StrBuf_Filler
     747                 :            :  * @brief modifies a range of chars of the Buf
     748                 :            :  * You can point to it via char* or a zero-based integer
     749                 :            :  * @param Buf The buffer to manipulate
     750                 :            :  * @param ptr char* to zero; use NULL if unused
     751                 :            :  * @param nThChar zero based pointer into the string; use -1 if unused
     752                 :            :  * @param nChars how many chars are to be flushed?
     753                 :            :  * @param PookValue The Character to place into that area
     754                 :            :  */
     755                 :          0 : long StrBufPook(StrBuf *Buf, const char* ptr, long nThChar, long nChars, char PookValue)
     756                 :            : {
     757         [ #  # ]:          0 :         if (Buf == NULL)
     758                 :          0 :                 return -1;
     759         [ #  # ]:          0 :         if (ptr != NULL)
     760                 :          0 :                 nThChar = ptr - Buf->buf;
     761 [ #  # ][ #  # ]:          0 :         if ((nThChar < 0) || (nThChar > Buf->BufUsed))
     762                 :          0 :                 return -1;
     763         [ #  # ]:          0 :         if (nThChar + nChars > Buf->BufUsed)
     764                 :          0 :                 nChars =  Buf->BufUsed - nThChar;
     765                 :            : 
     766                 :          0 :         memset(Buf->buf + nThChar, PookValue, nChars);
     767                 :            :         /* just to be shure... */
     768                 :          0 :         Buf->buf[Buf->BufUsed] = 0;
     769                 :          0 :         return nChars;
     770                 :            : }
     771                 :            : 
     772                 :            : /**
     773                 :            :  * @ingroup StrBuf_Filler
     774                 :            :  * @brief Append a StringBuffer to the buffer
     775                 :            :  * @param Buf Buffer to modify
     776                 :            :  * @param AppendBuf Buffer to copy at the end of our buffer
     777                 :            :  * @param Offset Should we start copying from an offset?
     778                 :            :  */
     779                 :        227 : void StrBufAppendBuf(StrBuf *Buf, const StrBuf *AppendBuf, unsigned long Offset)
     780                 :            : {
     781 [ +  - ][ +  - ]:        227 :         if ((AppendBuf == NULL) || (Buf == NULL) || (AppendBuf->buf == NULL))
                 [ -  + ]
     782                 :          0 :                 return;
     783                 :            : 
     784         [ +  + ]:        227 :         if (Buf->BufSize - Offset < AppendBuf->BufUsed + Buf->BufUsed + 1)
     785                 :         14 :                 IncreaseBuf(Buf, 
     786                 :            :                             (Buf->BufUsed > 0), 
     787                 :         14 :                             AppendBuf->BufUsed + Buf->BufUsed);
     788                 :            : 
     789                 :        454 :         memcpy(Buf->buf + Buf->BufUsed, 
     790                 :            :                AppendBuf->buf + Offset, 
     791                 :        227 :                AppendBuf->BufUsed - Offset);
     792                 :        227 :         Buf->BufUsed += AppendBuf->BufUsed - Offset;
     793                 :        227 :         Buf->buf[Buf->BufUsed] = '\0';
     794                 :            : }
     795                 :            : 
     796                 :            : 
     797                 :            : /**
     798                 :            :  * @ingroup StrBuf_Filler
     799                 :            :  * @brief Append a C-String to the buffer
     800                 :            :  * @param Buf Buffer to modify
     801                 :            :  * @param AppendBuf Buffer to copy at the end of our buffer
     802                 :            :  * @param AppendSize number of bytes to copy; set to -1 if we should count it in advance
     803                 :            :  * @param Offset Should we start copying from an offset?
     804                 :            :  */
     805                 :        844 : void StrBufAppendBufPlain(StrBuf *Buf, const char *AppendBuf, long AppendSize, unsigned long Offset)
     806                 :            : {
     807                 :            :         long aps;
     808                 :            :         long BufSizeRequired;
     809                 :            : 
     810 [ +  - ][ -  + ]:        844 :         if ((AppendBuf == NULL) || (Buf == NULL))
     811                 :          0 :                 return;
     812                 :            : 
     813         [ +  + ]:        844 :         if (AppendSize < 0 )
     814                 :         30 :                 aps = strlen(AppendBuf + Offset);
     815                 :            :         else
     816                 :        814 :                 aps = AppendSize - Offset;
     817                 :            : 
     818                 :        844 :         BufSizeRequired = Buf->BufUsed + aps + 1;
     819         [ +  + ]:        844 :         if (Buf->BufSize <= BufSizeRequired)
     820                 :         32 :                 IncreaseBuf(Buf, (Buf->BufUsed > 0), BufSizeRequired);
     821                 :            : 
     822                 :        844 :         memcpy(Buf->buf + Buf->BufUsed, 
     823                 :            :                AppendBuf + Offset, 
     824                 :            :                aps);
     825                 :        844 :         Buf->BufUsed += aps;
     826                 :        844 :         Buf->buf[Buf->BufUsed] = '\0';
     827                 :            : }
     828                 :            : 
     829                 :            : /**
     830                 :            :  * @ingroup StrBuf_Filler
     831                 :            :  * @brief sprintf like function appending the formated string to the buffer
     832                 :            :  * vsnprintf version to wrap into own calls
     833                 :            :  * @param Buf Buffer to extend by format and Params
     834                 :            :  * @param format printf alike format to add
     835                 :            :  * @param ap va_list containing the items for format
     836                 :            :  */
     837                 :          0 : void StrBufVAppendPrintf(StrBuf *Buf, const char *format, va_list ap)
     838                 :            : {
     839                 :            :         va_list apl;
     840                 :            :         size_t BufSize;
     841                 :            :         size_t nWritten;
     842                 :            :         size_t Offset;
     843                 :            :         size_t newused;
     844                 :            : 
     845 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL)  || (format == NULL))
     846                 :          0 :                 return;
     847                 :            : 
     848                 :          0 :         BufSize = Buf->BufSize;
     849                 :          0 :         nWritten = Buf->BufSize + 1;
     850                 :          0 :         Offset = Buf->BufUsed;
     851                 :          0 :         newused = Offset + nWritten;
     852                 :            :         
     853         [ #  # ]:          0 :         while (newused >= BufSize) {
     854                 :          0 :                 va_copy(apl, ap);
     855                 :          0 :                 nWritten = vsnprintf(Buf->buf + Offset, 
     856                 :          0 :                                      Buf->BufSize - Offset, 
     857                 :            :                                      format, apl);
     858                 :          0 :                 va_end(apl);
     859                 :          0 :                 newused = Offset + nWritten;
     860         [ #  # ]:          0 :                 if (newused >= Buf->BufSize) {
     861                 :          0 :                         IncreaseBuf(Buf, 1, newused);
     862                 :          0 :                         newused = Buf->BufSize + 1;
     863                 :            :                 }
     864                 :            :                 else {
     865                 :          0 :                         Buf->BufUsed = Offset + nWritten;
     866                 :          0 :                         BufSize = Buf->BufSize;
     867                 :            :                 }
     868                 :            : 
     869                 :            :         }
     870                 :            : }
     871                 :            : 
     872                 :            : /**
     873                 :            :  * @ingroup StrBuf_Filler
     874                 :            :  * @brief sprintf like function appending the formated string to the buffer
     875                 :            :  * @param Buf Buffer to extend by format and Params
     876                 :            :  * @param format printf alike format to add
     877                 :            :  */
     878                 :          9 : void StrBufAppendPrintf(StrBuf *Buf, const char *format, ...)
     879                 :            : {
     880                 :            :         size_t BufSize;
     881                 :            :         size_t nWritten;
     882                 :            :         size_t Offset;
     883                 :            :         size_t newused;
     884                 :            :         va_list arg_ptr;
     885                 :            :         
     886 [ +  - ][ -  + ]:          9 :         if ((Buf == NULL)  || (format == NULL))
     887                 :          0 :                 return;
     888                 :            : 
     889                 :          9 :         BufSize = Buf->BufSize;
     890                 :          9 :         nWritten = Buf->BufSize + 1;
     891                 :          9 :         Offset = Buf->BufUsed;
     892                 :          9 :         newused = Offset + nWritten;
     893                 :            : 
     894         [ +  + ]:         23 :         while (newused >= BufSize) {
     895                 :         14 :                 va_start(arg_ptr, format);
     896                 :         28 :                 nWritten = vsnprintf(Buf->buf + Buf->BufUsed, 
     897                 :         14 :                                      Buf->BufSize - Buf->BufUsed, 
     898                 :            :                                      format, arg_ptr);
     899                 :         14 :                 va_end(arg_ptr);
     900                 :         14 :                 newused = Buf->BufUsed + nWritten;
     901         [ +  + ]:         14 :                 if (newused >= Buf->BufSize) {
     902                 :          5 :                         IncreaseBuf(Buf, 1, newused);
     903                 :          5 :                         newused = Buf->BufSize + 1;
     904                 :            :                 }
     905                 :            :                 else {
     906                 :          9 :                         Buf->BufUsed += nWritten;
     907                 :          9 :                         BufSize = Buf->BufSize;
     908                 :            :                 }
     909                 :            : 
     910                 :            :         }
     911                 :            : }
     912                 :            : 
     913                 :            : /**
     914                 :            :  * @ingroup StrBuf_Filler
     915                 :            :  * @brief sprintf like function putting the formated string into the buffer
     916                 :            :  * @param Buf Buffer to extend by format and Parameters
     917                 :            :  * @param format printf alike format to add
     918                 :            :  */
     919                 :        103 : void StrBufPrintf(StrBuf *Buf, const char *format, ...)
     920                 :            : {
     921                 :            :         size_t nWritten;
     922                 :            :         va_list arg_ptr;
     923                 :            :         
     924 [ +  - ][ -  + ]:        103 :         if ((Buf == NULL)  || (format == NULL))
     925                 :          0 :                 return;
     926                 :            : 
     927                 :        103 :         nWritten = Buf->BufSize + 1;
     928         [ +  + ]:        225 :         while (nWritten >= Buf->BufSize) {
     929                 :        122 :                 va_start(arg_ptr, format);
     930                 :        122 :                 nWritten = vsnprintf(Buf->buf, Buf->BufSize, format, arg_ptr);
     931                 :        122 :                 va_end(arg_ptr);
     932         [ +  + ]:        122 :                 if (nWritten >= Buf->BufSize) {
     933                 :         19 :                         IncreaseBuf(Buf, 0, 0);
     934                 :         19 :                         nWritten = Buf->BufSize + 1;
     935                 :         19 :                         continue;
     936                 :            :                 }
     937                 :        103 :                 Buf->BufUsed = nWritten ;
     938                 :            :         }
     939                 :            : }
     940                 :            : 
     941                 :            : /**
     942                 :            :  * @ingroup StrBuf_Filler
     943                 :            :  * @brief Callback for cURL to append the webserver reply to a buffer
     944                 :            :  * @param ptr pre-defined by the cURL API; see man 3 curl for mre info
     945                 :            :  * @param size pre-defined by the cURL API; see man 3 curl for mre info
     946                 :            :  * @param nmemb pre-defined by the cURL API; see man 3 curl for mre info
     947                 :            :  * @param stream pre-defined by the cURL API; see man 3 curl for mre info
     948                 :            :  */
     949                 :          0 : size_t CurlFillStrBuf_callback(void *ptr, size_t size, size_t nmemb, void *stream)
     950                 :            : {
     951                 :            : 
     952                 :            :         StrBuf *Target;
     953                 :            : 
     954                 :          0 :         Target = stream;
     955         [ #  # ]:          0 :         if (ptr == NULL)
     956                 :          0 :                 return 0;
     957                 :            : 
     958                 :          0 :         StrBufAppendBufPlain(Target, ptr, size * nmemb, 0);
     959                 :          0 :         return size * nmemb;
     960                 :            : }
     961                 :            : 
     962                 :            : 
     963                 :            : /**
     964                 :            :  * @ingroup StrBuf
     965                 :            :  * @brief extracts a substring from Source into dest
     966                 :            :  * @param dest buffer to place substring into
     967                 :            :  * @param Source string to copy substring from
     968                 :            :  * @param Offset chars to skip from start
     969                 :            :  * @param nChars number of chars to copy
     970                 :            :  * @returns the number of chars copied; may be different from nChars due to the size of Source
     971                 :            :  */
     972                 :          0 : int StrBufSub(StrBuf *dest, const StrBuf *Source, unsigned long Offset, size_t nChars)
     973                 :            : {
     974                 :            :         size_t NCharsRemain;
     975         [ #  # ]:          0 :         if (Offset > Source->BufUsed)
     976                 :            :         {
     977         [ #  # ]:          0 :                 if (dest != NULL)
     978                 :          0 :                         FlushStrBuf(dest);
     979                 :          0 :                 return 0;
     980                 :            :         }
     981         [ #  # ]:          0 :         if (Offset + nChars < Source->BufUsed)
     982                 :            :         {
     983         [ #  # ]:          0 :                 if (nChars >= dest->BufSize)
     984                 :          0 :                         IncreaseBuf(dest, 0, nChars + 1);
     985                 :          0 :                 memcpy(dest->buf, Source->buf + Offset, nChars);
     986                 :          0 :                 dest->BufUsed = nChars;
     987                 :          0 :                 dest->buf[dest->BufUsed] = '\0';
     988                 :          0 :                 return nChars;
     989                 :            :         }
     990                 :          0 :         NCharsRemain = Source->BufUsed - Offset;
     991         [ #  # ]:          0 :         if (NCharsRemain  >= dest->BufSize)
     992                 :          0 :                 IncreaseBuf(dest, 0, NCharsRemain + 1);
     993                 :          0 :         memcpy(dest->buf, Source->buf + Offset, NCharsRemain);
     994                 :          0 :         dest->BufUsed = NCharsRemain;
     995                 :          0 :         dest->buf[dest->BufUsed] = '\0';
     996                 :          0 :         return NCharsRemain;
     997                 :            : }
     998                 :            : 
     999                 :            : /**
    1000                 :            :  * @ingroup StrBuf
    1001                 :            :  * @brief Cut nChars from the start of the string
    1002                 :            :  * @param Buf Buffer to modify
    1003                 :            :  * @param nChars how many chars should be skipped?
    1004                 :            :  */
    1005                 :          2 : void StrBufCutLeft(StrBuf *Buf, int nChars)
    1006                 :            : {
    1007 [ +  - ][ -  + ]:          2 :         if ((Buf == NULL) || (Buf->BufUsed == 0)) return;
    1008         [ -  + ]:          2 :         if (nChars >= Buf->BufUsed) {
    1009                 :          0 :                 FlushStrBuf(Buf);
    1010                 :          0 :                 return;
    1011                 :            :         }
    1012                 :          2 :         memmove(Buf->buf, Buf->buf + nChars, Buf->BufUsed - nChars);
    1013                 :          2 :         Buf->BufUsed -= nChars;
    1014                 :          2 :         Buf->buf[Buf->BufUsed] = '\0';
    1015                 :            : }
    1016                 :            : 
    1017                 :            : /**
    1018                 :            :  * @ingroup StrBuf
    1019                 :            :  * @brief Cut the trailing n Chars from the string
    1020                 :            :  * @param Buf Buffer to modify
    1021                 :            :  * @param nChars how many chars should be trunkated?
    1022                 :            :  */
    1023                 :          0 : void StrBufCutRight(StrBuf *Buf, int nChars)
    1024                 :            : {
    1025 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (Buf->BufUsed == 0)) return;
    1026         [ #  # ]:          0 :         if (nChars >= Buf->BufUsed) {
    1027                 :          0 :                 FlushStrBuf(Buf);
    1028                 :          0 :                 return;
    1029                 :            :         }
    1030                 :          0 :         Buf->BufUsed -= nChars;
    1031                 :          0 :         Buf->buf[Buf->BufUsed] = '\0';
    1032                 :            : }
    1033                 :            : 
    1034                 :            : /**
    1035                 :            :  * @ingroup StrBuf
    1036                 :            :  * @brief Cut the string after n Chars
    1037                 :            :  * @param Buf Buffer to modify
    1038                 :            :  * @param AfternChars after how many chars should we trunkate the string?
    1039                 :            :  * @param At if non-null and points inside of our string, cut it there.
    1040                 :            :  */
    1041                 :          0 : void StrBufCutAt(StrBuf *Buf, int AfternChars, const char *At)
    1042                 :            : {
    1043 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (Buf->BufUsed == 0)) return;
    1044         [ #  # ]:          0 :         if (At != NULL){
    1045                 :          0 :                 AfternChars = At - Buf->buf;
    1046                 :            :         }
    1047                 :            : 
    1048 [ #  # ][ #  # ]:          0 :         if ((AfternChars < 0) || (AfternChars >= Buf->BufUsed))
    1049                 :          0 :                 return;
    1050                 :          0 :         Buf->BufUsed = AfternChars;
    1051                 :          0 :         Buf->buf[Buf->BufUsed] = '\0';
    1052                 :            : }
    1053                 :            : 
    1054                 :            : 
    1055                 :            : /**
    1056                 :            :  * @ingroup StrBuf
    1057                 :            :  * @brief Strip leading and trailing spaces from a string; with premeasured and adjusted length.
    1058                 :            :  * @param Buf the string to modify
    1059                 :            :  */
    1060                 :          0 : void StrBufTrim(StrBuf *Buf)
    1061                 :            : {
    1062                 :          0 :         int delta = 0;
    1063 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (Buf->BufUsed == 0)) return;
    1064                 :            : 
    1065   [ #  #  #  # ]:          0 :         while ((Buf->BufUsed > 0) &&
    1066                 :          0 :                isspace(Buf->buf[Buf->BufUsed - 1]))
    1067                 :            :         {
    1068                 :          0 :                 Buf->BufUsed --;
    1069                 :            :         }
    1070                 :          0 :         Buf->buf[Buf->BufUsed] = '\0';
    1071                 :            : 
    1072         [ #  # ]:          0 :         if (Buf->BufUsed == 0) return;
    1073                 :            : 
    1074 [ #  # ][ #  # ]:          0 :         while ((Buf->BufUsed > delta) && (isspace(Buf->buf[delta]))){
    1075                 :          0 :                 delta ++;
    1076                 :            :         }
    1077         [ #  # ]:          0 :         if (delta > 0) StrBufCutLeft(Buf, delta);
    1078                 :            : }
    1079                 :            : /**
    1080                 :            :  * @ingroup StrBuf
    1081                 :            :  * @brief changes all spaces in the string  (tab, linefeed...) to Blank (0x20)
    1082                 :            :  * @param Buf the string to modify
    1083                 :            :  */
    1084                 :          0 : void StrBufSpaceToBlank(StrBuf *Buf)
    1085                 :            : {
    1086                 :            :         char *pche, *pch;
    1087                 :            : 
    1088 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (Buf->BufUsed == 0)) return;
    1089                 :            : 
    1090                 :          0 :         pch = Buf->buf;
    1091                 :          0 :         pche = pch + Buf->BufUsed;
    1092         [ #  # ]:          0 :         while (pch < pche) 
    1093                 :            :         {
    1094         [ #  # ]:          0 :                 if (isspace(*pch))
    1095                 :          0 :                         *pch = ' ';
    1096                 :          0 :                 pch ++;
    1097                 :            :         }
    1098                 :            : }
    1099                 :            : 
    1100                 :          0 : void StrBufStripAllBut(StrBuf *Buf, char leftboundary, char rightboundary)
    1101                 :            : {
    1102                 :            :         const char *pBuff;
    1103                 :            :         const char *pLeft;
    1104                 :            :         const char *pRight;
    1105                 :            : 
    1106         [ #  # ]:          0 :         if (Buf == NULL)
    1107                 :          0 :                 return;
    1108                 :          0 :         pLeft = pBuff = Buf->buf;
    1109         [ #  # ]:          0 :         while (pBuff != NULL) {
    1110                 :          0 :                 pLeft = pBuff;
    1111                 :          0 :                 pBuff = strchr(pBuff, leftboundary);
    1112         [ #  # ]:          0 :                 if (pBuff != NULL)
    1113                 :          0 :                         pBuff++;
    1114                 :            :         }
    1115                 :            :                 
    1116         [ #  # ]:          0 :         if (pLeft != NULL)
    1117                 :          0 :                 pBuff = pLeft;
    1118                 :            :         else
    1119                 :          0 :                 pBuff = Buf->buf;
    1120                 :          0 :         pRight = strchr(pBuff, rightboundary);
    1121         [ #  # ]:          0 :         if (pRight != NULL)
    1122                 :          0 :                 StrBufCutAt(Buf, 0, pRight);
    1123         [ #  # ]:          0 :         if (pLeft != NULL)
    1124                 :          0 :                 StrBufCutLeft(Buf, pLeft - Buf->buf);
    1125                 :            : }
    1126                 :            : 
    1127                 :            : 
    1128                 :            : /**
    1129                 :            :  * @ingroup StrBuf_Filler
    1130                 :            :  * @brief uppercase the contents of a buffer
    1131                 :            :  * @param Buf the buffer to translate
    1132                 :            :  */
    1133                 :          0 : void StrBufUpCase(StrBuf *Buf) 
    1134                 :            : {
    1135                 :            :         char *pch, *pche;
    1136                 :            : 
    1137 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (Buf->BufUsed == 0)) return;
    1138                 :            : 
    1139                 :          0 :         pch = Buf->buf;
    1140                 :          0 :         pche = pch + Buf->BufUsed;
    1141         [ #  # ]:          0 :         while (pch < pche) {
    1142                 :          0 :                 *pch = toupper(*pch);
    1143                 :          0 :                 pch ++;
    1144                 :            :         }
    1145                 :            : }
    1146                 :            : 
    1147                 :            : 
    1148                 :            : /**
    1149                 :            :  * @ingroup StrBuf_Filler
    1150                 :            :  * @brief lowercase the contents of a buffer
    1151                 :            :  * @param Buf the buffer to translate
    1152                 :            :  */
    1153                 :          0 : void StrBufLowerCase(StrBuf *Buf) 
    1154                 :            : {
    1155                 :            :         char *pch, *pche;
    1156                 :            : 
    1157 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (Buf->BufUsed == 0)) return;
    1158                 :            : 
    1159                 :          0 :         pch = Buf->buf;
    1160                 :          0 :         pche = pch + Buf->BufUsed;
    1161         [ #  # ]:          0 :         while (pch < pche) {
    1162                 :          0 :                 *pch = tolower(*pch);
    1163                 :          0 :                 pch ++;
    1164                 :            :         }
    1165                 :            : }
    1166                 :            : 
    1167                 :            : 
    1168                 :            : /*******************************************************************************
    1169                 :            :  *           a tokenizer that kills, maims, and destroys                       *
    1170                 :            :  *******************************************************************************/
    1171                 :            : 
    1172                 :            : /**
    1173                 :            :  * @ingroup StrBuf_Tokenizer
    1174                 :            :  * @brief Replace a token at a given place with a given length by another token with given length
    1175                 :            :  * @param Buf String where to work on
    1176                 :            :  * @param where where inside of the Buf is the search-token
    1177                 :            :  * @param HowLong How long is the token to be replaced
    1178                 :            :  * @param Repl Token to insert at 'where'
    1179                 :            :  * @param ReplLen Length of repl
    1180                 :            :  * @returns -1 if fail else length of resulting Buf
    1181                 :            :  */
    1182                 :          0 : int StrBufReplaceToken(StrBuf *Buf, long where, long HowLong, 
    1183                 :            :                        const char *Repl, long ReplLen)
    1184                 :            : {
    1185                 :            : 
    1186 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || 
                 [ #  # ]
    1187                 :          0 :             (where > Buf->BufUsed) ||
    1188                 :          0 :             (where + HowLong > Buf->BufUsed))
    1189                 :          0 :                 return -1;
    1190                 :            : 
    1191         [ #  # ]:          0 :         if (where + ReplLen - HowLong > Buf->BufSize)
    1192         [ #  # ]:          0 :                 if (IncreaseBuf(Buf, 1, Buf->BufUsed + ReplLen) < 0)
    1193                 :          0 :                         return -1;
    1194                 :            : 
    1195                 :          0 :         memmove(Buf->buf + where + ReplLen, 
    1196                 :          0 :                 Buf->buf + where + HowLong,
    1197                 :          0 :                 Buf->BufUsed - where - HowLong);
    1198                 :            :                                                 
    1199                 :          0 :         memcpy(Buf->buf + where, 
    1200                 :            :                Repl, ReplLen);
    1201                 :            : 
    1202                 :          0 :         Buf->BufUsed += ReplLen - HowLong;
    1203                 :            : 
    1204                 :          0 :         return Buf->BufUsed;
    1205                 :            : }
    1206                 :            : 
    1207                 :            : /**
    1208                 :            :  * @ingroup StrBuf_Tokenizer
    1209                 :            :  * @brief Counts the numbmer of tokens in a buffer
    1210                 :            :  * @param source String to count tokens in
    1211                 :            :  * @param tok    Tokenizer char to count
    1212                 :            :  * @returns numbers of tokenizer chars found
    1213                 :            :  */
    1214                 :          0 : int StrBufNum_tokens(const StrBuf *source, char tok)
    1215                 :            : {
    1216                 :            :         char *pch, *pche;
    1217                 :            :         long NTokens;
    1218 [ #  # ][ #  # ]:          0 :         if ((source == NULL) || (source->BufUsed == 0))
    1219                 :          0 :                 return 0;
    1220 [ #  # ][ #  # ]:          0 :         if ((source->BufUsed == 1) && (*source->buf == tok))
    1221                 :          0 :                 return 2;
    1222                 :          0 :         NTokens = 1;
    1223                 :          0 :         pch = source->buf;
    1224                 :          0 :         pche = pch + source->BufUsed;
    1225         [ #  # ]:          0 :         while (pch < pche)
    1226                 :            :         {
    1227         [ #  # ]:          0 :                 if (*pch == tok)
    1228                 :          0 :                         NTokens ++;
    1229                 :          0 :                 pch ++;
    1230                 :            :         }
    1231                 :          0 :         return NTokens;
    1232                 :            : }
    1233                 :            : 
    1234                 :            : /**
    1235                 :            :  * @ingroup StrBuf_Tokenizer
    1236                 :            :  * @brief a string tokenizer
    1237                 :            :  * @param Source StringBuffer to read into
    1238                 :            :  * @param parmnum n'th Parameter to remove
    1239                 :            :  * @param separator tokenizer character
    1240                 :            :  * @returns -1 if not found, else length of token.
    1241                 :            :  */
    1242                 :          0 : int StrBufRemove_token(StrBuf *Source, int parmnum, char separator)
    1243                 :            : {
    1244                 :            :         int ReducedBy;
    1245                 :            :         char *d, *s, *end;              /* dest, source */
    1246                 :          0 :         int count = 0;
    1247                 :            : 
    1248                 :            :         /* Find desired @parameter */
    1249                 :          0 :         end = Source->buf + Source->BufUsed;
    1250                 :          0 :         d = Source->buf;
    1251 [ #  # ][ #  # ]:          0 :         while ((d <= end) && 
    1252                 :            :                (count < parmnum))
    1253                 :            :         {
    1254                 :            :                 /* End of string, bail! */
    1255         [ #  # ]:          0 :                 if (!*d) {
    1256                 :          0 :                         d = NULL;
    1257                 :          0 :                         break;
    1258                 :            :                 }
    1259         [ #  # ]:          0 :                 if (*d == separator) {
    1260                 :          0 :                         count++;
    1261                 :            :                 }
    1262                 :          0 :                 d++;
    1263                 :            :         }
    1264 [ #  # ][ #  # ]:          0 :         if ((d == NULL) || (d >= end))
    1265                 :          0 :                 return 0;               /* @Parameter not found */
    1266                 :            : 
    1267                 :            :         /* Find next @parameter */
    1268                 :          0 :         s = d;
    1269 [ #  # ][ #  # ]:          0 :         while ((s <= end) && 
                 [ #  # ]
    1270                 :          0 :                (*s && *s != separator))
    1271                 :            :         {
    1272                 :          0 :                 s++;
    1273                 :            :         }
    1274         [ #  # ]:          0 :         if (*s == separator)
    1275                 :          0 :                 s++;
    1276                 :          0 :         ReducedBy = d - s;
    1277                 :            : 
    1278                 :            :         /* Hack and slash */
    1279         [ #  # ]:          0 :         if (s >= end) {
    1280                 :          0 :                 return 0;
    1281                 :            :         }
    1282         [ #  # ]:          0 :         else if (*s) {
    1283                 :          0 :                 memmove(d, s, Source->BufUsed - (s - Source->buf));
    1284                 :          0 :                 Source->BufUsed += ReducedBy;
    1285                 :          0 :                 Source->buf[Source->BufUsed] = '\0';
    1286                 :            :         }
    1287         [ #  # ]:          0 :         else if (d == Source->buf) {
    1288                 :          0 :                 *d = 0;
    1289                 :          0 :                 Source->BufUsed = 0;
    1290                 :            :         }
    1291                 :            :         else {
    1292                 :          0 :                 *--d = '\0';
    1293                 :          0 :                 Source->BufUsed += ReducedBy;
    1294                 :            :         }
    1295                 :            :         /*
    1296                 :            :         while (*s) {
    1297                 :            :                 *d++ = *s++;
    1298                 :            :         }
    1299                 :            :         *d = 0;
    1300                 :            :         */
    1301                 :          0 :         return ReducedBy;
    1302                 :            : }
    1303                 :            : 
    1304                 :            : 
    1305                 :            : /**
    1306                 :            :  * @ingroup StrBuf_Tokenizer
    1307                 :            :  * @brief a string tokenizer
    1308                 :            :  * @param dest Destination StringBuffer
    1309                 :            :  * @param Source StringBuffer to read into
    1310                 :            :  * @param parmnum n'th Parameter to extract
    1311                 :            :  * @param separator tokenizer character
    1312                 :            :  * @returns -1 if not found, else length of token.
    1313                 :            :  */
    1314                 :         20 : int StrBufExtract_token(StrBuf *dest, const StrBuf *Source, int parmnum, char separator)
    1315                 :            : {
    1316                 :            :         const char *s, *e;              //* source * /
    1317                 :         20 :         int len = 0;                    //* running total length of extracted string * /
    1318                 :         20 :         int current_token = 0;          //* token currently being processed * /
    1319                 :            :          
    1320         [ +  - ]:         20 :         if (dest != NULL) {
    1321                 :         20 :                 dest->buf[0] = '\0';
    1322                 :         20 :                 dest->BufUsed = 0;
    1323                 :            :         }
    1324                 :            :         else
    1325                 :          0 :                 return(-1);
    1326                 :            : 
    1327 [ +  - ][ -  + ]:         20 :         if ((Source == NULL) || (Source->BufUsed ==0)) {
    1328                 :          0 :                 return(-1);
    1329                 :            :         }
    1330                 :         20 :         s = Source->buf;
    1331                 :         20 :         e = s + Source->BufUsed;
    1332                 :            : 
    1333                 :            :         //cit_backtrace();
    1334                 :            :         //lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
    1335                 :            : 
    1336 [ +  + ][ +  - ]:        620 :         while ((s<e) && !IsEmptyStr(s)) {
    1337         [ +  + ]:        600 :                 if (*s == separator) {
    1338                 :         60 :                         ++current_token;
    1339                 :            :                 }
    1340         [ -  + ]:        600 :                 if (len >= dest->BufSize) {
    1341                 :          0 :                         dest->BufUsed = len;
    1342         [ #  # ]:          0 :                         if (IncreaseBuf(dest, 1, -1) < 0) {
    1343                 :          0 :                                 dest->BufUsed --;
    1344                 :          0 :                                 break;
    1345                 :            :                         }
    1346                 :            :                 }
    1347 [ +  + ][ +  + ]:        600 :                 if ( (current_token == parmnum) && 
    1348                 :        320 :                      (*s != separator)) {
    1349                 :        300 :                         dest->buf[len] = *s;
    1350                 :        300 :                         ++len;
    1351                 :            :                 }
    1352         [ -  + ]:        300 :                 else if (current_token > parmnum) {
    1353                 :          0 :                         break;
    1354                 :            :                 }
    1355                 :        600 :                 ++s;
    1356                 :            :         }
    1357                 :            :         
    1358                 :         20 :         dest->buf[len] = '\0';
    1359                 :         20 :         dest->BufUsed = len;
    1360                 :            :                 
    1361         [ -  + ]:         20 :         if (current_token < parmnum) {
    1362                 :            :                 //lprintf (CTDL_DEBUG,"test <!: %s\n", dest);
    1363                 :          0 :                 return(-1);
    1364                 :            :         }
    1365                 :            :         //lprintf (CTDL_DEBUG,"test <: %d; %s\n", len, dest);
    1366                 :         20 :         return(len);
    1367                 :            : }
    1368                 :            : 
    1369                 :            : 
    1370                 :            : 
    1371                 :            : 
    1372                 :            : 
    1373                 :            : /**
    1374                 :            :  * @ingroup StrBuf_Tokenizer
    1375                 :            :  * @brief a string tokenizer to fetch an integer
    1376                 :            :  * @param Source String containing tokens
    1377                 :            :  * @param parmnum n'th Parameter to extract
    1378                 :            :  * @param separator tokenizer character
    1379                 :            :  * @returns 0 if not found, else integer representation of the token
    1380                 :            :  */
    1381                 :          0 : int StrBufExtract_int(const StrBuf* Source, int parmnum, char separator)
    1382                 :            : {
    1383                 :            :         StrBuf tmp;
    1384                 :            :         char buf[64];
    1385                 :            :         
    1386                 :          0 :         tmp.buf = buf;
    1387                 :          0 :         buf[0] = '\0';
    1388                 :          0 :         tmp.BufSize = 64;
    1389                 :          0 :         tmp.BufUsed = 0;
    1390                 :          0 :         tmp.ConstBuf = 1;
    1391         [ #  # ]:          0 :         if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0)
    1392                 :          0 :                 return(atoi(buf));
    1393                 :            :         else
    1394                 :          0 :                 return 0;
    1395                 :            : }
    1396                 :            : 
    1397                 :            : /**
    1398                 :            :  * @ingroup StrBuf_Tokenizer
    1399                 :            :  * @brief a string tokenizer to fetch a long integer
    1400                 :            :  * @param Source String containing tokens
    1401                 :            :  * @param parmnum n'th Parameter to extract
    1402                 :            :  * @param separator tokenizer character
    1403                 :            :  * @returns 0 if not found, else long integer representation of the token
    1404                 :            :  */
    1405                 :          0 : long StrBufExtract_long(const StrBuf* Source, int parmnum, char separator)
    1406                 :            : {
    1407                 :            :         StrBuf tmp;
    1408                 :            :         char buf[64];
    1409                 :            :         
    1410                 :          0 :         tmp.buf = buf;
    1411                 :          0 :         buf[0] = '\0';
    1412                 :          0 :         tmp.BufSize = 64;
    1413                 :          0 :         tmp.BufUsed = 0;
    1414                 :          0 :         tmp.ConstBuf = 1;
    1415         [ #  # ]:          0 :         if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0)
    1416                 :          0 :                 return(atoi(buf));
    1417                 :            :         else
    1418                 :          0 :                 return 0;
    1419                 :            : }
    1420                 :            : 
    1421                 :            : 
    1422                 :            : /**
    1423                 :            :  * @ingroup StrBuf_Tokenizer
    1424                 :            :  * @brief a string tokenizer to fetch an unsigned long
    1425                 :            :  * @param Source String containing tokens
    1426                 :            :  * @param parmnum n'th Parameter to extract
    1427                 :            :  * @param separator tokenizer character
    1428                 :            :  * @returns 0 if not found, else unsigned long representation of the token
    1429                 :            :  */
    1430                 :          0 : unsigned long StrBufExtract_unsigned_long(const StrBuf* Source, int parmnum, char separator)
    1431                 :            : {
    1432                 :            :         StrBuf tmp;
    1433                 :            :         char buf[64];
    1434                 :            :         char *pnum;
    1435                 :            :         
    1436                 :          0 :         tmp.buf = buf;
    1437                 :          0 :         buf[0] = '\0';
    1438                 :          0 :         tmp.BufSize = 64;
    1439                 :          0 :         tmp.BufUsed = 0;
    1440                 :          0 :         tmp.ConstBuf = 1;
    1441         [ #  # ]:          0 :         if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0) {
    1442                 :          0 :                 pnum = &buf[0];
    1443         [ #  # ]:          0 :                 if (*pnum == '-')
    1444                 :          0 :                         pnum ++;
    1445                 :          0 :                 return (unsigned long) atol(pnum);
    1446                 :            :         }
    1447                 :            :         else 
    1448                 :          0 :                 return 0;
    1449                 :            : }
    1450                 :            : 
    1451                 :            : 
    1452                 :            : 
    1453                 :            : /**
    1454                 :            :  * @ingroup StrBuf_NextTokenizer
    1455                 :            :  * @brief a string tokenizer; Bounds checker
    1456                 :            :  *  function to make shure whether StrBufExtract_NextToken and friends have reached the end of the string.
    1457                 :            :  * @param Source our tokenbuffer
    1458                 :            :  * @param pStart the token iterator pointer to inspect
    1459                 :            :  * @returns whether the revolving pointer is inside of the search range
    1460                 :            :  */
    1461                 :          0 : int StrBufHaveNextToken(const StrBuf *Source, const char **pStart)
    1462                 :            : {
    1463 [ #  # ][ #  # ]:          0 :         if ((Source == NULL) || 
                 [ #  # ]
    1464                 :          0 :             (*pStart == StrBufNOTNULL) ||
    1465                 :          0 :             (Source->BufUsed == 0))
    1466                 :            :         {
    1467                 :          0 :                 return 0;
    1468                 :            :         }
    1469         [ #  # ]:          0 :         if (*pStart == NULL)
    1470                 :            :         {
    1471                 :          0 :                 return 1;
    1472                 :            :         }
    1473         [ #  # ]:          0 :         else if (*pStart > Source->buf + Source->BufUsed)
    1474                 :            :         {
    1475                 :          0 :                 return 0;
    1476                 :            :         }
    1477         [ #  # ]:          0 :         else if (*pStart <= Source->buf)
    1478                 :            :         {
    1479                 :          0 :                 return 0;
    1480                 :            :         }
    1481                 :            : 
    1482                 :          0 :         return 1;
    1483                 :            : }
    1484                 :            : 
    1485                 :            : /**
    1486                 :            :  * @ingroup StrBuf_NextTokenizer
    1487                 :            :  * @brief a string tokenizer
    1488                 :            :  * @param dest Destination StringBuffer
    1489                 :            :  * @param Source StringBuffer to read into
    1490                 :            :  * @param pStart pointer to the end of the last token. Feed with NULL on start.
    1491                 :            :  * @param separator tokenizer 
    1492                 :            :  * @returns -1 if not found, else length of token.
    1493                 :            :  */
    1494                 :         18 : int StrBufExtract_NextToken(StrBuf *dest, const StrBuf *Source, const char **pStart, char separator)
    1495                 :            : {
    1496                 :            :         const char *s;          /* source */
    1497                 :            :         const char *EndBuffer;  /* end stop of source buffer */
    1498                 :         18 :         int current_token = 0;  /* token currently being processed */
    1499                 :         18 :         int len = 0;            /* running total length of extracted string */
    1500                 :            : 
    1501 [ +  - ][ -  + ]:         18 :         if ((Source          == NULL) || 
    1502                 :         18 :             (Source->BufUsed == 0)      ) 
    1503                 :            :         {
    1504                 :          0 :                 *pStart = StrBufNOTNULL;
    1505                 :          0 :                 return -1;
    1506                 :            :         }
    1507                 :            :          
    1508                 :         18 :         EndBuffer = Source->buf + Source->BufUsed;
    1509                 :            : 
    1510         [ +  - ]:         18 :         if (dest != NULL) 
    1511                 :            :         {
    1512                 :         18 :                 dest->buf[0] = '\0';
    1513                 :         18 :                 dest->BufUsed = 0;
    1514                 :            :         }
    1515                 :            :         else
    1516                 :            :         {
    1517                 :          0 :                 *pStart = EndBuffer + 1;
    1518                 :          0 :                 return -1;
    1519                 :            :         }
    1520                 :            : 
    1521         [ +  + ]:         18 :         if (*pStart == NULL)
    1522                 :            :         {
    1523                 :         12 :                 *pStart = Source->buf; /* we're starting to examine this buffer. */
    1524                 :            :         }
    1525 [ +  - ][ -  + ]:          6 :         else if ((*pStart < Source->buf) || 
    1526                 :          6 :                  (*pStart > EndBuffer  )   ) 
    1527                 :            :         {
    1528                 :          0 :                 return -1; /* no more tokens to find. */
    1529                 :            :         }
    1530                 :            : 
    1531                 :         18 :         s = *pStart;
    1532                 :            :         /* start to find the next token */
    1533 [ +  + ][ +  + ]:         76 :         while ((s <= EndBuffer)      && 
    1534                 :            :                (current_token == 0) ) 
    1535                 :            :         {
    1536         [ +  + ]:         58 :                 if (*s == separator) 
    1537                 :            :                 {
    1538                 :            :                         /* we found the next token */
    1539                 :          7 :                         ++current_token;
    1540                 :            :                 }
    1541                 :            : 
    1542         [ -  + ]:         58 :                 if (len >= dest->BufSize) 
    1543                 :            :                 {
    1544                 :            :                         /* our Dest-buffer isn't big enough, increase it. */
    1545                 :          0 :                         dest->BufUsed = len;
    1546                 :            : 
    1547         [ #  # ]:          0 :                         if (IncreaseBuf(dest, 1, -1) < 0) {
    1548                 :            :                                 /* WHUT? no more mem? bail out. */
    1549                 :          0 :                                 s = EndBuffer;
    1550                 :          0 :                                 dest->BufUsed --;
    1551                 :          0 :                                 break;
    1552                 :            :                         }
    1553                 :            :                 }
    1554                 :            : 
    1555 [ +  + ][ +  + ]:         58 :                 if ( (current_token == 0 ) &&   /* are we in our target token? */
                 [ +  - ]
    1556                 :         51 :                      (!IsEmptyStr(s)     ) &&
    1557                 :         40 :                      (separator     != *s)    ) /* don't copy the token itself */
    1558                 :            :                 {
    1559                 :         40 :                         dest->buf[len] = *s;    /* Copy the payload */
    1560                 :         40 :                         ++len;                  /* remember the bigger size. */
    1561                 :            :                 }
    1562                 :            : 
    1563                 :         58 :                 ++s;
    1564                 :            :         }
    1565                 :            : 
    1566                 :            :         /* did we reach the end? */
    1567         [ +  + ]:         18 :         if ((s > EndBuffer)) {
    1568                 :         11 :                 EndBuffer = StrBufNOTNULL;
    1569                 :         11 :                 *pStart = EndBuffer;
    1570                 :            :         }
    1571                 :            :         else {
    1572                 :          7 :                 *pStart = s;  /* remember the position for the next run */
    1573                 :            :         }
    1574                 :            : 
    1575                 :            :         /* sanitize our extracted token */
    1576                 :         18 :         dest->buf[len] = '\0';
    1577                 :         18 :         dest->BufUsed  = len;
    1578                 :            : 
    1579                 :         18 :         return (len);
    1580                 :            : }
    1581                 :            : 
    1582                 :            : 
    1583                 :            : /**
    1584                 :            :  * @ingroup StrBuf_NextTokenizer
    1585                 :            :  * @brief a string tokenizer
    1586                 :            :  * @param Source StringBuffer to read from
    1587                 :            :  * @param pStart pointer to the end of the last token. Feed with NULL.
    1588                 :            :  * @param separator tokenizer character
    1589                 :            :  * @param nTokens number of tokens to fastforward over
    1590                 :            :  * @returns -1 if not found, else length of token.
    1591                 :            :  */
    1592                 :          0 : int StrBufSkip_NTokenS(const StrBuf *Source, const char **pStart, char separator, int nTokens)
    1593                 :            : {
    1594                 :            :         const char *s, *EndBuffer;      //* source * /
    1595                 :          0 :         int len = 0;                    //* running total length of extracted string * /
    1596                 :          0 :         int current_token = 0;          //* token currently being processed * /
    1597                 :            : 
    1598 [ #  # ][ #  # ]:          0 :         if ((Source == NULL) || 
    1599                 :          0 :             (Source->BufUsed ==0)) {
    1600                 :          0 :                 return(-1);
    1601                 :            :         }
    1602         [ #  # ]:          0 :         if (nTokens == 0)
    1603                 :          0 :                 return Source->BufUsed;
    1604                 :            : 
    1605         [ #  # ]:          0 :         if (*pStart == NULL)
    1606                 :          0 :                 *pStart = Source->buf;
    1607                 :            : 
    1608                 :          0 :         EndBuffer = Source->buf + Source->BufUsed;
    1609                 :            : 
    1610 [ #  # ][ #  # ]:          0 :         if ((*pStart < Source->buf) || 
    1611                 :          0 :             (*pStart >  EndBuffer)) {
    1612                 :          0 :                 return (-1);
    1613                 :            :         }
    1614                 :            : 
    1615                 :            : 
    1616                 :          0 :         s = *pStart;
    1617                 :            : 
    1618                 :            :         //cit_backtrace();
    1619                 :            :         //lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
    1620                 :            : 
    1621 [ #  # ][ #  # ]:          0 :         while ((s<EndBuffer) && !IsEmptyStr(s)) {
    1622         [ #  # ]:          0 :                 if (*s == separator) {
    1623                 :          0 :                         ++current_token;
    1624                 :            :                 }
    1625         [ #  # ]:          0 :                 if (current_token >= nTokens) {
    1626                 :          0 :                         break;
    1627                 :            :                 }
    1628                 :          0 :                 ++s;
    1629                 :            :         }
    1630                 :          0 :         *pStart = s;
    1631                 :          0 :         (*pStart) ++;
    1632                 :            : 
    1633                 :          0 :         return(len);
    1634                 :            : }
    1635                 :            : 
    1636                 :            : /**
    1637                 :            :  * @ingroup StrBuf_NextTokenizer
    1638                 :            :  * @brief a string tokenizer to fetch an integer
    1639                 :            :  * @param Source StringBuffer to read from
    1640                 :            :  * @param pStart Cursor on the tokenstring
    1641                 :            :  * @param separator tokenizer character
    1642                 :            :  * @returns 0 if not found, else integer representation of the token
    1643                 :            :  */
    1644                 :          0 : int StrBufExtractNext_int(const StrBuf* Source, const char **pStart, char separator)
    1645                 :            : {
    1646                 :            :         StrBuf tmp;
    1647                 :            :         char buf[64];
    1648                 :            :         
    1649                 :          0 :         tmp.buf = buf;
    1650                 :          0 :         buf[0] = '\0';
    1651                 :          0 :         tmp.BufSize = 64;
    1652                 :          0 :         tmp.BufUsed = 0;
    1653                 :          0 :         tmp.ConstBuf = 1;
    1654         [ #  # ]:          0 :         if (StrBufExtract_NextToken(&tmp, Source, pStart, separator) > 0)
    1655                 :          0 :                 return(atoi(buf));
    1656                 :            :         else
    1657                 :          0 :                 return 0;
    1658                 :            : }
    1659                 :            : 
    1660                 :            : /**
    1661                 :            :  * @ingroup StrBuf_NextTokenizer
    1662                 :            :  * @brief a string tokenizer to fetch a long integer
    1663                 :            :  * @param Source StringBuffer to read from
    1664                 :            :  * @param pStart Cursor on the tokenstring
    1665                 :            :  * @param separator tokenizer character
    1666                 :            :  * @returns 0 if not found, else long integer representation of the token
    1667                 :            :  */
    1668                 :         10 : long StrBufExtractNext_long(const StrBuf* Source, const char **pStart, char separator)
    1669                 :            : {
    1670                 :            :         StrBuf tmp;
    1671                 :            :         char buf[64];
    1672                 :            :         
    1673                 :         10 :         tmp.buf = buf;
    1674                 :         10 :         buf[0] = '\0';
    1675                 :         10 :         tmp.BufSize = 64;
    1676                 :         10 :         tmp.BufUsed = 0;
    1677                 :         10 :         tmp.ConstBuf = 1;
    1678         [ +  - ]:         10 :         if (StrBufExtract_NextToken(&tmp, Source, pStart, separator) > 0)
    1679                 :         10 :                 return(atoi(buf));
    1680                 :            :         else
    1681                 :         10 :                 return 0;
    1682                 :            : }
    1683                 :            : 
    1684                 :            : 
    1685                 :            : /**
    1686                 :            :  * @ingroup StrBuf_NextTokenizer
    1687                 :            :  * @brief a string tokenizer to fetch an unsigned long
    1688                 :            :  * @param Source StringBuffer to read from
    1689                 :            :  * @param pStart Cursor on the tokenstring
    1690                 :            :  * @param separator tokenizer character
    1691                 :            :  * @returns 0 if not found, else unsigned long representation of the token
    1692                 :            :  */
    1693                 :          0 : unsigned long StrBufExtractNext_unsigned_long(const StrBuf* Source, const char **pStart, char separator)
    1694                 :            : {
    1695                 :            :         StrBuf tmp;
    1696                 :            :         char buf[64];
    1697                 :            :         char *pnum;
    1698                 :            :         
    1699                 :          0 :         tmp.buf = buf;
    1700                 :          0 :         buf[0] = '\0';
    1701                 :          0 :         tmp.BufSize = 64;
    1702                 :          0 :         tmp.BufUsed = 0;
    1703                 :          0 :         tmp.ConstBuf = 1;
    1704         [ #  # ]:          0 :         if (StrBufExtract_NextToken(&tmp, Source, pStart, separator) > 0) {
    1705                 :          0 :                 pnum = &buf[0];
    1706         [ #  # ]:          0 :                 if (*pnum == '-')
    1707                 :          0 :                         pnum ++;
    1708                 :          0 :                 return (unsigned long) atol(pnum);
    1709                 :            :         }
    1710                 :            :         else 
    1711                 :          0 :                 return 0;
    1712                 :            : }
    1713                 :            : 
    1714                 :            : 
    1715                 :            : 
    1716                 :            : 
    1717                 :            : 
    1718                 :            : /*******************************************************************************
    1719                 :            :  *                             Escape Appending                                *
    1720                 :            :  *******************************************************************************/
    1721                 :            : 
    1722                 :            : /** 
    1723                 :            :  * @ingroup StrBuf_DeEnCoder
    1724                 :            :  * @brief Escape a string for feeding out as a URL while appending it to a Buffer
    1725                 :            :  * @param OutBuf the output buffer
    1726                 :            :  * @param In Buffer to encode
    1727                 :            :  * @param PlainIn way in from plain old c strings
    1728                 :            :  */
    1729                 :          0 : void StrBufUrlescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn)
    1730                 :            : {
    1731                 :            :         const char *pch, *pche;
    1732                 :            :         char *pt, *pte;
    1733                 :            :         int len;
    1734                 :            :         
    1735 [ #  # ][ #  # ]:          0 :         if (((In == NULL) && (PlainIn == NULL)) || (OutBuf == NULL) )
                 [ #  # ]
    1736                 :          0 :                 return;
    1737         [ #  # ]:          0 :         if (PlainIn != NULL) {
    1738                 :          0 :                 len = strlen(PlainIn);
    1739                 :          0 :                 pch = PlainIn;
    1740                 :          0 :                 pche = pch + len;
    1741                 :            :         }
    1742                 :            :         else {
    1743                 :          0 :                 pch = In->buf;
    1744                 :          0 :                 pche = pch + In->BufUsed;
    1745                 :          0 :                 len = In->BufUsed;
    1746                 :            :         }
    1747                 :            : 
    1748         [ #  # ]:          0 :         if (len == 0) 
    1749                 :          0 :                 return;
    1750                 :            : 
    1751                 :          0 :         pt = OutBuf->buf + OutBuf->BufUsed;
    1752                 :          0 :         pte = OutBuf->buf + OutBuf->BufSize - 4; /**< we max append 3 chars at once plus the \0 */
    1753                 :            : 
    1754         [ #  # ]:          0 :         while (pch < pche) {
    1755         [ #  # ]:          0 :                 if (pt >= pte) {
    1756                 :          0 :                         IncreaseBuf(OutBuf, 1, -1);
    1757                 :          0 :                         pte = OutBuf->buf + OutBuf->BufSize - 4; /**< we max append 3 chars at once plus the \0 */
    1758                 :          0 :                         pt = OutBuf->buf + OutBuf->BufUsed;
    1759                 :            :                 }
    1760                 :            : 
    1761 [ #  # ][ #  # ]:          0 :                 if((*pch >= 'a' && *pch <= 'z') ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1762                 :          0 :                    (*pch >= '@' && *pch <= 'Z') || /* @ A-Z */
    1763                 :          0 :                    (*pch >= '0' && *pch <= ':') || /* 0-9 : */
    1764                 :          0 :                    (*pch == '!') || (*pch == '_') || 
    1765                 :          0 :                    (*pch == ',') || (*pch == '.'))
    1766                 :            :                 {
    1767                 :          0 :                         *(pt++) = *(pch++);
    1768                 :          0 :                         OutBuf->BufUsed++;
    1769                 :            :                 }                       
    1770                 :            :                 else {
    1771                 :          0 :                         *pt = '%';
    1772                 :          0 :                         *(pt + 1) = HexList[(unsigned char)*pch][0];
    1773                 :          0 :                         *(pt + 2) = HexList[(unsigned char)*pch][1];
    1774                 :          0 :                         pt += 3;
    1775                 :          0 :                         OutBuf->BufUsed += 3;
    1776                 :          0 :                         pch ++;
    1777                 :            :                 }
    1778                 :            :         }
    1779                 :          0 :         *pt = '\0';
    1780                 :            : }
    1781                 :            : 
    1782                 :            : /** 
    1783                 :            :  * @ingroup StrBuf_DeEnCoder
    1784                 :            :  * @brief append a string in hex encoding to the buffer
    1785                 :            :  * @param OutBuf the output buffer
    1786                 :            :  * @param In Buffer to encode
    1787                 :            :  * @param PlainIn way in from plain old c strings
    1788                 :            :  */
    1789                 :          0 : void StrBufHexescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn)
    1790                 :            : {
    1791                 :            :         const char *pch, *pche;
    1792                 :            :         char *pt, *pte;
    1793                 :            :         int len;
    1794                 :            :         
    1795 [ #  # ][ #  # ]:          0 :         if (((In == NULL) && (PlainIn == NULL)) || (OutBuf == NULL) )
                 [ #  # ]
    1796                 :          0 :                 return;
    1797         [ #  # ]:          0 :         if (PlainIn != NULL) {
    1798                 :          0 :                 len = strlen(PlainIn);
    1799                 :          0 :                 pch = PlainIn;
    1800                 :          0 :                 pche = pch + len;
    1801                 :            :         }
    1802                 :            :         else {
    1803                 :          0 :                 pch = In->buf;
    1804                 :          0 :                 pche = pch + In->BufUsed;
    1805                 :          0 :                 len = In->BufUsed;
    1806                 :            :         }
    1807                 :            : 
    1808         [ #  # ]:          0 :         if (len == 0) 
    1809                 :          0 :                 return;
    1810                 :            : 
    1811                 :          0 :         pt = OutBuf->buf + OutBuf->BufUsed;
    1812                 :          0 :         pte = OutBuf->buf + OutBuf->BufSize - 3; /**< we max append 3 chars at once plus the \0 */
    1813                 :            : 
    1814         [ #  # ]:          0 :         while (pch < pche) {
    1815         [ #  # ]:          0 :                 if (pt >= pte) {
    1816                 :          0 :                         IncreaseBuf(OutBuf, 1, -1);
    1817                 :          0 :                         pte = OutBuf->buf + OutBuf->BufSize - 3; /**< we max append 3 chars at once plus the \0 */
    1818                 :          0 :                         pt = OutBuf->buf + OutBuf->BufUsed;
    1819                 :            :                 }
    1820                 :            : 
    1821                 :          0 :                 *pt = HexList[(unsigned char)*pch][0];
    1822                 :          0 :                 pt ++;
    1823                 :          0 :                 *pt = HexList[(unsigned char)*pch][1];
    1824                 :          0 :                 pt ++; pch ++; OutBuf->BufUsed += 2;
    1825                 :            :         }
    1826                 :          0 :         *pt = '\0';
    1827                 :            : }
    1828                 :            : 
    1829                 :            : /**
    1830                 :            :  * @ingroup StrBuf_DeEnCoder
    1831                 :            :  * @brief Append a string, escaping characters which have meaning in HTML.  
    1832                 :            :  *
    1833                 :            :  * @param Target        target buffer
    1834                 :            :  * @param Source        source buffer; set to NULL if you just have a C-String
    1835                 :            :  * @param PlainIn       Plain-C string to append; set to NULL if unused
    1836                 :            :  * @param nbsp          If nonzero, spaces are converted to non-breaking spaces.
    1837                 :            :  * @param nolinebreaks  if set to 1, linebreaks are removed from the string.
    1838                 :            :  *                      if set to 2, linebreaks are replaced by &ltbr/&gt
    1839                 :            :  */
    1840                 :          0 : long StrEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn, int nbsp, int nolinebreaks)
    1841                 :            : {
    1842                 :            :         const char *aptr, *eiptr;
    1843                 :            :         char *bptr, *eptr;
    1844                 :            :         long len;
    1845                 :            : 
    1846 [ #  # ][ #  # ]:          0 :         if (((Source == NULL) && (PlainIn == NULL)) || (Target == NULL) )
                 [ #  # ]
    1847                 :          0 :                 return -1;
    1848                 :            : 
    1849         [ #  # ]:          0 :         if (PlainIn != NULL) {
    1850                 :          0 :                 aptr = PlainIn;
    1851                 :          0 :                 len = strlen(PlainIn);
    1852                 :          0 :                 eiptr = aptr + len;
    1853                 :            :         }
    1854                 :            :         else {
    1855                 :          0 :                 aptr = Source->buf;
    1856                 :          0 :                 eiptr = aptr + Source->BufUsed;
    1857                 :          0 :                 len = Source->BufUsed;
    1858                 :            :         }
    1859                 :            : 
    1860         [ #  # ]:          0 :         if (len == 0) 
    1861                 :          0 :                 return -1;
    1862                 :            : 
    1863                 :          0 :         bptr = Target->buf + Target->BufUsed;
    1864                 :          0 :         eptr = Target->buf + Target->BufSize - 11; /* our biggest unit to put in...  */
    1865                 :            : 
    1866         [ #  # ]:          0 :         while (aptr < eiptr){
    1867         [ #  # ]:          0 :                 if(bptr >= eptr) {
    1868                 :          0 :                         IncreaseBuf(Target, 1, -1);
    1869                 :          0 :                         eptr = Target->buf + Target->BufSize - 11; /* our biggest unit to put in...  */
    1870                 :          0 :                         bptr = Target->buf + Target->BufUsed;
    1871                 :            :                 }
    1872         [ #  # ]:          0 :                 if (*aptr == '<') {
    1873                 :          0 :                         memcpy(bptr, "&lt;", 4);
    1874                 :          0 :                         bptr += 4;
    1875                 :          0 :                         Target->BufUsed += 4;
    1876                 :            :                 }
    1877         [ #  # ]:          0 :                 else if (*aptr == '>') {
    1878                 :          0 :                         memcpy(bptr, "&gt;", 4);
    1879                 :          0 :                         bptr += 4;
    1880                 :          0 :                         Target->BufUsed += 4;
    1881                 :            :                 }
    1882         [ #  # ]:          0 :                 else if (*aptr == '&') {
    1883                 :          0 :                         memcpy(bptr, "&amp;", 5);
    1884                 :          0 :                         bptr += 5;
    1885                 :          0 :                         Target->BufUsed += 5;
    1886                 :            :                 }
    1887         [ #  # ]:          0 :                 else if (*aptr == '"') {
    1888                 :          0 :                         memcpy(bptr, "&quot;", 6);
    1889                 :          0 :                         bptr += 6;
    1890                 :          0 :                         Target->BufUsed += 6;
    1891                 :            :                 }
    1892         [ #  # ]:          0 :                 else if (*aptr == '\'') {
    1893                 :          0 :                         memcpy(bptr, "&#39;", 5);
    1894                 :          0 :                         bptr += 5;
    1895                 :          0 :                         Target->BufUsed += 5;
    1896                 :            :                 }
    1897         [ #  # ]:          0 :                 else if (*aptr == LB) {
    1898                 :          0 :                         *bptr = '<';
    1899                 :          0 :                         bptr ++;
    1900                 :          0 :                         Target->BufUsed ++;
    1901                 :            :                 }
    1902         [ #  # ]:          0 :                 else if (*aptr == RB) {
    1903                 :          0 :                         *bptr = '>';
    1904                 :          0 :                         bptr ++;
    1905                 :          0 :                         Target->BufUsed ++;
    1906                 :            :                 }
    1907         [ #  # ]:          0 :                 else if (*aptr == QU) {
    1908                 :          0 :                         *bptr ='"';
    1909                 :          0 :                         bptr ++;
    1910                 :          0 :                         Target->BufUsed ++;
    1911                 :            :                 }
    1912 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == 32) && (nbsp == 1)) {
    1913                 :          0 :                         memcpy(bptr, "&nbsp;", 6);
    1914                 :          0 :                         bptr += 6;
    1915                 :          0 :                         Target->BufUsed += 6;
    1916                 :            :                 }
    1917 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == '\n') && (nolinebreaks == 1)) {
    1918                 :          0 :                         *bptr='\0';     /* nothing */
    1919                 :            :                 }
    1920 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == '\n') && (nolinebreaks == 2)) {
    1921                 :          0 :                         memcpy(bptr, "&lt;br/&gt;", 11);
    1922                 :          0 :                         bptr += 11;
    1923                 :          0 :                         Target->BufUsed += 11;
    1924                 :            :                 }
    1925                 :            : 
    1926                 :            : 
    1927 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == '\r') && (nolinebreaks != 0)) {
    1928                 :          0 :                         *bptr='\0';     /* nothing */
    1929                 :            :                 }
    1930                 :            :                 else{
    1931                 :          0 :                         *bptr = *aptr;
    1932                 :          0 :                         bptr++;
    1933                 :          0 :                         Target->BufUsed ++;
    1934                 :            :                 }
    1935                 :          0 :                 aptr ++;
    1936                 :            :         }
    1937                 :          0 :         *bptr = '\0';
    1938 [ #  # ][ #  # ]:          0 :         if ((bptr = eptr - 1 ) && !IsEmptyStr(aptr) )
    1939                 :          0 :                 return -1;
    1940                 :          0 :         return Target->BufUsed;
    1941                 :            : }
    1942                 :            : 
    1943                 :            : /**
    1944                 :            :  * @ingroup StrBuf_DeEnCoder
    1945                 :            :  * @brief Append a string, escaping characters which have meaning in HTML.  
    1946                 :            :  * Converts linebreaks into blanks; escapes single quotes
    1947                 :            :  * @param Target        target buffer
    1948                 :            :  * @param Source        source buffer; set to NULL if you just have a C-String
    1949                 :            :  * @param PlainIn       Plain-C string to append; set to NULL if unused
    1950                 :            :  */
    1951                 :          0 : void StrMsgEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn)
    1952                 :            : {
    1953                 :            :         const char *aptr, *eiptr;
    1954                 :            :         char *tptr, *eptr;
    1955                 :            :         long len;
    1956                 :            : 
    1957 [ #  # ][ #  # ]:          0 :         if (((Source == NULL) && (PlainIn == NULL)) || (Target == NULL) )
                 [ #  # ]
    1958                 :          0 :                 return ;
    1959                 :            : 
    1960         [ #  # ]:          0 :         if (PlainIn != NULL) {
    1961                 :          0 :                 aptr = PlainIn;
    1962                 :          0 :                 len = strlen(PlainIn);
    1963                 :          0 :                 eiptr = aptr + len;
    1964                 :            :         }
    1965                 :            :         else {
    1966                 :          0 :                 aptr = Source->buf;
    1967                 :          0 :                 eiptr = aptr + Source->BufUsed;
    1968                 :          0 :                 len = Source->BufUsed;
    1969                 :            :         }
    1970                 :            : 
    1971         [ #  # ]:          0 :         if (len == 0) 
    1972                 :          0 :                 return;
    1973                 :            : 
    1974                 :          0 :         eptr = Target->buf + Target->BufSize - 8; 
    1975                 :          0 :         tptr = Target->buf + Target->BufUsed;
    1976                 :            :         
    1977         [ #  # ]:          0 :         while (aptr < eiptr){
    1978         [ #  # ]:          0 :                 if(tptr >= eptr) {
    1979                 :          0 :                         IncreaseBuf(Target, 1, -1);
    1980                 :          0 :                         eptr = Target->buf + Target->BufSize - 8; 
    1981                 :          0 :                         tptr = Target->buf + Target->BufUsed;
    1982                 :            :                 }
    1983                 :            :                
    1984         [ #  # ]:          0 :                 if (*aptr == '\n') {
    1985                 :          0 :                         *tptr = ' ';
    1986                 :          0 :                         Target->BufUsed++;
    1987                 :            :                 }
    1988         [ #  # ]:          0 :                 else if (*aptr == '\r') {
    1989                 :          0 :                         *tptr = ' ';
    1990                 :          0 :                         Target->BufUsed++;
    1991                 :            :                 }
    1992         [ #  # ]:          0 :                 else if (*aptr == '\'') {
    1993                 :          0 :                         *(tptr++) = '&';
    1994                 :          0 :                         *(tptr++) = '#';
    1995                 :          0 :                         *(tptr++) = '3';
    1996                 :          0 :                         *(tptr++) = '9';
    1997                 :          0 :                         *tptr = ';';
    1998                 :          0 :                         Target->BufUsed += 5;
    1999                 :            :                 } else {
    2000                 :          0 :                         *tptr = *aptr;
    2001                 :          0 :                         Target->BufUsed++;
    2002                 :            :                 }
    2003                 :          0 :                 tptr++; aptr++;
    2004                 :            :         }
    2005                 :          0 :         *tptr = '\0';
    2006                 :            : }
    2007                 :            : 
    2008                 :            : 
    2009                 :            : 
    2010                 :            : /**
    2011                 :            :  * @ingroup StrBuf_DeEnCoder
    2012                 :            :  * @brief Append a string, escaping characters which have meaning in ICAL.  
    2013                 :            :  * [\n,] 
    2014                 :            :  * @param Target        target buffer
    2015                 :            :  * @param Source        source buffer; set to NULL if you just have a C-String
    2016                 :            :  * @param PlainIn       Plain-C string to append; set to NULL if unused
    2017                 :            :  */
    2018                 :          0 : void StrIcalEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn)
    2019                 :            : {
    2020                 :            :         const char *aptr, *eiptr;
    2021                 :            :         char *tptr, *eptr;
    2022                 :            :         long len;
    2023                 :            : 
    2024 [ #  # ][ #  # ]:          0 :         if (((Source == NULL) && (PlainIn == NULL)) || (Target == NULL) )
                 [ #  # ]
    2025                 :          0 :                 return ;
    2026                 :            : 
    2027         [ #  # ]:          0 :         if (PlainIn != NULL) {
    2028                 :          0 :                 aptr = PlainIn;
    2029                 :          0 :                 len = strlen(PlainIn);
    2030                 :          0 :                 eiptr = aptr + len;
    2031                 :            :         }
    2032                 :            :         else {
    2033                 :          0 :                 aptr = Source->buf;
    2034                 :          0 :                 eiptr = aptr + Source->BufUsed;
    2035                 :          0 :                 len = Source->BufUsed;
    2036                 :            :         }
    2037                 :            : 
    2038         [ #  # ]:          0 :         if (len == 0) 
    2039                 :          0 :                 return;
    2040                 :            : 
    2041                 :          0 :         eptr = Target->buf + Target->BufSize - 8; 
    2042                 :          0 :         tptr = Target->buf + Target->BufUsed;
    2043                 :            :         
    2044         [ #  # ]:          0 :         while (aptr < eiptr){
    2045         [ #  # ]:          0 :                 if(tptr + 3 >= eptr) {
    2046                 :          0 :                         IncreaseBuf(Target, 1, -1);
    2047                 :          0 :                         eptr = Target->buf + Target->BufSize - 8; 
    2048                 :          0 :                         tptr = Target->buf + Target->BufUsed;
    2049                 :            :                 }
    2050                 :            :                
    2051         [ #  # ]:          0 :                 if (*aptr == '\n') {
    2052                 :          0 :                         *tptr = '\\';
    2053                 :          0 :                         Target->BufUsed++;
    2054                 :          0 :                         tptr++;
    2055                 :          0 :                         *tptr = 'n';
    2056                 :          0 :                         Target->BufUsed++;
    2057                 :            :                 }
    2058         [ #  # ]:          0 :                 else if (*aptr == '\r') {
    2059                 :          0 :                         *tptr = '\\';
    2060                 :          0 :                         Target->BufUsed++;
    2061                 :          0 :                         tptr++;
    2062                 :          0 :                         *tptr = 'r';
    2063                 :          0 :                         Target->BufUsed++;
    2064                 :            :                 }
    2065         [ #  # ]:          0 :                 else if (*aptr == ',') {
    2066                 :          0 :                         *tptr = '\\';
    2067                 :          0 :                         Target->BufUsed++;
    2068                 :          0 :                         tptr++;
    2069                 :          0 :                         *tptr = ',';
    2070                 :          0 :                         Target->BufUsed++;
    2071                 :            :                 } else {
    2072                 :          0 :                         *tptr = *aptr;
    2073                 :          0 :                         Target->BufUsed++;
    2074                 :            :                 }
    2075                 :          0 :                 tptr++; aptr++;
    2076                 :            :         }
    2077                 :          0 :         *tptr = '\0';
    2078                 :            : }
    2079                 :            : 
    2080                 :            : /**
    2081                 :            :  * @ingroup StrBuf_DeEnCoder
    2082                 :            :  * @brief Append a string, escaping characters which have meaning in JavaScript strings .  
    2083                 :            :  *
    2084                 :            :  * @param Target        target buffer
    2085                 :            :  * @param Source        source buffer; set to NULL if you just have a C-String
    2086                 :            :  * @param PlainIn       Plain-C string to append; set to NULL if unused
    2087                 :            :  * @returns size of result or -1
    2088                 :            :  */
    2089                 :         89 : long StrECMAEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn)
    2090                 :            : {
    2091                 :            :         const char *aptr, *eiptr;
    2092                 :            :         char *bptr, *eptr;
    2093                 :            :         long len;
    2094                 :            : 
    2095 [ -  + ][ #  # ]:         89 :         if (((Source == NULL) && (PlainIn == NULL)) || (Target == NULL) )
                 [ -  + ]
    2096                 :          0 :                 return -1;
    2097                 :            : 
    2098         [ -  + ]:         89 :         if (PlainIn != NULL) {
    2099                 :          0 :                 aptr = PlainIn;
    2100                 :          0 :                 len = strlen(PlainIn);
    2101                 :          0 :                 eiptr = aptr + len;
    2102                 :            :         }
    2103                 :            :         else {
    2104                 :         89 :                 aptr = Source->buf;
    2105                 :         89 :                 eiptr = aptr + Source->BufUsed;
    2106                 :         89 :                 len = Source->BufUsed;
    2107                 :            :         }
    2108                 :            : 
    2109         [ +  + ]:         89 :         if (len == 0) 
    2110                 :          8 :                 return -1;
    2111                 :            : 
    2112                 :         81 :         bptr = Target->buf + Target->BufUsed;
    2113                 :         81 :         eptr = Target->buf + Target->BufSize - 3; /* our biggest unit to put in...  */
    2114                 :            : 
    2115         [ +  + ]:       1179 :         while (aptr < eiptr){
    2116         [ +  + ]:       1098 :                 if(bptr >= eptr) {
    2117                 :          3 :                         IncreaseBuf(Target, 1, -1);
    2118                 :          3 :                         eptr = Target->buf + Target->BufSize - 3; 
    2119                 :          3 :                         bptr = Target->buf + Target->BufUsed;
    2120                 :            :                 }
    2121         [ -  + ]:       1098 :                 if (*aptr == '"') {
    2122                 :          0 :                         *bptr = '\\';
    2123                 :          0 :                         bptr ++;
    2124                 :          0 :                         *bptr = '"';
    2125                 :          0 :                         bptr ++;
    2126                 :          0 :                         Target->BufUsed += 2;
    2127         [ -  + ]:       1098 :                 } else if (*aptr == '\\') {
    2128                 :          0 :                         *bptr = '\\';
    2129                 :          0 :                         bptr ++;
    2130                 :          0 :                         *bptr = '\\';
    2131                 :          0 :                         bptr ++;
    2132                 :          0 :                         Target->BufUsed += 2;
    2133                 :            :                 }
    2134                 :            :                 else{
    2135                 :       1098 :                         *bptr = *aptr;
    2136                 :       1098 :                         bptr++;
    2137                 :       1098 :                         Target->BufUsed ++;
    2138                 :            :                 }
    2139                 :       1098 :                 aptr ++;
    2140                 :            :         }
    2141                 :         81 :         *bptr = '\0';
    2142 [ -  + ][ #  # ]:         81 :         if ((bptr == eptr - 1 ) && !IsEmptyStr(aptr) )
    2143                 :          0 :                 return -1;
    2144                 :         89 :         return Target->BufUsed;
    2145                 :            : }
    2146                 :            : 
    2147                 :            : /**
    2148                 :            :  * @ingroup StrBuf_DeEnCoder
    2149                 :            :  * @brief Append a string, escaping characters which have meaning in HTML + json.  
    2150                 :            :  *
    2151                 :            :  * @param Target        target buffer
    2152                 :            :  * @param Source        source buffer; set to NULL if you just have a C-String
    2153                 :            :  * @param PlainIn       Plain-C string to append; set to NULL if unused
    2154                 :            :  * @param nbsp          If nonzero, spaces are converted to non-breaking spaces.
    2155                 :            :  * @param nolinebreaks  if set to 1, linebreaks are removed from the string.
    2156                 :            :  *                      if set to 2, linebreaks are replaced by &ltbr/&gt
    2157                 :            :  */
    2158                 :          0 : long StrHtmlEcmaEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn, int nbsp, int nolinebreaks)
    2159                 :            : {
    2160                 :            :         const char *aptr, *eiptr;
    2161                 :            :         char *bptr, *eptr;
    2162                 :            :         long len;
    2163                 :          0 :         int IsUtf8Sequence = 0;
    2164                 :            : 
    2165 [ #  # ][ #  # ]:          0 :         if (((Source == NULL) && (PlainIn == NULL)) || (Target == NULL) )
                 [ #  # ]
    2166                 :          0 :                 return -1;
    2167                 :            : 
    2168         [ #  # ]:          0 :         if (PlainIn != NULL) {
    2169                 :          0 :                 aptr = PlainIn;
    2170                 :          0 :                 len = strlen(PlainIn);
    2171                 :          0 :                 eiptr = aptr + len;
    2172                 :            :         }
    2173                 :            :         else {
    2174                 :          0 :                 aptr = Source->buf;
    2175                 :          0 :                 eiptr = aptr + Source->BufUsed;
    2176                 :          0 :                 len = Source->BufUsed;
    2177                 :            :         }
    2178                 :            : 
    2179         [ #  # ]:          0 :         if (len == 0) 
    2180                 :          0 :                 return -1;
    2181                 :            : 
    2182                 :          0 :         bptr = Target->buf + Target->BufUsed;
    2183                 :          0 :         eptr = Target->buf + Target->BufSize - 11; /* our biggest unit to put in...  */
    2184                 :            : 
    2185         [ #  # ]:          0 :         while (aptr < eiptr){
    2186         [ #  # ]:          0 :                 if(bptr >= eptr) {
    2187                 :          0 :                         IncreaseBuf(Target, 1, -1);
    2188                 :          0 :                         eptr = Target->buf + Target->BufSize - 11; /* our biggest unit to put in...  */
    2189                 :          0 :                         bptr = Target->buf + Target->BufUsed;
    2190                 :            :                 }
    2191         [ #  # ]:          0 :                 if (*aptr == '<') {
    2192                 :          0 :                         memcpy(bptr, "&lt;", 4);
    2193                 :          0 :                         bptr += 4;
    2194                 :          0 :                         Target->BufUsed += 4;
    2195                 :            :                 }
    2196         [ #  # ]:          0 :                 else if (*aptr == '>') {
    2197                 :          0 :                         memcpy(bptr, "&gt;", 4);
    2198                 :          0 :                         bptr += 4;
    2199                 :          0 :                         Target->BufUsed += 4;
    2200                 :            :                 }
    2201         [ #  # ]:          0 :                 else if (*aptr == '&') {
    2202                 :          0 :                         memcpy(bptr, "&amp;", 5);
    2203                 :          0 :                         bptr += 5;
    2204                 :          0 :                         Target->BufUsed += 5;
    2205                 :            :                 }
    2206         [ #  # ]:          0 :                 else if (*aptr == LB) {
    2207                 :          0 :                         *bptr = '<';
    2208                 :          0 :                         bptr ++;
    2209                 :          0 :                         Target->BufUsed ++;
    2210                 :            :                 }
    2211         [ #  # ]:          0 :                 else if (*aptr == RB) {
    2212                 :          0 :                         *bptr = '>';
    2213                 :          0 :                         bptr ++;
    2214                 :          0 :                         Target->BufUsed ++;
    2215                 :            :                 }
    2216 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == 32) && (nbsp == 1)) {
    2217                 :          0 :                         memcpy(bptr, "&nbsp;", 6);
    2218                 :          0 :                         bptr += 6;
    2219                 :          0 :                         Target->BufUsed += 6;
    2220                 :            :                 }
    2221 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == '\n') && (nolinebreaks == 1)) {
    2222                 :          0 :                         *bptr='\0';     /* nothing */
    2223                 :            :                 }
    2224 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == '\n') && (nolinebreaks == 2)) {
    2225                 :          0 :                         memcpy(bptr, "&lt;br/&gt;", 11);
    2226                 :          0 :                         bptr += 11;
    2227                 :          0 :                         Target->BufUsed += 11;
    2228                 :            :                 }
    2229                 :            : 
    2230 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == '\r') && (nolinebreaks != 0)) {
    2231                 :          0 :                         *bptr='\0';     /* nothing */
    2232                 :            :                 }
    2233                 :            : 
    2234 [ #  # ][ #  # ]:          0 :                 else if ((*aptr == '"') || (*aptr == QU)) {
    2235                 :          0 :                         *bptr = '\\';
    2236                 :          0 :                         bptr ++;
    2237                 :          0 :                         *bptr = '"';
    2238                 :          0 :                         bptr ++;
    2239                 :          0 :                         Target->BufUsed += 2;
    2240         [ #  # ]:          0 :                 } else if (*aptr == '\\') {
    2241                 :          0 :                         *bptr = '\\';
    2242                 :          0 :                         bptr ++;
    2243                 :          0 :                         *bptr = '\\';
    2244                 :          0 :                         bptr ++;
    2245                 :          0 :                         Target->BufUsed += 2;
    2246                 :            :                 }
    2247                 :            :                 else {
    2248         [ #  # ]:          0 :                         if (((unsigned char)*aptr) >= 0x20)
    2249                 :            :                         {
    2250                 :          0 :                                 IsUtf8Sequence =  Ctdl_GetUtf8SequenceLength(aptr, eiptr);
    2251                 :            :                                 
    2252                 :          0 :                                 *bptr = *aptr;
    2253                 :          0 :                                 Target->BufUsed ++;
    2254         [ #  # ]:          0 :                                 while (IsUtf8Sequence > 1){
    2255         [ #  # ]:          0 :                                         if(bptr + IsUtf8Sequence >= eptr) {
    2256                 :          0 :                                                 IncreaseBuf(Target, 1, -1);
    2257                 :          0 :                                                 eptr = Target->buf + Target->BufSize - 11; /* our biggest unit to put in...  */
    2258                 :          0 :                                                 bptr = Target->buf + Target->BufUsed - 1;
    2259                 :            :                                         }
    2260                 :          0 :                                         bptr++; aptr++;
    2261                 :          0 :                                         IsUtf8Sequence --;
    2262                 :          0 :                                         *bptr = *aptr;
    2263                 :          0 :                                         Target->BufUsed ++;
    2264                 :            :                                 }
    2265                 :          0 :                                 bptr++;
    2266                 :            :                         }
    2267                 :            : 
    2268                 :            :                 }
    2269                 :          0 :                 aptr ++;
    2270                 :            :         }
    2271                 :          0 :         *bptr = '\0';
    2272 [ #  # ][ #  # ]:          0 :         if ((bptr = eptr - 1 ) && !IsEmptyStr(aptr) )
    2273                 :          0 :                 return -1;
    2274                 :          0 :         return Target->BufUsed;
    2275                 :            : }
    2276                 :            : 
    2277                 :            : /**
    2278                 :            :  * @ingroup StrBuf_DeEnCoder
    2279                 :            :  * @brief unhide special chars hidden to the HTML escaper
    2280                 :            :  * @param target buffer to put the unescaped string in
    2281                 :            :  * @param source buffer to unescape
    2282                 :            :  */
    2283                 :          0 : void StrBufEUid_unescapize(StrBuf *target, const StrBuf *source) 
    2284                 :            : {
    2285                 :            :         int a, b, len;
    2286                 :            :         char hex[3];
    2287                 :            : 
    2288         [ #  # ]:          0 :         if (target != NULL)
    2289                 :          0 :                 FlushStrBuf(target);
    2290                 :            : 
    2291 [ #  # ][ #  # ]:          0 :         if (source == NULL ||target == NULL)
    2292                 :            :         {
    2293                 :          0 :                 return;
    2294                 :            :         }
    2295                 :            : 
    2296                 :          0 :         len = source->BufUsed;
    2297         [ #  # ]:          0 :         for (a = 0; a < len; ++a) {
    2298         [ #  # ]:          0 :                 if (target->BufUsed >= target->BufSize)
    2299                 :          0 :                         IncreaseBuf(target, 1, -1);
    2300                 :            : 
    2301         [ #  # ]:          0 :                 if (source->buf[a] == '=') {
    2302                 :          0 :                         hex[0] = source->buf[a + 1];
    2303                 :          0 :                         hex[1] = source->buf[a + 2];
    2304                 :          0 :                         hex[2] = 0;
    2305                 :          0 :                         b = 0;
    2306                 :          0 :                         sscanf(hex, "%02x", &b);
    2307                 :          0 :                         target->buf[target->BufUsed] = b;
    2308                 :          0 :                         target->buf[++target->BufUsed] = 0;
    2309                 :          0 :                         a += 2;
    2310                 :            :                 }
    2311                 :            :                 else {
    2312                 :          0 :                         target->buf[target->BufUsed] = source->buf[a];
    2313                 :          0 :                         target->buf[++target->BufUsed] = 0;
    2314                 :            :                 }
    2315                 :            :         }
    2316                 :            : }
    2317                 :            : 
    2318                 :            : 
    2319                 :            : /**
    2320                 :            :  * @ingroup StrBuf_DeEnCoder
    2321                 :            :  * @brief hide special chars from the HTML escapers and friends
    2322                 :            :  * @param target buffer to put the escaped string in
    2323                 :            :  * @param source buffer to escape
    2324                 :            :  */
    2325                 :          0 : void StrBufEUid_escapize(StrBuf *target, const StrBuf *source) 
    2326                 :            : {
    2327                 :            :         int i, len;
    2328                 :            : 
    2329         [ #  # ]:          0 :         if (target != NULL)
    2330                 :          0 :                 FlushStrBuf(target);
    2331                 :            : 
    2332 [ #  # ][ #  # ]:          0 :         if (source == NULL ||target == NULL)
    2333                 :            :         {
    2334                 :          0 :                 return;
    2335                 :            :         }
    2336                 :            : 
    2337                 :          0 :         len = source->BufUsed;
    2338         [ #  # ]:          0 :         for (i=0; i<len; ++i) {
    2339         [ #  # ]:          0 :                 if (target->BufUsed + 4 >= target->BufSize)
    2340                 :          0 :                         IncreaseBuf(target, 1, -1);
    2341 [ #  # ][ #  # ]:          0 :                 if ( (isalnum(source->buf[i])) || 
                 [ #  # ]
    2342                 :          0 :                      (source->buf[i]=='-') || 
    2343                 :          0 :                      (source->buf[i]=='_') ) {
    2344                 :          0 :                         target->buf[target->BufUsed++] = source->buf[i];
    2345                 :            :                 }
    2346                 :            :                 else {
    2347                 :          0 :                         sprintf(&target->buf[target->BufUsed], 
    2348                 :            :                                 "=%02X", 
    2349                 :          0 :                                 (0xFF &source->buf[i]));
    2350                 :          0 :                         target->BufUsed += 3;
    2351                 :            :                 }
    2352                 :            :         }
    2353                 :          0 :         target->buf[target->BufUsed + 1] = '\0';
    2354                 :            : }
    2355                 :            : 
    2356                 :            : 
    2357                 :            : /*******************************************************************************
    2358                 :            :  *                      Quoted Printable de/encoding                           *
    2359                 :            :  *******************************************************************************/
    2360                 :            : 
    2361                 :            : /**
    2362                 :            :  * @ingroup StrBuf_DeEnCoder
    2363                 :            :  * @brief decode a buffer from base 64 encoding; destroys original
    2364                 :            :  * @param Buf Buffor to transform
    2365                 :            :  */
    2366                 :          0 : int StrBufDecodeBase64(StrBuf *Buf)
    2367                 :            : {
    2368                 :            :         char *xferbuf;
    2369                 :            :         size_t siz;
    2370         [ #  # ]:          0 :         if (Buf == NULL) return -1;
    2371                 :            : 
    2372                 :          0 :         xferbuf = (char*) malloc(Buf->BufSize);
    2373                 :          0 :         *xferbuf = '\0';
    2374                 :          0 :         siz = CtdlDecodeBase64(xferbuf,
    2375                 :          0 :                                Buf->buf,
    2376                 :          0 :                                Buf->BufUsed);
    2377                 :          0 :         free(Buf->buf);
    2378                 :          0 :         Buf->buf = xferbuf;
    2379                 :          0 :         Buf->BufUsed = siz;
    2380                 :          0 :         return siz;
    2381                 :            : }
    2382                 :            : 
    2383                 :            : /**
    2384                 :            :  * @ingroup StrBuf_DeEnCoder
    2385                 :            :  * @brief decode a buffer from base 64 encoding; destroys original
    2386                 :            :  * @param Buf Buffor to transform
    2387                 :            :  */
    2388                 :          0 : int StrBufDecodeHex(StrBuf *Buf)
    2389                 :            : {
    2390                 :            :         unsigned int ch;
    2391                 :            :         char *pch, *pche, *pchi;
    2392                 :            : 
    2393         [ #  # ]:          0 :         if (Buf == NULL) return -1;
    2394                 :            : 
    2395                 :          0 :         pch = pchi = Buf->buf;
    2396                 :          0 :         pche = pch + Buf->BufUsed;
    2397                 :            : 
    2398         [ #  # ]:          0 :         while (pchi < pche){
    2399                 :          0 :                 ch = decode_hex(pchi);
    2400                 :          0 :                 *pch = ch;
    2401                 :          0 :                 pch ++;
    2402                 :          0 :                 pchi += 2;
    2403                 :            :         }
    2404                 :            : 
    2405                 :          0 :         *pch = '\0';
    2406                 :          0 :         Buf->BufUsed = pch - Buf->buf;
    2407                 :          0 :         return Buf->BufUsed;
    2408                 :            : }
    2409                 :            : 
    2410                 :            : /**
    2411                 :            :  * @ingroup StrBuf_DeEnCoder
    2412                 :            :  * @brief replace all chars >0x20 && < 0x7F with Mute
    2413                 :            :  * @param Mute char to put over invalid chars
    2414                 :            :  * @param Buf Buffor to transform
    2415                 :            :  */
    2416                 :          0 : int StrBufSanitizeAscii(StrBuf *Buf, const char Mute)
    2417                 :            : {
    2418                 :            :         unsigned char *pch;
    2419                 :            : 
    2420         [ #  # ]:          0 :         if (Buf == NULL) return -1;
    2421                 :          0 :         pch = (unsigned char *)Buf->buf;
    2422         [ #  # ]:          0 :         while (pch < (unsigned char *)Buf->buf + Buf->BufUsed) {
    2423 [ #  # ][ #  # ]:          0 :                 if ((*pch < 0x20) || (*pch > 0x7F))
    2424                 :          0 :                         *pch = Mute;
    2425                 :          0 :                 pch ++;
    2426                 :            :         }
    2427                 :          0 :         return Buf->BufUsed;
    2428                 :            : }
    2429                 :            : 
    2430                 :            : 
    2431                 :            : /**
    2432                 :            :  * @ingroup StrBuf_DeEnCoder
    2433                 :            :  * @brief remove escaped strings from i.e. the url string (like %20 for blanks)
    2434                 :            :  * @param Buf Buffer to translate
    2435                 :            :  * @param StripBlanks Reduce several blanks to one?
    2436                 :            :  */
    2437                 :          0 : long StrBufUnescape(StrBuf *Buf, int StripBlanks)
    2438                 :            : {
    2439                 :            :         int a, b;
    2440                 :            :         char hex[3];
    2441                 :            :         long len;
    2442                 :            : 
    2443         [ #  # ]:          0 :         if (Buf == NULL)
    2444                 :          0 :                 return -1;
    2445                 :            : 
    2446 [ #  # ][ #  # ]:          0 :         while ((Buf->BufUsed > 0) && (isspace(Buf->buf[Buf->BufUsed - 1]))){
    2447                 :          0 :                 Buf->buf[Buf->BufUsed - 1] = '\0';
    2448                 :          0 :                 Buf->BufUsed --;
    2449                 :            :         }
    2450                 :            : 
    2451                 :          0 :         a = 0; 
    2452         [ #  # ]:          0 :         while (a < Buf->BufUsed) {
    2453         [ #  # ]:          0 :                 if (Buf->buf[a] == '+')
    2454                 :          0 :                         Buf->buf[a] = ' ';
    2455         [ #  # ]:          0 :                 else if (Buf->buf[a] == '%') {
    2456                 :            :                         /* don't let % chars through, rather truncate the input. */
    2457         [ #  # ]:          0 :                         if (a + 2 > Buf->BufUsed) {
    2458                 :          0 :                                 Buf->buf[a] = '\0';
    2459                 :          0 :                                 Buf->BufUsed = a;
    2460                 :            :                         }
    2461                 :            :                         else {                  
    2462                 :          0 :                                 hex[0] = Buf->buf[a + 1];
    2463                 :          0 :                                 hex[1] = Buf->buf[a + 2];
    2464                 :          0 :                                 hex[2] = 0;
    2465                 :          0 :                                 b = 0;
    2466                 :          0 :                                 sscanf(hex, "%02x", &b);
    2467                 :          0 :                                 Buf->buf[a] = (char) b;
    2468                 :          0 :                                 len = Buf->BufUsed - a - 2;
    2469         [ #  # ]:          0 :                                 if (len > 0)
    2470                 :          0 :                                         memmove(&Buf->buf[a + 1], &Buf->buf[a + 3], len);
    2471                 :            :                         
    2472                 :          0 :                                 Buf->BufUsed -=2;
    2473                 :            :                         }
    2474                 :            :                 }
    2475                 :          0 :                 a++;
    2476                 :            :         }
    2477                 :          0 :         return a;
    2478                 :            : }
    2479                 :            : 
    2480                 :            : 
    2481                 :            : /**
    2482                 :            :  * @ingroup StrBuf_DeEnCoder
    2483                 :            :  * @brief       RFC2047-encode a header field if necessary.
    2484                 :            :  *              If no non-ASCII characters are found, the string
    2485                 :            :  *              will be copied verbatim without encoding.
    2486                 :            :  *
    2487                 :            :  * @param       target          Target buffer.
    2488                 :            :  * @param       source          Source string to be encoded.
    2489                 :            :  * @returns     encoded length; -1 if non success.
    2490                 :            :  */
    2491                 :          0 : int StrBufRFC2047encode(StrBuf **target, const StrBuf *source)
    2492                 :            : {
    2493                 :          0 :         const char headerStr[] = "=?UTF-8?Q?";
    2494                 :          0 :         int need_to_encode = 0;
    2495                 :          0 :         int i = 0;
    2496                 :            :         unsigned char ch;
    2497                 :            : 
    2498 [ #  # ][ #  # ]:          0 :         if ((source == NULL) || 
    2499                 :            :             (target == NULL))
    2500                 :          0 :             return -1;
    2501                 :            : 
    2502 [ #  # ][ #  # ]:          0 :         while ((i < source->BufUsed) &&
                 [ #  # ]
    2503                 :          0 :                (!IsEmptyStr (&source->buf[i])) &&
    2504                 :            :                (need_to_encode == 0)) {
    2505 [ #  # ][ #  # ]:          0 :                 if (((unsigned char) source->buf[i] < 32) || 
    2506                 :          0 :                     ((unsigned char) source->buf[i] > 126)) {
    2507                 :          0 :                         need_to_encode = 1;
    2508                 :            :                 }
    2509                 :          0 :                 i++;
    2510                 :            :         }
    2511                 :            : 
    2512         [ #  # ]:          0 :         if (!need_to_encode) {
    2513         [ #  # ]:          0 :                 if (*target == NULL) {
    2514                 :          0 :                         *target = NewStrBufPlain(source->buf, source->BufUsed);
    2515                 :            :                 }
    2516                 :            :                 else {
    2517                 :          0 :                         FlushStrBuf(*target);
    2518                 :          0 :                         StrBufAppendBuf(*target, source, 0);
    2519                 :            :                 }
    2520                 :          0 :                 return (*target)->BufUsed;
    2521                 :            :         }
    2522         [ #  # ]:          0 :         if (*target == NULL)
    2523                 :          0 :                 *target = NewStrBufPlain(NULL, sizeof(headerStr) + source->BufUsed * 2);
    2524         [ #  # ]:          0 :         else if (sizeof(headerStr) + source->BufUsed >= (*target)->BufSize)
    2525                 :          0 :                 IncreaseBuf(*target, sizeof(headerStr) + source->BufUsed, 0);
    2526                 :          0 :         memcpy ((*target)->buf, headerStr, sizeof(headerStr) - 1);
    2527                 :          0 :         (*target)->BufUsed = sizeof(headerStr) - 1;
    2528         [ #  # ]:          0 :         for (i=0; (i < source->BufUsed); ++i) {
    2529         [ #  # ]:          0 :                 if ((*target)->BufUsed + 4 >= (*target)->BufSize)
    2530                 :          0 :                         IncreaseBuf(*target, 1, 0);
    2531                 :          0 :                 ch = (unsigned char) source->buf[i];
    2532 [ #  # ][ #  # ]:          0 :                 if ((ch < 32) || (ch > 126) || (ch == 61)) {
                 [ #  # ]
    2533                 :          0 :                         sprintf(&(*target)->buf[(*target)->BufUsed], "=%02X", ch);
    2534                 :          0 :                         (*target)->BufUsed += 3;
    2535                 :            :                 }
    2536                 :            :                 else {
    2537                 :          0 :                         (*target)->buf[(*target)->BufUsed] = ch;
    2538                 :          0 :                         (*target)->BufUsed++;
    2539                 :            :                 }
    2540                 :            :         }
    2541                 :            :         
    2542         [ #  # ]:          0 :         if ((*target)->BufUsed + 4 >= (*target)->BufSize)
    2543                 :          0 :                 IncreaseBuf(*target, 1, 0);
    2544                 :            : 
    2545                 :          0 :         (*target)->buf[(*target)->BufUsed++] = '?';
    2546                 :          0 :         (*target)->buf[(*target)->BufUsed++] = '=';
    2547                 :          0 :         (*target)->buf[(*target)->BufUsed] = '\0';
    2548                 :          0 :         return (*target)->BufUsed;;
    2549                 :            : }
    2550                 :            : 
    2551                 :            : 
    2552                 :            : 
    2553                 :          0 : static void AddRecipient(StrBuf *Target, 
    2554                 :            :                          StrBuf *UserName, 
    2555                 :            :                          StrBuf *EmailAddress, 
    2556                 :            :                          StrBuf *EncBuf)
    2557                 :            : {
    2558                 :          0 :         int QuoteMe = 0;
    2559                 :            : 
    2560         [ #  # ]:          0 :         if (StrLength(Target) > 0) StrBufAppendBufPlain(Target, HKEY(", "), 0);
    2561         [ #  # ]:          0 :         if (strchr(ChrPtr(UserName), ',') != NULL) QuoteMe = 1;
    2562                 :            : 
    2563         [ #  # ]:          0 :         if (QuoteMe)  StrBufAppendBufPlain(Target, HKEY("\""), 0);
    2564                 :          0 :         StrBufRFC2047encode(&EncBuf, UserName);
    2565                 :          0 :         StrBufAppendBuf(Target, EncBuf, 0);
    2566         [ #  # ]:          0 :         if (QuoteMe)  StrBufAppendBufPlain(Target, HKEY("\" "), 0);
    2567                 :          0 :         else          StrBufAppendBufPlain(Target, HKEY(" "), 0);
    2568                 :            : 
    2569         [ #  # ]:          0 :         if (StrLength(EmailAddress) > 0){
    2570                 :          0 :                 StrBufAppendBufPlain(Target, HKEY("<"), 0);
    2571                 :          0 :                 StrBufAppendBuf(Target, EmailAddress, 0); /* TODO: what about IDN???? */
    2572                 :          0 :                 StrBufAppendBufPlain(Target, HKEY(">"), 0);
    2573                 :            :         }
    2574                 :          0 : }
    2575                 :            : 
    2576                 :            : 
    2577                 :            : /**
    2578                 :            :  * \brief QP encode parts of an email TO/CC/BCC vector, and strip/filter invalid parts
    2579                 :            :  * \param Recp Source list of email recipients
    2580                 :            :  * \param UserName Temporary buffer for internal use; Please provide valid buffer.
    2581                 :            :  * \param EmailAddress Temporary buffer for internal use; Please provide valid buffer.
    2582                 :            :  * \param EncBuf Temporary buffer for internal use; Please provide valid buffer.
    2583                 :            :  * \returns encoded & sanitized buffer with the contents of Recp; Caller owns this memory.
    2584                 :            :  */
    2585                 :          0 : StrBuf *StrBufSanitizeEmailRecipientVector(const StrBuf *Recp, 
    2586                 :            :                                            StrBuf *UserName, 
    2587                 :            :                                            StrBuf *EmailAddress,
    2588                 :            :                                            StrBuf *EncBuf)
    2589                 :            : {
    2590                 :            :         StrBuf *Target;
    2591                 :            :         int need_to_encode;
    2592                 :            : 
    2593                 :            :         const char *pch, *pche;
    2594                 :            :         const char *UserStart, *UserEnd, *EmailStart, *EmailEnd, *At;
    2595                 :            : 
    2596 [ #  # ][ #  # ]:          0 :         if ((Recp == NULL) || (StrLength(Recp) == 0))
    2597                 :          0 :                 return NULL;
    2598                 :            : 
    2599                 :          0 :         need_to_encode = 0;
    2600                 :          0 :         pch = ChrPtr(Recp);
    2601                 :          0 :         pche = pch + StrLength(Recp);
    2602                 :            : 
    2603         [ #  # ]:          0 :         if (!CheckEncode(pch, -1, pche))
    2604                 :          0 :                 return NewStrBufDup(Recp);
    2605                 :            : 
    2606                 :          0 :         Target = NewStrBufPlain(NULL, StrLength(Recp));
    2607                 :            : 
    2608 [ #  # ][ #  # ]:          0 :         while ((pch != NULL) && (pch < pche))
    2609                 :            :         {
    2610                 :          0 :                 int ColonOk = 0;
    2611                 :            : 
    2612         [ #  # ]:          0 :                 while (isspace(*pch)) pch++;
    2613                 :          0 :                 UserStart = UserEnd = EmailStart = EmailEnd = NULL;
    2614                 :            :                 
    2615 [ #  # ][ #  # ]:          0 :                 if ((*pch == '"') || (*pch == '\'')) {
    2616                 :          0 :                         UserStart = pch + 1;
    2617                 :            :                         
    2618                 :          0 :                         UserEnd = strchr(UserStart, *pch);
    2619         [ #  # ]:          0 :                         if (UserEnd == NULL) 
    2620                 :          0 :                                 break; ///TODO: Userfeedback??
    2621                 :          0 :                         EmailStart = UserEnd + 1;
    2622         [ #  # ]:          0 :                         while (isspace(*EmailStart))
    2623                 :          0 :                                 EmailStart++;
    2624         [ #  # ]:          0 :                         if (UserEnd == UserStart) {
    2625                 :          0 :                                 UserStart = UserEnd = NULL;
    2626                 :            :                         }
    2627                 :            :                         
    2628         [ #  # ]:          0 :                         if (*EmailStart == '<') {
    2629                 :          0 :                                 EmailStart++;
    2630                 :          0 :                                 EmailEnd = strchr(EmailStart, '>');
    2631         [ #  # ]:          0 :                                 if (EmailEnd == NULL)
    2632                 :          0 :                                         EmailEnd = strchr(EmailStart, ',');
    2633                 :            :                                 
    2634                 :            :                         }
    2635                 :            :                         else {
    2636                 :          0 :                                 EmailEnd = strchr(EmailStart, ',');
    2637                 :            :                         }
    2638         [ #  # ]:          0 :                         if (EmailEnd == NULL)
    2639                 :          0 :                                 EmailEnd = pche;
    2640                 :          0 :                         pch = EmailEnd + 1;
    2641                 :          0 :                         ColonOk = 1;
    2642                 :            :                 }
    2643                 :            :                 else {
    2644                 :          0 :                         int gt = 0;
    2645                 :          0 :                         UserStart = pch;
    2646                 :          0 :                         EmailEnd = strchr(UserStart, ',');
    2647         [ #  # ]:          0 :                         if (EmailEnd == NULL) {
    2648                 :          0 :                                 EmailEnd = strchr(pch, '>');
    2649                 :          0 :                                 pch = NULL;
    2650         [ #  # ]:          0 :                                 if (EmailEnd != NULL) {
    2651                 :          0 :                                         gt = 1;
    2652                 :            :                                 }
    2653                 :            :                                 else {
    2654                 :          0 :                                         EmailEnd = pche;
    2655                 :            :                                 }
    2656                 :            :                         }
    2657                 :            :                         else {
    2658                 :            : 
    2659                 :          0 :                                 pch = EmailEnd + 1;
    2660 [ #  # ][ #  # ]:          0 :                                 while ((EmailEnd > UserStart) && !gt &&
                 [ #  # ]
           [ #  #  #  # ]
    2661                 :          0 :                                        ((*EmailEnd == ',') ||
    2662                 :          0 :                                         (*EmailEnd == '>') ||
    2663                 :          0 :                                         (isspace(*EmailEnd))))
    2664                 :            :                                 {
    2665         [ #  # ]:          0 :                                         if (*EmailEnd == '>')
    2666                 :          0 :                                                 gt = 1;
    2667                 :            :                                         else 
    2668                 :          0 :                                                 EmailEnd--;
    2669                 :            :                                 }
    2670         [ #  # ]:          0 :                                 if (EmailEnd == UserStart)
    2671                 :          0 :                                         break;
    2672                 :            :                         }
    2673         [ #  # ]:          0 :                         if (gt) {
    2674                 :          0 :                                 EmailStart = strchr(UserStart, '<');
    2675 [ #  # ][ #  # ]:          0 :                                 if ((EmailStart == NULL) || (EmailStart > EmailEnd))
    2676                 :            :                                         break;
    2677                 :          0 :                                 UserEnd = EmailStart;
    2678                 :            : 
    2679   [ #  #  #  # ]:          0 :                                 while ((UserEnd > UserStart) && 
    2680                 :          0 :                                        isspace (*(UserEnd - 1)))
    2681                 :          0 :                                         UserEnd --;
    2682                 :          0 :                                 EmailStart ++;
    2683         [ #  # ]:          0 :                                 if (UserStart >= UserEnd)
    2684                 :          0 :                                         UserStart = UserEnd = NULL;
    2685                 :          0 :                                 At = strchr(EmailStart, '@');
    2686                 :            :                         }
    2687                 :            :                         else { /* this is a local recipient... no domain, just a realname */
    2688                 :          0 :                                 EmailStart = UserStart;
    2689                 :          0 :                                 At = strchr(EmailStart, '@');
    2690         [ #  # ]:          0 :                                 if (At == NULL) {
    2691                 :          0 :                                         UserEnd = EmailEnd;
    2692                 :          0 :                                         EmailEnd = NULL;
    2693                 :            :                                 }
    2694                 :            :                                 else {
    2695                 :          0 :                                         EmailStart = UserStart;
    2696                 :          0 :                                         UserStart = NULL;
    2697                 :            :                                 }
    2698                 :            :                         }
    2699                 :            :                 }
    2700                 :            : 
    2701 [ #  # ][ #  # ]:          0 :                 if ((UserStart != NULL) && (UserEnd != NULL))
    2702                 :          0 :                         StrBufPlain(UserName, UserStart, UserEnd - UserStart);
    2703 [ #  # ][ #  # ]:          0 :                 else if ((UserStart != NULL) && (UserEnd == NULL))
    2704                 :          0 :                         StrBufPlain(UserName, UserStart, UserEnd - UserStart);
    2705                 :            :                 else
    2706                 :          0 :                         FlushStrBuf(UserName);
    2707                 :            : 
    2708 [ #  # ][ #  # ]:          0 :                 if ((EmailStart != NULL) && (EmailEnd != NULL))
    2709                 :          0 :                         StrBufPlain(EmailAddress, EmailStart, EmailEnd - EmailStart);
    2710 [ #  # ][ #  # ]:          0 :                 else if ((EmailStart != NULL) && (EmailEnd == NULL))
    2711                 :          0 :                         StrBufPlain(EmailAddress, EmailStart, EmailEnd - pche);
    2712                 :            :                 else 
    2713                 :          0 :                         FlushStrBuf(EmailAddress);
    2714                 :            : 
    2715                 :          0 :                 AddRecipient(Target, UserName, EmailAddress, EncBuf);
    2716                 :            : 
    2717         [ #  # ]:          0 :                 if (pch == NULL)
    2718                 :          0 :                         break;
    2719                 :            :                 
    2720 [ #  # ][ #  # ]:          0 :                 if ((pch != NULL) && (*pch == ','))
    2721                 :          0 :                         pch ++;
    2722 [ #  # ][ #  # ]:          0 :                 if (pch != NULL) while (isspace(*pch))
    2723                 :          0 :                         pch ++;
    2724                 :            :         }
    2725                 :          0 :         return Target;
    2726                 :            : }
    2727                 :            : 
    2728                 :            : 
    2729                 :            : /**
    2730                 :            :  * @ingroup StrBuf
    2731                 :            :  * @brief replaces all occurances of 'search' by 'replace'
    2732                 :            :  * @param buf Buffer to modify
    2733                 :            :  * @param search character to search
    2734                 :            :  * @param replace character to replace search by
    2735                 :            :  */
    2736                 :          0 : void StrBufReplaceChars(StrBuf *buf, char search, char replace)
    2737                 :            : {
    2738                 :            :         long i;
    2739         [ #  # ]:          0 :         if (buf == NULL)
    2740                 :          0 :                 return;
    2741         [ #  # ]:          0 :         for (i=0; i<buf->BufUsed; i++)
    2742         [ #  # ]:          0 :                 if (buf->buf[i] == search)
    2743                 :          0 :                         buf->buf[i] = replace;
    2744                 :            : 
    2745                 :            : }
    2746                 :            : 
    2747                 :            : /**
    2748                 :            :  * @ingroup StrBuf
    2749                 :            :  * @brief removes all \r s from the string, or replaces them with \n if its not a combination of both.
    2750                 :            :  * @param buf Buffer to modify
    2751                 :            :  */
    2752                 :          0 : void StrBufToUnixLF(StrBuf *buf)
    2753                 :            : {
    2754                 :            :         char *pche, *pchS, *pchT;
    2755         [ #  # ]:          0 :         if (buf == NULL)
    2756                 :          0 :                 return;
    2757                 :            : 
    2758                 :          0 :         pche = buf->buf + buf->BufUsed;
    2759                 :          0 :         pchS = pchT = buf->buf;
    2760         [ #  # ]:          0 :         while (pchS < pche)
    2761                 :            :         {
    2762         [ #  # ]:          0 :                 if (*pchS == '\r')
    2763                 :            :                 {
    2764                 :          0 :                         pchS ++;
    2765         [ #  # ]:          0 :                         if (*pchS != '\n') {
    2766                 :          0 :                                 *pchT = '\n';
    2767                 :          0 :                                 pchT++;
    2768                 :            :                         }
    2769                 :            :                 }
    2770                 :          0 :                 *pchT = *pchS;
    2771                 :          0 :                 pchT++; pchS++;
    2772                 :            :         }
    2773                 :          0 :         *pchT = '\0';
    2774                 :          0 :         buf->BufUsed = pchT - buf->buf;
    2775                 :            : }
    2776                 :            : 
    2777                 :            : 
    2778                 :            : /*******************************************************************************
    2779                 :            :  *                 Iconv Wrapper; RFC822 de/encoding                           *
    2780                 :            :  *******************************************************************************/
    2781                 :            : 
    2782                 :            : /**
    2783                 :            :  * @ingroup StrBuf_DeEnCoder
    2784                 :            :  * @brief Wrapper around iconv_open()
    2785                 :            :  * Our version adds aliases for non-standard Microsoft charsets
    2786                 :            :  * such as 'MS950', aliasing them to names like 'CP950'
    2787                 :            :  *
    2788                 :            :  * @param tocode        Target encoding
    2789                 :            :  * @param fromcode      Source encoding
    2790                 :            :  * @param pic           anonimized pointer to iconv struct
    2791                 :            :  */
    2792                 :         25 : void  ctdl_iconv_open(const char *tocode, const char *fromcode, void *pic)
    2793                 :            : {
    2794                 :            : #ifdef HAVE_ICONV
    2795                 :         25 :         iconv_t ic = (iconv_t)(-1) ;
    2796                 :         25 :         ic = iconv_open(tocode, fromcode);
    2797         [ -  + ]:         25 :         if (ic == (iconv_t)(-1) ) {
    2798                 :            :                 char alias_fromcode[64];
    2799 [ #  # ][ #  # ]:          0 :                 if ( (strlen(fromcode) == 5) && (!strncasecmp(fromcode, "MS", 2)) ) {
    2800                 :          0 :                         safestrncpy(alias_fromcode, fromcode, sizeof alias_fromcode);
    2801                 :          0 :                         alias_fromcode[0] = 'C';
    2802                 :          0 :                         alias_fromcode[1] = 'P';
    2803                 :          0 :                         ic = iconv_open(tocode, alias_fromcode);
    2804                 :            :                 }
    2805                 :            :         }
    2806                 :         25 :         *(iconv_t *)pic = ic;
    2807                 :            : #endif
    2808                 :         25 : }
    2809                 :            : 
    2810                 :            : 
    2811                 :            : /**
    2812                 :            :  * @ingroup StrBuf_DeEnCoder
    2813                 :            :  * @brief find one chunk of a RFC822 encoded string
    2814                 :            :  * @param Buffer where to search
    2815                 :            :  * @param bptr where to start searching
    2816                 :            :  * @returns found position, NULL if none.
    2817                 :            :  */
    2818                 :         20 : static inline const char *FindNextEnd (const StrBuf *Buf, const char *bptr)
    2819                 :            : {
    2820                 :            :         const char * end;
    2821                 :            :         /* Find the next ?Q? */
    2822         [ -  + ]:         20 :         if (Buf->BufUsed - (bptr - Buf->buf)  < 6)
    2823                 :          0 :                 return NULL;
    2824                 :            : 
    2825                 :         20 :         end = strchr(bptr + 2, '?');
    2826                 :            : 
    2827         [ -  + ]:         20 :         if (end == NULL)
    2828                 :          0 :                 return NULL;
    2829                 :            : 
    2830 [ +  - ][ +  + ]:         20 :         if ((Buf->BufUsed - (end - Buf->buf) > 3) &&
         [ +  - ][ +  - ]
    2831                 :         36 :             ((*(end + 1) == 'B') || (*(end + 1) == 'Q')) && 
    2832                 :         20 :             (*(end + 2) == '?')) {
    2833                 :            :                 /* skip on to the end of the cluster, the next ?= */
    2834                 :         20 :                 end = strstr(end + 3, "?=");
    2835                 :            :         }
    2836                 :            :         else
    2837                 :            :                 /* sort of half valid encoding, try to find an end. */
    2838                 :          0 :                 end = strstr(bptr, "?=");
    2839                 :         20 :         return end;
    2840                 :            : }
    2841                 :            : 
    2842                 :            : 
    2843                 :            : 
    2844                 :            : /**
    2845                 :            :  * @ingroup StrBuf_DeEnCoder
    2846                 :            :  * @brief convert one buffer according to the preselected iconv pointer PIC
    2847                 :            :  * @param ConvertBuf buffer we need to translate
    2848                 :            :  * @param TmpBuf To share a workbuffer over several iterations. prepare to have it filled with useless stuff afterwards.
    2849                 :            :  * @param pic Pointer to the iconv-session Object
    2850                 :            :  */
    2851                 :         25 : void StrBufConvert(StrBuf *ConvertBuf, StrBuf *TmpBuf, void *pic)
    2852                 :            : {
    2853                 :            : #ifdef HAVE_ICONV
    2854                 :         25 :         long trycount = 0;
    2855                 :            :         size_t siz;
    2856                 :            :         iconv_t ic;
    2857                 :            :         char *ibuf;                     /**< Buffer of characters to be converted */
    2858                 :            :         char *obuf;                     /**< Buffer for converted characters */
    2859                 :            :         size_t ibuflen;                 /**< Length of input buffer */
    2860                 :            :         size_t obuflen;                 /**< Length of output buffer */
    2861                 :            : 
    2862                 :            : 
    2863                 :            :         /* since we're converting to utf-8, one glyph may take up to 6 bytes */
    2864         [ +  + ]:         25 :         if (ConvertBuf->BufUsed * 6 >= TmpBuf->BufSize)
    2865                 :          9 :                 IncreaseBuf(TmpBuf, 0, ConvertBuf->BufUsed * 6);
    2866                 :            : TRYAGAIN:
    2867                 :         25 :         ic = *(iconv_t*)pic;
    2868                 :         25 :         ibuf = ConvertBuf->buf;
    2869                 :         25 :         ibuflen = ConvertBuf->BufUsed;
    2870                 :         25 :         obuf = TmpBuf->buf;
    2871                 :         25 :         obuflen = TmpBuf->BufSize;
    2872                 :            :         
    2873                 :         25 :         siz = iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
    2874                 :            : 
    2875                 :            :         if (siz < 0) {
    2876                 :            :                 if (errno == E2BIG) {
    2877                 :            :                         trycount ++;                    
    2878                 :            :                         IncreaseBuf(TmpBuf, 0, 0);
    2879                 :            :                         if (trycount < 5) 
    2880                 :            :                                 goto TRYAGAIN;
    2881                 :            : 
    2882                 :            :                 }
    2883                 :            :                 else if (errno == EILSEQ){ 
    2884                 :            :                         /* hm, invalid utf8 sequence... what to do now? */
    2885                 :            :                         /* An invalid multibyte sequence has been encountered in the input */
    2886                 :            :                 }
    2887                 :            :                 else if (errno == EINVAL) {
    2888                 :            :                         /* An incomplete multibyte sequence has been encountered in the input. */
    2889                 :            :                 }
    2890                 :            : 
    2891                 :            :                 FlushStrBuf(TmpBuf);
    2892                 :            :         }
    2893                 :            :         else {
    2894                 :         25 :                 TmpBuf->BufUsed = TmpBuf->BufSize - obuflen;
    2895                 :         25 :                 TmpBuf->buf[TmpBuf->BufUsed] = '\0';
    2896                 :            :                 
    2897                 :            :                 /* little card game: wheres the red lady? */
    2898                 :         25 :                 SwapBuffers(ConvertBuf, TmpBuf);
    2899                 :         25 :                 FlushStrBuf(TmpBuf);
    2900                 :            :         }
    2901                 :            : #endif
    2902                 :         25 : }
    2903                 :            : 
    2904                 :            : 
    2905                 :            : /**
    2906                 :            :  * @ingroup StrBuf_DeEnCoder
    2907                 :            :  * @brief catches one RFC822 encoded segment, and decodes it.
    2908                 :            :  * @param Target buffer to fill with result
    2909                 :            :  * @param DecodeMe buffer with stuff to process
    2910                 :            :  * @param SegmentStart points to our current segment in DecodeMe
    2911                 :            :  * @param SegmentEnd Points to the end of our current segment in DecodeMe
    2912                 :            :  * @param ConvertBuf Workbuffer shared between several iterations. Random content; needs to be valid
    2913                 :            :  * @param ConvertBuf2 Workbuffer shared between several iterations. Random content; needs to be valid
    2914                 :            :  * @param FoundCharset Characterset to default decoding to; if we find another we will overwrite it.
    2915                 :            :  */
    2916                 :         20 : inline static void DecodeSegment(StrBuf *Target, 
    2917                 :            :                                  const StrBuf *DecodeMe, 
    2918                 :            :                                  const char *SegmentStart, 
    2919                 :            :                                  const char *SegmentEnd, 
    2920                 :            :                                  StrBuf *ConvertBuf,
    2921                 :            :                                  StrBuf *ConvertBuf2, 
    2922                 :            :                                  StrBuf *FoundCharset)
    2923                 :            : {
    2924                 :            :         StrBuf StaticBuf;
    2925                 :            :         char charset[128];
    2926                 :            :         char encoding[16];
    2927                 :            : #ifdef HAVE_ICONV
    2928                 :         20 :         iconv_t ic = (iconv_t)(-1);
    2929                 :            : #else
    2930                 :            :         void *ic = NULL;
    2931                 :            : #endif
    2932                 :            :         /* Now we handle foreign character sets properly encoded
    2933                 :            :          * in RFC2047 format.
    2934                 :            :          */
    2935                 :         20 :         StaticBuf.buf = (char*) SegmentStart; /*< it will just be read there... */
    2936                 :         20 :         StaticBuf.BufUsed = SegmentEnd - SegmentStart;
    2937                 :         20 :         StaticBuf.BufSize = DecodeMe->BufSize - (SegmentStart - DecodeMe->buf);
    2938                 :         20 :         extract_token(charset, SegmentStart, 1, '?', sizeof charset);
    2939         [ +  - ]:         20 :         if (FoundCharset != NULL) {
    2940                 :         20 :                 FlushStrBuf(FoundCharset);
    2941                 :         20 :                 StrBufAppendBufPlain(FoundCharset, charset, -1, 0);
    2942                 :            :         }
    2943                 :         20 :         extract_token(encoding, SegmentStart, 2, '?', sizeof encoding);
    2944                 :         20 :         StrBufExtract_token(ConvertBuf, &StaticBuf, 3, '?');
    2945                 :            :         
    2946                 :         20 :         *encoding = toupper(*encoding);
    2947         [ +  + ]:         20 :         if (*encoding == 'B') { /**< base64 */
    2948         [ -  + ]:          4 :                 if (ConvertBuf2->BufSize < ConvertBuf->BufUsed)
    2949                 :          0 :                         IncreaseBuf(ConvertBuf2, 0, ConvertBuf->BufUsed);
    2950                 :          4 :                 ConvertBuf2->BufUsed = CtdlDecodeBase64(ConvertBuf2->buf, 
    2951                 :          4 :                                                         ConvertBuf->buf, 
    2952                 :          4 :                                                         ConvertBuf->BufUsed);
    2953                 :            :         }
    2954         [ +  - ]:         16 :         else if (*encoding == 'Q') {    /**< quoted-printable */
    2955                 :            :                 long pos;
    2956                 :            :                 
    2957                 :         16 :                 pos = 0;
    2958         [ +  + ]:        156 :                 while (pos < ConvertBuf->BufUsed)
    2959                 :            :                 {
    2960         [ +  + ]:        140 :                         if (ConvertBuf->buf[pos] == '_') 
    2961                 :          8 :                                 ConvertBuf->buf[pos] = ' ';
    2962                 :        140 :                         pos++;
    2963                 :            :                 }
    2964                 :            :                 
    2965         [ -  + ]:         16 :                 if (ConvertBuf2->BufSize < ConvertBuf->BufUsed)
    2966                 :          0 :                         IncreaseBuf(ConvertBuf2, 0, ConvertBuf->BufUsed);
    2967                 :            : 
    2968                 :         16 :                 ConvertBuf2->BufUsed = CtdlDecodeQuotedPrintable(
    2969                 :            :                         ConvertBuf2->buf, 
    2970                 :            :                         ConvertBuf->buf,
    2971                 :         16 :                         ConvertBuf->BufUsed);
    2972                 :            :         }
    2973                 :            :         else {
    2974                 :          0 :                 StrBufAppendBuf(ConvertBuf2, ConvertBuf, 0);
    2975                 :            :         }
    2976                 :            : #ifdef HAVE_ICONV
    2977                 :         20 :         ctdl_iconv_open("UTF-8", charset, &ic);
    2978         [ +  - ]:         20 :         if (ic != (iconv_t)(-1) ) {             
    2979                 :            : #endif
    2980                 :         20 :                 StrBufConvert(ConvertBuf2, ConvertBuf, &ic);
    2981                 :         20 :                 StrBufAppendBuf(Target, ConvertBuf2, 0);
    2982                 :            : #ifdef HAVE_ICONV
    2983                 :         20 :                 iconv_close(ic);
    2984                 :            :         }
    2985                 :            :         else {
    2986                 :          0 :                 StrBufAppendBufPlain(Target, HKEY("(unreadable)"), 0);
    2987                 :            :         }
    2988                 :            : #endif
    2989                 :         20 : }
    2990                 :            : 
    2991                 :            : /**
    2992                 :            :  * @ingroup StrBuf_DeEnCoder
    2993                 :            :  * @brief Handle subjects with RFC2047 encoding such as: [deprecated old syntax!]
    2994                 :            :  * =?koi8-r?B?78bP0s3Mxc7JxSDXz9rE1dvO2c3JINvB0sHNySDP?=
    2995                 :            :  * @param Target where to put the decoded string to 
    2996                 :            :  * @param DecodeMe buffer with encoded string
    2997                 :            :  * @param DefaultCharset if we don't find one, which should we use?
    2998                 :            :  * @param FoundCharset overrides DefaultCharset if non-empty; If we find a charset inside of the string, 
    2999                 :            :  *        put it here for later use where no string might be known.
    3000                 :            :  */
    3001                 :         17 : void StrBuf_RFC822_to_Utf8(StrBuf *Target, const StrBuf *DecodeMe, const StrBuf* DefaultCharset, StrBuf *FoundCharset)
    3002                 :            : {
    3003                 :            :         StrBuf *ConvertBuf;
    3004                 :            :         StrBuf *ConvertBuf2;
    3005                 :         17 :         ConvertBuf = NewStrBufPlain(NULL, StrLength(DecodeMe));
    3006                 :         17 :         ConvertBuf2 = NewStrBufPlain(NULL, StrLength(DecodeMe));
    3007                 :            :         
    3008                 :         17 :         StrBuf_RFC822_2_Utf8(Target, 
    3009                 :            :                              DecodeMe, 
    3010                 :            :                              DefaultCharset, 
    3011                 :            :                              FoundCharset, 
    3012                 :            :                              ConvertBuf, 
    3013                 :            :                              ConvertBuf2);
    3014                 :         17 :         FreeStrBuf(&ConvertBuf);
    3015                 :         17 :         FreeStrBuf(&ConvertBuf2);
    3016                 :         17 : }
    3017                 :            : 
    3018                 :            : /**
    3019                 :            :  * @ingroup StrBuf_DeEnCoder
    3020                 :            :  * @brief Handle subjects with RFC2047 encoding such as:
    3021                 :            :  * =?koi8-r?B?78bP0s3Mxc7JxSDXz9rE1dvO2c3JINvB0sHNySDP?=
    3022                 :            :  * @param Target where to put the decoded string to 
    3023                 :            :  * @param DecodeMe buffer with encoded string
    3024                 :            :  * @param DefaultCharset if we don't find one, which should we use?
    3025                 :            :  * @param FoundCharset overrides DefaultCharset if non-empty; If we find a charset inside of the string, 
    3026                 :            :  *        put it here for later use where no string might be known.
    3027                 :            :  * @param ConvertBuf workbuffer. feed in, you shouldn't care about its content.
    3028                 :            :  * @param ConvertBuf2 workbuffer. feed in, you shouldn't care about its content.
    3029                 :            :  */
    3030                 :         17 : void StrBuf_RFC822_2_Utf8(StrBuf *Target, 
    3031                 :            :                           const StrBuf *DecodeMe, 
    3032                 :            :                           const StrBuf* DefaultCharset, 
    3033                 :            :                           StrBuf *FoundCharset, 
    3034                 :            :                           StrBuf *ConvertBuf, 
    3035                 :            :                           StrBuf *ConvertBuf2)
    3036                 :            : {
    3037                 :         17 :         StrBuf *DecodedInvalidBuf = NULL;
    3038                 :         17 :         const StrBuf *DecodeMee = DecodeMe;
    3039                 :         17 :         const char *start, *end, *next, *nextend, *ptr = NULL;
    3040                 :            : #ifdef HAVE_ICONV
    3041                 :         17 :         iconv_t ic = (iconv_t)(-1) ;
    3042                 :            : #endif
    3043                 :            :         const char *eptr;
    3044                 :         17 :         int passes = 0;
    3045                 :            :         int i, len;
    3046                 :         17 :         int illegal_non_rfc2047_encoding = 0;
    3047                 :            : 
    3048                 :            :         /* Sometimes, badly formed messages contain strings which were simply
    3049                 :            :          *  written out directly in some foreign character set instead of
    3050                 :            :          *  using RFC2047 encoding.  This is illegal but we will attempt to
    3051                 :            :          *  handle it anyway by converting from a user-specified default
    3052                 :            :          *  charset to UTF-8 if we see any nonprintable characters.
    3053                 :            :          */
    3054                 :            :         
    3055                 :         17 :         len = StrLength(DecodeMe);
    3056         [ +  + ]:       1398 :         for (i=0; i<DecodeMe->BufUsed; ++i) {
    3057 [ +  + ][ -  + ]:       1386 :                 if ((DecodeMe->buf[i] < 32) || (DecodeMe->buf[i] > 126)) {
    3058                 :          5 :                         illegal_non_rfc2047_encoding = 1;
    3059                 :          5 :                         break;
    3060                 :            :                 }
    3061                 :            :         }
    3062                 :            : 
    3063 [ +  +  +  -  + :         27 :         if ((illegal_non_rfc2047_encoding) &&
                      - ]
    3064                 :          5 :             (strcasecmp(ChrPtr(DefaultCharset), "UTF-8")) && 
    3065                 :          5 :             (strcasecmp(ChrPtr(DefaultCharset), "us-ascii")) )
    3066                 :            :         {
    3067                 :            : #ifdef HAVE_ICONV
    3068                 :          5 :                 ctdl_iconv_open("UTF-8", ChrPtr(DefaultCharset), &ic);
    3069         [ +  - ]:          5 :                 if (ic != (iconv_t)(-1) ) {
    3070                 :          5 :                         DecodedInvalidBuf = NewStrBufDup(DecodeMe);
    3071                 :          5 :                         StrBufConvert(DecodedInvalidBuf, ConvertBuf, &ic);///TODO: don't void const?
    3072                 :          5 :                         DecodeMee = DecodedInvalidBuf;
    3073                 :          5 :                         iconv_close(ic);
    3074                 :            :                 }
    3075                 :            : #endif
    3076                 :            :         }
    3077                 :            : 
    3078                 :            :         /* pre evaluate the first pair */
    3079                 :         17 :         nextend = end = NULL;
    3080                 :         17 :         len = StrLength(DecodeMee);
    3081                 :         17 :         start = strstr(DecodeMee->buf, "=?");
    3082                 :         17 :         eptr = DecodeMee->buf + DecodeMee->BufUsed;
    3083         [ +  + ]:         17 :         if (start != NULL) 
    3084                 :          8 :                 end = FindNextEnd (DecodeMee, start);
    3085                 :            :         else {
    3086                 :          9 :                 StrBufAppendBuf(Target, DecodeMee, 0);
    3087                 :          9 :                 FreeStrBuf(&DecodedInvalidBuf);
    3088                 :          9 :                 return;
    3089                 :            :         }
    3090                 :            : 
    3091                 :            : 
    3092         [ +  + ]:          8 :         if (start != DecodeMee->buf) {
    3093                 :            :                 long nFront;
    3094                 :            :                 
    3095                 :          4 :                 nFront = start - DecodeMee->buf;
    3096                 :          4 :                 StrBufAppendBufPlain(Target, DecodeMee->buf, nFront, 0);
    3097                 :          4 :                 len -= nFront;
    3098                 :            :         }
    3099                 :            :         /*
    3100                 :            :          * Since spammers will go to all sorts of absurd lengths to get their
    3101                 :            :          * messages through, there are LOTS of corrupt headers out there.
    3102                 :            :          * So, prevent a really badly formed RFC2047 header from throwing
    3103                 :            :          * this function into an infinite loop.
    3104                 :            :          */
    3105 [ +  + ][ +  - ]:         28 :         while ((start != NULL) && 
         [ +  - ][ +  - ]
                 [ +  - ]
    3106                 :            :                (end != NULL) && 
    3107                 :            :                (start < eptr) && 
    3108                 :            :                (end < eptr) && 
    3109                 :            :                (passes < 20))
    3110                 :            :         {
    3111                 :         20 :                 passes++;
    3112                 :         20 :                 DecodeSegment(Target, 
    3113                 :            :                               DecodeMee, 
    3114                 :            :                               start, 
    3115                 :            :                               end, 
    3116                 :            :                               ConvertBuf,
    3117                 :            :                               ConvertBuf2,
    3118                 :            :                               FoundCharset);
    3119                 :            :                 
    3120                 :         20 :                 next = strstr(end, "=?");
    3121                 :         20 :                 nextend = NULL;
    3122   [ +  +  +  - ]:         20 :                 if ((next != NULL) && 
    3123                 :            :                     (next < eptr))
    3124                 :         12 :                         nextend = FindNextEnd(DecodeMee, next);
    3125         [ +  + ]:         20 :                 if (nextend == NULL)
    3126                 :          8 :                         next = NULL;
    3127                 :            : 
    3128                 :            :                 /* did we find two partitions */
    3129 [ +  + ][ +  - ]:         20 :                 if ((next != NULL) && 
    3130                 :         12 :                     ((next - end) > 2))
    3131                 :            :                 {
    3132                 :         12 :                         ptr = end + 2;
    3133   [ +  +  +  + ]:         40 :                         while ((ptr < next) && 
         [ -  + ][ -  + ]
                 [ -  + ]
    3134                 :         16 :                                (isspace(*ptr) ||
    3135                 :          4 :                                 (*ptr == '\r') ||
    3136                 :          4 :                                 (*ptr == '\n') || 
    3137                 :          4 :                                 (*ptr == '\t')))
    3138                 :         12 :                                 ptr ++;
    3139                 :            :                         /* 
    3140                 :            :                          * did we find a gab just filled with blanks?
    3141                 :            :                          * if not, copy its stuff over.
    3142                 :            :                          */
    3143         [ +  + ]:         12 :                         if (ptr != next)
    3144                 :            :                         {
    3145                 :          4 :                                 StrBufAppendBufPlain(Target, 
    3146                 :            :                                                      end + 2, 
    3147                 :          4 :                                                      next - end - 2,
    3148                 :            :                                                      0);
    3149                 :            :                         }
    3150                 :            :                 }
    3151                 :            :                 /* our next-pair is our new first pair now. */
    3152                 :         20 :                 ptr = end + 2;
    3153                 :         20 :                 start = next;
    3154                 :         20 :                 end = nextend;
    3155                 :            :         }
    3156                 :          8 :         end = ptr;
    3157                 :          8 :         nextend = DecodeMee->buf + DecodeMee->BufUsed;
    3158 [ +  - ][ +  + ]:          8 :         if ((end != NULL) && (end < nextend)) {
    3159                 :          4 :                 ptr = end;
    3160   [ +  -  +  + ]:         16 :                 while ( (ptr < nextend) &&
         [ -  + ][ -  + ]
                 [ -  + ]
    3161                 :          8 :                         (isspace(*ptr) ||
    3162                 :          4 :                          (*ptr == '\r') ||
    3163                 :          4 :                          (*ptr == '\n') || 
    3164                 :          4 :                          (*ptr == '\t')))
    3165                 :          4 :                         ptr ++;
    3166         [ +  - ]:          4 :                 if (ptr < nextend)
    3167                 :          4 :                         StrBufAppendBufPlain(Target, end, nextend - end, 0);
    3168                 :            :         }
    3169                 :         17 :         FreeStrBuf(&DecodedInvalidBuf);
    3170                 :            : }
    3171                 :            : 
    3172                 :            : /*******************************************************************************
    3173                 :            :  *                   Manipulating UTF-8 Strings                                *
    3174                 :            :  *******************************************************************************/
    3175                 :            : 
    3176                 :            : /**
    3177                 :            :  * @ingroup StrBuf
    3178                 :            :  * @brief evaluate the length of an utf8 special character sequence
    3179                 :            :  * @param Char the character to examine
    3180                 :            :  * @returns width of utf8 chars in bytes
    3181                 :            :  */
    3182                 :          0 : static inline int Ctdl_GetUtf8SequenceLength(const char *CharS, const char *CharE)
    3183                 :            : {
    3184                 :          0 :         int n = 1;
    3185                 :          0 :         char test = (1<<7);
    3186                 :            :         
    3187 [ #  # ][ #  # ]:          0 :         while ((n < 8) && ((test & *CharS) != 0)) {
    3188                 :          0 :                 test = test << 1;
    3189                 :          0 :                 n ++;
    3190                 :            :         }
    3191 [ #  # ][ #  # ]:          0 :         if ((n > 6) || ((CharE - CharS) < n))
    3192                 :          0 :                 n = 1;
    3193                 :          0 :         return n;
    3194                 :            : }
    3195                 :            : 
    3196                 :            : /**
    3197                 :            :  * @ingroup StrBuf
    3198                 :            :  * @brief detect whether this char starts an utf-8 encoded char
    3199                 :            :  * @param Char character to inspect
    3200                 :            :  * @returns yes or no
    3201                 :            :  */
    3202                 :          0 : static inline int Ctdl_IsUtf8SequenceStart(const char Char)
    3203                 :            : {
    3204                 :            : /** 11??.???? indicates an UTF8 Sequence. */
    3205                 :          0 :         return ((Char & 0xC0) != 0);
    3206                 :            : }
    3207                 :            : 
    3208                 :            : /**
    3209                 :            :  * @ingroup StrBuf
    3210                 :            :  * @brief measure the number of glyphs in an UTF8 string...
    3211                 :            :  * @param Buf string to measure
    3212                 :            :  * @returns the number of glyphs in Buf
    3213                 :            :  */
    3214                 :          0 : long StrBuf_Utf8StrLen(StrBuf *Buf)
    3215                 :            : {
    3216                 :          0 :         int n = 0;
    3217                 :          0 :         int m = 0;
    3218                 :            :         char *aptr, *eptr;
    3219                 :            : 
    3220 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (Buf->BufUsed == 0))
    3221                 :          0 :                 return 0;
    3222                 :          0 :         aptr = Buf->buf;
    3223                 :          0 :         eptr = Buf->buf + Buf->BufUsed;
    3224 [ #  # ][ #  # ]:          0 :         while ((aptr < eptr) && (*aptr != '\0')) {
    3225         [ #  # ]:          0 :                 if (Ctdl_IsUtf8SequenceStart(*aptr)){
    3226                 :          0 :                         m = Ctdl_GetUtf8SequenceLength(aptr, eptr);
    3227 [ #  # ][ #  # ]:          0 :                         while ((aptr < eptr) && (*aptr++ != '\0')&& (m-- > 0) );
                 [ #  # ]
    3228                 :          0 :                         n ++;
    3229                 :            :                 }
    3230                 :            :                 else {
    3231                 :          0 :                         n++;
    3232                 :          0 :                         aptr++;
    3233                 :            :                 }
    3234                 :            :         }
    3235                 :          0 :         return n;
    3236                 :            : }
    3237                 :            : 
    3238                 :            : /**
    3239                 :            :  * @ingroup StrBuf
    3240                 :            :  * @brief cuts a string after maxlen glyphs
    3241                 :            :  * @param Buf string to cut to maxlen glyphs
    3242                 :            :  * @param maxlen how long may the string become?
    3243                 :            :  * @returns current length of the string
    3244                 :            :  */
    3245                 :          0 : long StrBuf_Utf8StrCut(StrBuf *Buf, int maxlen)
    3246                 :            : {
    3247                 :            :         char *aptr, *eptr;
    3248                 :          0 :         int n = 0, m = 0;
    3249                 :            : 
    3250                 :          0 :         aptr = Buf->buf;
    3251                 :          0 :         eptr = Buf->buf + Buf->BufUsed;
    3252 [ #  # ][ #  # ]:          0 :         while ((aptr < eptr) && (*aptr != '\0')) {
    3253         [ #  # ]:          0 :                 if (Ctdl_IsUtf8SequenceStart(*aptr)){
    3254                 :          0 :                         m = Ctdl_GetUtf8SequenceLength(aptr, eptr);
    3255 [ #  # ][ #  # ]:          0 :                         while ((*aptr++ != '\0') && (m-- > 0));
    3256                 :          0 :                         n ++;
    3257                 :            :                 }
    3258                 :            :                 else {
    3259                 :          0 :                         n++;
    3260                 :          0 :                         aptr++;
    3261                 :            :                 }
    3262         [ #  # ]:          0 :                 if (n > maxlen) {
    3263                 :          0 :                         *aptr = '\0';
    3264                 :          0 :                         Buf->BufUsed = aptr - Buf->buf;
    3265                 :          0 :                         return Buf->BufUsed;
    3266                 :            :                 }                       
    3267                 :            :         }
    3268                 :          0 :         return Buf->BufUsed;
    3269                 :            : 
    3270                 :            : }
    3271                 :            : 
    3272                 :            : 
    3273                 :            : 
    3274                 :            : 
    3275                 :            : 
    3276                 :            : /*******************************************************************************
    3277                 :            :  *                               wrapping ZLib                                 *
    3278                 :            :  *******************************************************************************/
    3279                 :            : 
    3280                 :            : #ifdef HAVE_ZLIB
    3281                 :            : #define DEF_MEM_LEVEL 8 /*< memlevel??? */
    3282                 :            : #define OS_CODE 0x03    /*< unix */
    3283                 :            : 
    3284                 :            : /**
    3285                 :            :  * @ingroup StrBuf_DeEnCoder
    3286                 :            :  * @brief uses the same calling syntax as compress2(), but it
    3287                 :            :  *   creates a stream compatible with HTTP "Content-encoding: gzip"
    3288                 :            :  * @param dest compressed buffer
    3289                 :            :  * @param destLen length of the compresed data 
    3290                 :            :  * @param source source to encode
    3291                 :            :  * @param sourceLen length of source to encode 
    3292                 :            :  * @param level compression level
    3293                 :            :  */
    3294                 :          0 : int ZEXPORT compress_gzip(Bytef * dest,
    3295                 :            :                           size_t * destLen,
    3296                 :            :                           const Bytef * source,
    3297                 :            :                           uLong sourceLen,     
    3298                 :            :                           int level)
    3299                 :            : {
    3300                 :            :         const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */
    3301                 :            : 
    3302                 :            :         /* write gzip header */
    3303                 :          0 :         snprintf((char *) dest, *destLen, 
    3304                 :            :                  "%c%c%c%c%c%c%c%c%c%c",
    3305                 :            :                  gz_magic[0], gz_magic[1], Z_DEFLATED,
    3306                 :            :                  0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /* xflags */ ,
    3307                 :            :                  OS_CODE);
    3308                 :            : 
    3309                 :            :         /* normal deflate */
    3310                 :            :         z_stream stream;
    3311                 :            :         int err;
    3312                 :          0 :         stream.next_in = (Bytef *) source;
    3313                 :          0 :         stream.avail_in = (uInt) sourceLen;
    3314                 :          0 :         stream.next_out = dest + 10L;   // after header
    3315                 :          0 :         stream.avail_out = (uInt) * destLen;
    3316         [ #  # ]:          0 :         if ((uLong) stream.avail_out != *destLen)
    3317                 :          0 :                 return Z_BUF_ERROR;
    3318                 :            : 
    3319                 :          0 :         stream.zalloc = (alloc_func) 0;
    3320                 :          0 :         stream.zfree = (free_func) 0;
    3321                 :          0 :         stream.opaque = (voidpf) 0;
    3322                 :            : 
    3323                 :          0 :         err = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS,
    3324                 :            :                            DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
    3325         [ #  # ]:          0 :         if (err != Z_OK)
    3326                 :          0 :                 return err;
    3327                 :            : 
    3328                 :          0 :         err = deflate(&stream, Z_FINISH);
    3329         [ #  # ]:          0 :         if (err != Z_STREAM_END) {
    3330                 :          0 :                 deflateEnd(&stream);
    3331         [ #  # ]:          0 :                 return err == Z_OK ? Z_BUF_ERROR : err;
    3332                 :            :         }
    3333                 :          0 :         *destLen = stream.total_out + 10L;
    3334                 :            : 
    3335                 :            :         /* write CRC and Length */
    3336                 :          0 :         uLong crc = crc32(0L, source, sourceLen);
    3337                 :            :         int n;
    3338         [ #  # ]:          0 :         for (n = 0; n < 4; ++n, ++*destLen) {
    3339                 :          0 :                 dest[*destLen] = (int) (crc & 0xff);
    3340                 :          0 :                 crc >>= 8;
    3341                 :            :         }
    3342                 :          0 :         uLong len = stream.total_in;
    3343         [ #  # ]:          0 :         for (n = 0; n < 4; ++n, ++*destLen) {
    3344                 :          0 :                 dest[*destLen] = (int) (len & 0xff);
    3345                 :          0 :                 len >>= 8;
    3346                 :            :         }
    3347                 :          0 :         err = deflateEnd(&stream);
    3348                 :          0 :         return err;
    3349                 :            : }
    3350                 :            : #endif
    3351                 :            : 
    3352                 :            : 
    3353                 :            : /**
    3354                 :            :  * @ingroup StrBuf_DeEnCoder
    3355                 :            :  * @brief compress the buffer with gzip
    3356                 :            :  * Attention! If you feed this a Const String, you must maintain the uncompressed buffer yourself!
    3357                 :            :  * @param Buf buffer whose content is to be gzipped
    3358                 :            :  */
    3359                 :          0 : int CompressBuffer(StrBuf *Buf)
    3360                 :            : {
    3361                 :            : #ifdef HAVE_ZLIB
    3362                 :          0 :         char *compressed_data = NULL;
    3363                 :            :         size_t compressed_len, bufsize;
    3364                 :          0 :         int i = 0;
    3365                 :            : 
    3366                 :          0 :         bufsize = compressed_len = Buf->BufUsed +  (Buf->BufUsed / 100) + 100;
    3367                 :          0 :         compressed_data = malloc(compressed_len);
    3368                 :            :         
    3369         [ #  # ]:          0 :         if (compressed_data == NULL)
    3370                 :          0 :                 return -1;
    3371                 :            :         /* Flush some space after the used payload so valgrind shuts up... */
    3372 [ #  # ][ #  # ]:          0 :         while ((i < 10) && (Buf->BufUsed + i < Buf->BufSize))
    3373                 :          0 :                 Buf->buf[Buf->BufUsed + i++] = '\0';
    3374         [ #  # ]:          0 :         if (compress_gzip((Bytef *) compressed_data,
    3375                 :            :                           &compressed_len,
    3376                 :            :                           (Bytef *) Buf->buf,
    3377                 :            :                           (uLongf) Buf->BufUsed, Z_BEST_SPEED) == Z_OK) {
    3378         [ #  # ]:          0 :                 if (!Buf->ConstBuf)
    3379                 :          0 :                         free(Buf->buf);
    3380                 :          0 :                 Buf->buf = compressed_data;
    3381                 :          0 :                 Buf->BufUsed = compressed_len;
    3382                 :          0 :                 Buf->BufSize = bufsize;
    3383                 :            :                 /* Flush some space after the used payload so valgrind shuts up... */
    3384                 :          0 :                 i = 0;
    3385 [ #  # ][ #  # ]:          0 :                 while ((i < 10) && (Buf->BufUsed + i < Buf->BufSize))
    3386                 :          0 :                         Buf->buf[Buf->BufUsed + i++] = '\0';
    3387                 :          0 :                 return 1;
    3388                 :            :         } else {
    3389                 :          0 :                 free(compressed_data);
    3390                 :            :         }
    3391                 :            : #endif  /* HAVE_ZLIB */
    3392                 :          0 :         return 0;
    3393                 :            : }
    3394                 :            : 
    3395                 :            : 
    3396                 :            : 
    3397                 :            : /*******************************************************************************
    3398                 :            :  *           File I/O; Prefer buffered read since its faster!                  *
    3399                 :            :  *******************************************************************************/
    3400                 :            : 
    3401                 :            : /**
    3402                 :            :  * @ingroup StrBuf_IO
    3403                 :            :  * @brief Read a line from socket
    3404                 :            :  * flushes and closes the FD on error
    3405                 :            :  * @param buf the buffer to get the input to
    3406                 :            :  * @param fd pointer to the filedescriptor to read
    3407                 :            :  * @param append Append to an existing string or replace?
    3408                 :            :  * @param Error strerror() on error 
    3409                 :            :  * @returns numbers of chars read
    3410                 :            :  */
    3411                 :         26 : int StrBufTCP_read_line(StrBuf *buf, int *fd, int append, const char **Error)
    3412                 :            : {
    3413                 :            :         int len, rlen, slen;
    3414                 :            : 
    3415         [ +  - ]:         26 :         if (!append)
    3416                 :         26 :                 FlushStrBuf(buf);
    3417                 :            : 
    3418                 :         26 :         slen = len = buf->BufUsed;
    3419                 :            :         while (1) {
    3420                 :        691 :                 rlen = read(*fd, &buf->buf[len], 1);
    3421         [ +  + ]:        691 :                 if (rlen < 1) {
    3422                 :          1 :                         *Error = strerror(errno);
    3423                 :            :                         
    3424                 :          1 :                         close(*fd);
    3425                 :          1 :                         *fd = -1;
    3426                 :            :                         
    3427                 :          1 :                         return -1;
    3428                 :            :                 }
    3429         [ +  + ]:        690 :                 if (buf->buf[len] == '\n')
    3430                 :            :                         break;
    3431         [ +  - ]:        665 :                 if (buf->buf[len] != '\r')
    3432                 :        665 :                         len ++;
    3433         [ +  + ]:        665 :                 if (len + 2 >= buf->BufSize) {
    3434                 :          9 :                         buf->BufUsed = len;
    3435                 :          9 :                         buf->buf[len+1] = '\0';
    3436                 :          9 :                         IncreaseBuf(buf, 1, -1);
    3437                 :            :                 }
    3438                 :        691 :         }
    3439                 :         25 :         buf->BufUsed = len;
    3440                 :         25 :         buf->buf[len] = '\0';
    3441                 :         25 :         return len - slen;
    3442                 :            : }
    3443                 :            : 
    3444                 :            : /**
    3445                 :            :  * @ingroup StrBuf_BufferedIO
    3446                 :            :  * @brief Read a line from socket
    3447                 :            :  * flushes and closes the FD on error
    3448                 :            :  * @param Line the line to read from the fd / I/O Buffer
    3449                 :            :  * @param buf the buffer to get the input to
    3450                 :            :  * @param fd pointer to the filedescriptor to read
    3451                 :            :  * @param timeout number of successless selects until we bail out
    3452                 :            :  * @param selectresolution how long to wait on each select
    3453                 :            :  * @param Error strerror() on error 
    3454                 :            :  * @returns numbers of chars read
    3455                 :            :  */
    3456                 :          0 : int StrBufTCP_read_buffered_line(StrBuf *Line, 
    3457                 :            :                                  StrBuf *buf, 
    3458                 :            :                                  int *fd, 
    3459                 :            :                                  int timeout, 
    3460                 :            :                                  int selectresolution, 
    3461                 :            :                                  const char **Error)
    3462                 :            : {
    3463                 :            :         int len, rlen;
    3464                 :          0 :         int nSuccessLess = 0;
    3465                 :            :         fd_set rfds;
    3466                 :          0 :         char *pch = NULL;
    3467                 :            :         int fdflags;
    3468                 :            :         int IsNonBlock;
    3469                 :            :         struct timeval tv;
    3470                 :            : 
    3471         [ #  # ]:          0 :         if (buf->BufUsed > 0) {
    3472                 :          0 :                 pch = strchr(buf->buf, '\n');
    3473         [ #  # ]:          0 :                 if (pch != NULL) {
    3474                 :          0 :                         rlen = 0;
    3475                 :          0 :                         len = pch - buf->buf;
    3476 [ #  # ][ #  # ]:          0 :                         if (len > 0 && (*(pch - 1) == '\r') )
    3477                 :          0 :                                 rlen ++;
    3478                 :          0 :                         StrBufSub(Line, buf, 0, len - rlen);
    3479                 :          0 :                         StrBufCutLeft(buf, len + 1);
    3480                 :          0 :                         return len - rlen;
    3481                 :            :                 }
    3482                 :            :         }
    3483                 :            :         
    3484         [ #  # ]:          0 :         if (buf->BufSize - buf->BufUsed < 10)
    3485                 :          0 :                 IncreaseBuf(buf, 1, -1);
    3486                 :            : 
    3487                 :          0 :         fdflags = fcntl(*fd, F_GETFL);
    3488                 :          0 :         IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK;
    3489                 :            : 
    3490 [ #  # ][ #  # ]:          0 :         while ((nSuccessLess < timeout) && (pch == NULL)) {
    3491         [ #  # ]:          0 :                 if (IsNonBlock){
    3492                 :          0 :                         tv.tv_sec = selectresolution;
    3493                 :          0 :                         tv.tv_usec = 0;
    3494                 :            :                         
    3495                 :          0 :                         FD_ZERO(&rfds);
    3496                 :          0 :                         FD_SET(*fd, &rfds);
    3497         [ #  # ]:          0 :                         if (select(*fd + 1, NULL, &rfds, NULL, &tv) == -1) {
    3498                 :          0 :                                 *Error = strerror(errno);
    3499                 :          0 :                                 close (*fd);
    3500                 :          0 :                                 *fd = -1;
    3501                 :          0 :                                 return -1;
    3502                 :            :                         }
    3503                 :            :                 }
    3504 [ #  # ][ #  # ]:          0 :                 if (IsNonBlock && !  FD_ISSET(*fd, &rfds)) {
    3505                 :          0 :                         nSuccessLess ++;
    3506                 :          0 :                         continue;
    3507                 :            :                 }
    3508                 :          0 :                 rlen = read(*fd, 
    3509                 :          0 :                             &buf->buf[buf->BufUsed], 
    3510                 :          0 :                             buf->BufSize - buf->BufUsed - 1);
    3511         [ #  # ]:          0 :                 if (rlen < 1) {
    3512                 :          0 :                         *Error = strerror(errno);
    3513                 :          0 :                         close(*fd);
    3514                 :          0 :                         *fd = -1;
    3515                 :          0 :                         return -1;
    3516                 :            :                 }
    3517         [ #  # ]:          0 :                 else if (rlen > 0) {
    3518                 :          0 :                         nSuccessLess = 0;
    3519                 :          0 :                         buf->BufUsed += rlen;
    3520                 :          0 :                         buf->buf[buf->BufUsed] = '\0';
    3521         [ #  # ]:          0 :                         if (buf->BufUsed + 10 > buf->BufSize) {
    3522                 :          0 :                                 IncreaseBuf(buf, 1, -1);
    3523                 :            :                         }
    3524                 :          0 :                         pch = strchr(buf->buf, '\n');
    3525                 :          0 :                         continue;
    3526                 :            :                 }
    3527                 :            :                 
    3528                 :            :         }
    3529         [ #  # ]:          0 :         if (pch != NULL) {
    3530                 :          0 :                 rlen = 0;
    3531                 :          0 :                 len = pch - buf->buf;
    3532 [ #  # ][ #  # ]:          0 :                 if (len > 0 && (*(pch - 1) == '\r') )
    3533                 :          0 :                         rlen ++;
    3534                 :          0 :                 StrBufSub(Line, buf, 0, len - rlen);
    3535                 :          0 :                 StrBufCutLeft(buf, len + 1);
    3536                 :          0 :                 return len - rlen;
    3537                 :            :         }
    3538                 :          0 :         return -1;
    3539                 :            : 
    3540                 :            : }
    3541                 :            : 
    3542                 :            : static const char *ErrRBLF_PreConditionFailed="StrBufTCP_read_buffered_line_fast: Wrong arguments or invalid Filedescriptor";
    3543                 :            : static const char *ErrRBLF_SelectFailed="StrBufTCP_read_buffered_line_fast: Select failed without reason";
    3544                 :            : static const char *ErrRBLF_NotEnoughSentFromServer="StrBufTCP_read_buffered_line_fast: No complete line was sent from peer";
    3545                 :            : /**
    3546                 :            :  * @ingroup StrBuf_BufferedIO
    3547                 :            :  * @brief Read a line from socket
    3548                 :            :  * flushes and closes the FD on error
    3549                 :            :  * @param Line where to append our Line read from the fd / I/O Buffer; 
    3550                 :            :  * @param IOBuf the buffer to get the input to; lifetime pair to FD
    3551                 :            :  * @param Pos pointer to the current read position, should be NULL initialized on opening the FD it belongs to.!
    3552                 :            :  * @param fd pointer to the filedescriptor to read
    3553                 :            :  * @param timeout number of successless selects until we bail out
    3554                 :            :  * @param selectresolution how long to wait on each select
    3555                 :            :  * @param Error strerror() on error 
    3556                 :            :  * @returns numbers of chars read or -1 in case of error. "\n" will become 0
    3557                 :            :  */
    3558                 :          0 : int StrBufTCP_read_buffered_line_fast(StrBuf *Line, 
    3559                 :            :                                       StrBuf *IOBuf, 
    3560                 :            :                                       const char **Pos,
    3561                 :            :                                       int *fd, 
    3562                 :            :                                       int timeout, 
    3563                 :            :                                       int selectresolution, 
    3564                 :            :                                       const char **Error)
    3565                 :            : {
    3566                 :          0 :         const char *pche = NULL;
    3567                 :          0 :         const char *pos = NULL;
    3568                 :            :         const char *pLF;
    3569                 :            :         int len, rlen, retlen;
    3570                 :          0 :         int nSuccessLess = 0;
    3571                 :            :         fd_set rfds;
    3572                 :          0 :         const char *pch = NULL;
    3573                 :            :         int fdflags;
    3574                 :            :         int IsNonBlock;
    3575                 :            :         struct timeval tv;
    3576                 :            :         
    3577                 :          0 :         retlen = 0;
    3578 [ #  # ][ #  # ]:          0 :         if ((Line == NULL) ||
         [ #  # ][ #  # ]
    3579                 :            :             (Pos == NULL) ||
    3580                 :            :             (IOBuf == NULL) ||
    3581                 :          0 :             (*fd == -1))
    3582                 :            :         {
    3583         [ #  # ]:          0 :                 if (Pos != NULL)
    3584                 :          0 :                         *Pos = NULL;
    3585                 :          0 :                 *Error = ErrRBLF_PreConditionFailed;
    3586                 :          0 :                 return -1;
    3587                 :            :         }
    3588                 :            : 
    3589                 :          0 :         pos = *Pos;
    3590 [ #  # ][ #  # ]:          0 :         if ((IOBuf->BufUsed > 0) && 
                 [ #  # ]
    3591                 :            :             (pos != NULL) && 
    3592                 :          0 :             (pos < IOBuf->buf + IOBuf->BufUsed)) 
    3593                 :            :         {
    3594                 :            :                 char *pcht;
    3595                 :            : 
    3596                 :          0 :                 pche = IOBuf->buf + IOBuf->BufUsed;
    3597                 :          0 :                 pch = pos;
    3598                 :          0 :                 pcht = Line->buf;
    3599                 :            : 
    3600 [ #  # ][ #  # ]:          0 :                 while ((pch < pche) && (*pch != '\n'))
    3601                 :            :                 {
    3602         [ #  # ]:          0 :                         if (Line->BufUsed + 10 > Line->BufSize)
    3603                 :            :                         {
    3604                 :            :                                 long apos;
    3605                 :          0 :                                 apos = pcht - Line->buf;
    3606                 :          0 :                                 *pcht = '\0';
    3607                 :          0 :                                 IncreaseBuf(Line, 1, -1);
    3608                 :          0 :                                 pcht = Line->buf + apos;
    3609                 :            :                         }
    3610                 :          0 :                         *pcht++ = *pch++;
    3611                 :          0 :                         Line->BufUsed++;
    3612                 :          0 :                         retlen++;
    3613                 :            :                 }
    3614                 :            : 
    3615                 :          0 :                 len = pch - pos;
    3616 [ #  # ][ #  # ]:          0 :                 if (len > 0 && (*(pch - 1) == '\r') )
    3617                 :            :                 {
    3618                 :          0 :                         retlen--;
    3619                 :          0 :                         len --;
    3620                 :          0 :                         pcht --;
    3621                 :          0 :                         Line->BufUsed --;
    3622                 :            :                 }
    3623                 :          0 :                 *pcht = '\0';
    3624                 :            : 
    3625 [ #  # ][ #  # ]:          0 :                 if ((pch >= pche) || (*pch == '\0'))
    3626                 :            :                 {
    3627                 :          0 :                         FlushStrBuf(IOBuf);
    3628                 :          0 :                         *Pos = NULL;
    3629                 :          0 :                         pch = NULL;
    3630                 :          0 :                         pos = 0;
    3631                 :            :                 }
    3632                 :            : 
    3633 [ #  # ][ #  # ]:          0 :                 if ((pch != NULL) && 
    3634                 :            :                     (pch <= pche)) 
    3635                 :            :                 {
    3636         [ #  # ]:          0 :                         if (pch + 1 >= pche) {
    3637                 :          0 :                                 *Pos = NULL;
    3638                 :          0 :                                 FlushStrBuf(IOBuf);
    3639                 :            :                         }
    3640                 :            :                         else
    3641                 :          0 :                                 *Pos = pch + 1;
    3642                 :            :                         
    3643                 :          0 :                         return retlen;
    3644                 :            :                 }
    3645                 :            :                 else 
    3646                 :          0 :                         FlushStrBuf(IOBuf);
    3647                 :            :         }
    3648                 :            : 
    3649                 :            :         /* If we come here, Pos is Unset since we read everything into Line, and now go for more. */
    3650                 :            :         
    3651         [ #  # ]:          0 :         if (IOBuf->BufSize - IOBuf->BufUsed < 10)
    3652                 :          0 :                 IncreaseBuf(IOBuf, 1, -1);
    3653                 :            : 
    3654                 :          0 :         fdflags = fcntl(*fd, F_GETFL);
    3655                 :          0 :         IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK;
    3656                 :            : 
    3657                 :          0 :         pLF = NULL;
    3658 [ #  # ][ #  # ]:          0 :         while ((nSuccessLess < timeout) && 
                 [ #  # ]
    3659                 :            :                (pLF == NULL) &&
    3660                 :          0 :                (*fd != -1)) {
    3661         [ #  # ]:          0 :                 if (IsNonBlock)
    3662                 :            :                 {
    3663                 :          0 :                         tv.tv_sec = 1;
    3664                 :          0 :                         tv.tv_usec = 0;
    3665                 :            :                 
    3666                 :          0 :                         FD_ZERO(&rfds);
    3667                 :          0 :                         FD_SET(*fd, &rfds);
    3668         [ #  # ]:          0 :                         if (select((*fd) + 1, &rfds, NULL, NULL, &tv) == -1) {
    3669                 :          0 :                                 *Error = strerror(errno);
    3670                 :          0 :                                 close (*fd);
    3671                 :          0 :                                 *fd = -1;
    3672         [ #  # ]:          0 :                                 if (*Error == NULL)
    3673                 :          0 :                                         *Error = ErrRBLF_SelectFailed;
    3674                 :          0 :                                 return -1;
    3675                 :            :                         }
    3676         [ #  # ]:          0 :                         if (! FD_ISSET(*fd, &rfds) != 0) {
    3677                 :          0 :                                 nSuccessLess ++;
    3678                 :          0 :                                 continue;
    3679                 :            :                         }
    3680                 :            :                 }
    3681                 :          0 :                 rlen = read(*fd, 
    3682                 :          0 :                             &IOBuf->buf[IOBuf->BufUsed], 
    3683                 :          0 :                             IOBuf->BufSize - IOBuf->BufUsed - 1);
    3684         [ #  # ]:          0 :                 if (rlen < 1) {
    3685                 :          0 :                         *Error = strerror(errno);
    3686                 :          0 :                         close(*fd);
    3687                 :          0 :                         *fd = -1;
    3688                 :          0 :                         return -1;
    3689                 :            :                 }
    3690         [ #  # ]:          0 :                 else if (rlen > 0) {
    3691                 :          0 :                         nSuccessLess = 0;
    3692                 :          0 :                         pLF = IOBuf->buf + IOBuf->BufUsed;
    3693                 :          0 :                         IOBuf->BufUsed += rlen;
    3694                 :          0 :                         IOBuf->buf[IOBuf->BufUsed] = '\0';
    3695                 :            :                         
    3696                 :          0 :                         pche = IOBuf->buf + IOBuf->BufUsed;
    3697                 :            :                         
    3698 [ #  # ][ #  # ]:          0 :                         while ((pLF < pche) && (*pLF != '\n'))
    3699                 :          0 :                                 pLF ++;
    3700 [ #  # ][ #  # ]:          0 :                         if ((pLF >= pche) || (*pLF == '\0'))
    3701                 :          0 :                                 pLF = NULL;
    3702                 :            : 
    3703         [ #  # ]:          0 :                         if (IOBuf->BufUsed + 10 > IOBuf->BufSize)
    3704                 :            :                         {
    3705                 :          0 :                                 long apos = 0;
    3706                 :            : 
    3707         [ #  # ]:          0 :                                 if (pLF != NULL) apos = pLF - IOBuf->buf;
    3708                 :          0 :                                 IncreaseBuf(IOBuf, 1, -1);      
    3709         [ #  # ]:          0 :                                 if (pLF != NULL) pLF = IOBuf->buf + apos;
    3710                 :            :                         }
    3711                 :            : 
    3712                 :          0 :                         continue;
    3713                 :            :                 }
    3714                 :            :         }
    3715                 :          0 :         *Pos = NULL;
    3716         [ #  # ]:          0 :         if (pLF != NULL) {
    3717                 :          0 :                 pos = IOBuf->buf;
    3718                 :          0 :                 len = pLF - pos;
    3719 [ #  # ][ #  # ]:          0 :                 if (len > 0 && (*(pLF - 1) == '\r') )
    3720                 :          0 :                         len --;
    3721                 :          0 :                 StrBufAppendBufPlain(Line, ChrPtr(IOBuf), len, 0);
    3722         [ #  # ]:          0 :                 if (pLF + 1 >= IOBuf->buf + IOBuf->BufUsed)
    3723                 :            :                 {
    3724                 :          0 :                         FlushStrBuf(IOBuf);
    3725                 :            :                 }
    3726                 :            :                 else 
    3727                 :          0 :                         *Pos = pLF + 1;
    3728                 :          0 :                 return retlen + len;
    3729                 :            :         }
    3730                 :          0 :         *Error = ErrRBLF_NotEnoughSentFromServer;
    3731                 :          0 :         return -1;
    3732                 :            : 
    3733                 :            : }
    3734                 :            : 
    3735                 :            : static const char *ErrRBLF_BLOBPreConditionFailed="StrBufReadBLOB: Wrong arguments or invalid Filedescriptor";
    3736                 :            : /**
    3737                 :            :  * @ingroup StrBuf_IO
    3738                 :            :  * @brief Input binary data from socket
    3739                 :            :  * flushes and closes the FD on error
    3740                 :            :  * @param Buf the buffer to get the input to
    3741                 :            :  * @param fd pointer to the filedescriptor to read
    3742                 :            :  * @param append Append to an existing string or replace?
    3743                 :            :  * @param nBytes the maximal number of bytes to read
    3744                 :            :  * @param Error strerror() on error 
    3745                 :            :  * @returns numbers of chars read
    3746                 :            :  */
    3747                 :        194 : int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **Error)
    3748                 :            : {
    3749                 :            :         int fdflags;
    3750                 :            :         int len, rlen, slen;
    3751                 :            :         int nSuccessLess;
    3752                 :        194 :         int nRead = 0;
    3753                 :            :         char *ptr;
    3754                 :            :         int IsNonBlock;
    3755                 :            :         struct timeval tv;
    3756                 :            :         fd_set rfds;
    3757                 :            : 
    3758 [ +  - ][ -  + ]:        194 :         if ((Buf == NULL) || (*fd == -1))
    3759                 :            :         {
    3760                 :          0 :                 *Error = ErrRBLF_BLOBPreConditionFailed;
    3761                 :          0 :                 return -1;
    3762                 :            :         }
    3763         [ -  + ]:        194 :         if (!append)
    3764                 :          0 :                 FlushStrBuf(Buf);
    3765         [ -  + ]:        194 :         if (Buf->BufUsed + nBytes >= Buf->BufSize)
    3766                 :          0 :                 IncreaseBuf(Buf, 1, Buf->BufUsed + nBytes);
    3767                 :            : 
    3768                 :        194 :         ptr = Buf->buf + Buf->BufUsed;
    3769                 :            : 
    3770                 :        194 :         slen = len = Buf->BufUsed;
    3771                 :            : 
    3772                 :        194 :         fdflags = fcntl(*fd, F_GETFL);
    3773                 :        194 :         IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK;
    3774                 :        194 :         nSuccessLess = 0;
    3775 [ +  + ][ +  - ]:        388 :         while ((nRead < nBytes) && 
    3776                 :        194 :                (*fd != -1)) 
    3777                 :            :         {
    3778         [ -  + ]:        194 :                 if (IsNonBlock)
    3779                 :            :                 {
    3780                 :          0 :                         tv.tv_sec = 1;
    3781                 :          0 :                         tv.tv_usec = 0;
    3782                 :            :                 
    3783                 :          0 :                         FD_ZERO(&rfds);
    3784                 :          0 :                         FD_SET(*fd, &rfds);
    3785         [ #  # ]:          0 :                         if (select(*fd + 1, &rfds, NULL, NULL, &tv) == -1) {
    3786                 :          0 :                                 *Error = strerror(errno);
    3787                 :          0 :                                 close (*fd);
    3788                 :          0 :                                 *fd = -1;
    3789         [ #  # ]:          0 :                                 if (*Error == NULL)
    3790                 :          0 :                                         *Error = ErrRBLF_SelectFailed;
    3791                 :          0 :                                 return -1;
    3792                 :            :                         }
    3793         [ #  # ]:          0 :                         if (! FD_ISSET(*fd, &rfds) != 0) {
    3794                 :          0 :                                 nSuccessLess ++;
    3795                 :          0 :                                 continue;
    3796                 :            :                         }
    3797                 :            :                 }
    3798                 :            : 
    3799         [ -  + ]:        194 :                 if ((rlen = read(*fd, 
    3800                 :            :                                  ptr,
    3801                 :        194 :                                  nBytes - nRead)) == -1) {
    3802                 :          0 :                         close(*fd);
    3803                 :          0 :                         *fd = -1;
    3804                 :          0 :                         *Error = strerror(errno);
    3805                 :          0 :                         return rlen;
    3806                 :            :                 }
    3807                 :        194 :                 nRead += rlen;
    3808                 :        194 :                 ptr += rlen;
    3809                 :        194 :                 Buf->BufUsed += rlen;
    3810                 :            :         }
    3811                 :        194 :         Buf->buf[Buf->BufUsed] = '\0';
    3812                 :        194 :         return nRead;
    3813                 :            : }
    3814                 :            : 
    3815                 :            : const char *ErrRBB_BLOBFPreConditionFailed = "StrBufReadBLOBBuffered: to many selects; aborting.";
    3816                 :            : const char *ErrRBB_too_many_selects        = "StrBufReadBLOBBuffered: to many selects; aborting.";
    3817                 :            : /**
    3818                 :            :  * @ingroup StrBuf_BufferedIO
    3819                 :            :  * @brief Input binary data from socket
    3820                 :            :  * flushes and closes the FD on error
    3821                 :            :  * @param Blob put binary thing here
    3822                 :            :  * @param IOBuf the buffer to get the input to
    3823                 :            :  * @param Pos offset inside of IOBuf
    3824                 :            :  * @param fd pointer to the filedescriptor to read
    3825                 :            :  * @param append Append to an existing string or replace?
    3826                 :            :  * @param nBytes the maximal number of bytes to read
    3827                 :            :  * @param check whether we should search for '000\n' terminators in case of timeouts
    3828                 :            :  * @param Error strerror() on error 
    3829                 :            :  * @returns numbers of chars read
    3830                 :            :  */
    3831                 :          0 : int StrBufReadBLOBBuffered(StrBuf *Blob, 
    3832                 :            :                            StrBuf *IOBuf, 
    3833                 :            :                            const char **Pos,
    3834                 :            :                            int *fd, 
    3835                 :            :                            int append, 
    3836                 :            :                            long nBytes, 
    3837                 :            :                            int check, 
    3838                 :            :                            const char **Error)
    3839                 :            : {
    3840                 :            :         const char *pche;
    3841                 :            :         const char *pos;
    3842                 :            :         int fdflags;
    3843                 :          0 :         int len = 0;
    3844                 :            :         int rlen, slen;
    3845                 :          0 :         int nRead = 0;
    3846                 :          0 :         int nAlreadyRead = 0;
    3847                 :            :         int IsNonBlock;
    3848                 :            :         char *ptr;
    3849                 :            :         fd_set rfds;
    3850                 :            :         const char *pch;
    3851                 :            :         struct timeval tv;
    3852                 :          0 :         int nSuccessLess = 0;
    3853                 :            :         int MaxTries;
    3854                 :            : 
    3855 [ #  # ][ #  # ]:          0 :         if ((Blob == NULL) || (*fd == -1) || (IOBuf == NULL) || (Pos == NULL))
         [ #  # ][ #  # ]
    3856                 :            :         {
    3857         [ #  # ]:          0 :                 if (*Pos != NULL)
    3858                 :          0 :                         *Pos = NULL;
    3859                 :          0 :                 *Error = ErrRBB_BLOBFPreConditionFailed;
    3860                 :          0 :                 return -1;
    3861                 :            :         }
    3862                 :            : 
    3863         [ #  # ]:          0 :         if (!append)
    3864                 :          0 :                 FlushStrBuf(Blob);
    3865         [ #  # ]:          0 :         if (Blob->BufUsed + nBytes >= Blob->BufSize) 
    3866                 :          0 :                 IncreaseBuf(Blob, append, Blob->BufUsed + nBytes);
    3867                 :            :         
    3868                 :          0 :         pos = *Pos;
    3869                 :            : 
    3870         [ #  # ]:          0 :         if (pos != NULL)
    3871                 :          0 :                 len = pos - IOBuf->buf;
    3872                 :          0 :         rlen = IOBuf->BufUsed - len;
    3873                 :            : 
    3874                 :            : 
    3875 [ #  # ][ #  # ]:          0 :         if ((IOBuf->BufUsed > 0) && 
                 [ #  # ]
    3876                 :            :             (pos != NULL) && 
    3877                 :          0 :             (pos < IOBuf->buf + IOBuf->BufUsed)) 
    3878                 :            :         {
    3879                 :          0 :                 pche = IOBuf->buf + IOBuf->BufUsed;
    3880                 :          0 :                 pch = pos;
    3881                 :            : 
    3882         [ #  # ]:          0 :                 if (rlen < nBytes) {
    3883                 :          0 :                         memcpy(Blob->buf + Blob->BufUsed, pos, rlen);
    3884                 :          0 :                         Blob->BufUsed += rlen;
    3885                 :          0 :                         Blob->buf[Blob->BufUsed] = '\0';
    3886                 :          0 :                         nAlreadyRead = nRead = rlen;
    3887                 :          0 :                         *Pos = NULL; 
    3888                 :            :                 }
    3889         [ #  # ]:          0 :                 if (rlen >= nBytes) {
    3890                 :          0 :                         memcpy(Blob->buf + Blob->BufUsed, pos, nBytes);
    3891                 :          0 :                         Blob->BufUsed += nBytes;
    3892                 :          0 :                         Blob->buf[Blob->BufUsed] = '\0';
    3893         [ #  # ]:          0 :                         if (rlen == nBytes) {
    3894                 :          0 :                                 *Pos = NULL; 
    3895                 :          0 :                                 FlushStrBuf(IOBuf);
    3896                 :            :                         }
    3897                 :            :                         else 
    3898                 :          0 :                                 *Pos += nBytes;
    3899                 :          0 :                         return nBytes;
    3900                 :            :                 }
    3901                 :            :         }
    3902                 :            : 
    3903                 :          0 :         FlushStrBuf(IOBuf);
    3904                 :          0 :         *Pos = NULL;
    3905         [ #  # ]:          0 :         if (IOBuf->BufSize < nBytes - nRead)
    3906                 :          0 :                 IncreaseBuf(IOBuf, 0, nBytes - nRead);
    3907                 :          0 :         ptr = IOBuf->buf;
    3908                 :            : 
    3909                 :          0 :         slen = len = Blob->BufUsed;
    3910                 :            : 
    3911                 :          0 :         fdflags = fcntl(*fd, F_GETFL);
    3912                 :          0 :         IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK;
    3913         [ #  # ]:          0 :         if (IsNonBlock)
    3914                 :          0 :                 MaxTries =   1000;
    3915                 :            :         else
    3916                 :          0 :                 MaxTries = 100000;
    3917                 :            : 
    3918                 :          0 :         nBytes -= nRead;
    3919                 :          0 :         nRead = 0;
    3920 [ #  # ][ #  # ]:          0 :         while ((nSuccessLess < MaxTries) && 
                 [ #  # ]
    3921                 :            :                (nRead < nBytes) &&
    3922                 :          0 :                (*fd != -1)) {
    3923         [ #  # ]:          0 :                 if (IsNonBlock)
    3924                 :            :                 {
    3925                 :          0 :                         tv.tv_sec = 1;
    3926                 :          0 :                         tv.tv_usec = 0;
    3927                 :            :                 
    3928                 :          0 :                         FD_ZERO(&rfds);
    3929                 :          0 :                         FD_SET(*fd, &rfds);
    3930         [ #  # ]:          0 :                         if (select(*fd + 1, &rfds, NULL, NULL, &tv) == -1) {
    3931                 :          0 :                                 *Error = strerror(errno);
    3932                 :          0 :                                 close (*fd);
    3933                 :          0 :                                 *fd = -1;
    3934         [ #  # ]:          0 :                                 if (*Error == NULL)
    3935                 :          0 :                                         *Error = ErrRBLF_SelectFailed;
    3936                 :          0 :                                 return -1;
    3937                 :            :                         }
    3938         [ #  # ]:          0 :                         if (! FD_ISSET(*fd, &rfds) != 0) {
    3939                 :          0 :                                 nSuccessLess ++;
    3940                 :          0 :                                 continue;
    3941                 :            :                         }
    3942                 :            :                 }
    3943                 :          0 :                 rlen = read(*fd, 
    3944                 :            :                             ptr,
    3945                 :          0 :                             IOBuf->BufSize - (ptr - IOBuf->buf));
    3946         [ #  # ]:          0 :                 if (rlen == -1) {
    3947                 :          0 :                         close(*fd);
    3948                 :          0 :                         *fd = -1;
    3949                 :          0 :                         *Error = strerror(errno);
    3950                 :          0 :                         return rlen;
    3951                 :            :                 }
    3952         [ #  # ]:          0 :                 else if (rlen == 0){
    3953 [ #  # ][ #  # ]:          0 :                         if ((check == NNN_TERM) && 
                 [ #  # ]
    3954                 :            :                             (nRead > 5) &&
    3955                 :          0 :                             (strncmp(IOBuf->buf + IOBuf->BufUsed - 5, "\n000\n", 5) == 0)) 
    3956                 :            :                         {
    3957                 :          0 :                                 StrBufPlain(Blob, HKEY("\n000\n"));
    3958                 :          0 :                                 StrBufCutRight(Blob, 5);
    3959                 :          0 :                                 return Blob->BufUsed;
    3960                 :            :                         }
    3961         [ #  # ]:          0 :                         else if (!IsNonBlock) 
    3962                 :          0 :                                 nSuccessLess ++;
    3963         [ #  # ]:          0 :                         else if (nSuccessLess > MaxTries) {
    3964                 :          0 :                                 FlushStrBuf(IOBuf);
    3965                 :          0 :                                 *Error = ErrRBB_too_many_selects;
    3966                 :          0 :                                 return -1;
    3967                 :            :                         }
    3968                 :            :                 }
    3969         [ #  # ]:          0 :                 else if (rlen > 0) {
    3970                 :          0 :                         nSuccessLess = 0;
    3971                 :          0 :                         nRead += rlen;
    3972                 :          0 :                         ptr += rlen;
    3973                 :          0 :                         IOBuf->BufUsed += rlen;
    3974                 :            :                 }
    3975                 :            :         }
    3976         [ #  # ]:          0 :         if (nSuccessLess >= MaxTries) {
    3977                 :          0 :                 FlushStrBuf(IOBuf);
    3978                 :          0 :                 *Error = ErrRBB_too_many_selects;
    3979                 :          0 :                 return -1;
    3980                 :            :         }
    3981                 :            : 
    3982         [ #  # ]:          0 :         if (nRead > nBytes) {
    3983                 :          0 :                 *Pos = IOBuf->buf + nBytes;
    3984                 :            :         }
    3985                 :          0 :         Blob->buf[Blob->BufUsed] = '\0';
    3986                 :          0 :         StrBufAppendBufPlain(Blob, IOBuf->buf, nBytes, 0);
    3987         [ #  # ]:          0 :         if (*Pos == NULL) {
    3988                 :          0 :                 FlushStrBuf(IOBuf);
    3989                 :            :         }
    3990                 :          0 :         return nRead + nAlreadyRead;
    3991                 :            : }
    3992                 :            : 
    3993                 :            : /**
    3994                 :            :  * @ingroup StrBuf_IO
    3995                 :            :  * @brief extract a "next line" from Buf; Ptr to persist across several iterations
    3996                 :            :  * @param LineBuf your line will be copied here.
    3997                 :            :  * @param Buf BLOB with lines of text...
    3998                 :            :  * @param Ptr moved arround to keep the next-line across several iterations
    3999                 :            :  *        has to be &NULL on start; will be &NotNULL on end of buffer
    4000                 :            :  * @returns size of copied buffer
    4001                 :            :  */
    4002                 :          0 : int StrBufSipLine(StrBuf *LineBuf, StrBuf *Buf, const char **Ptr)
    4003                 :            : {
    4004                 :            :         const char *aptr, *ptr, *eptr;
    4005                 :            :         char *optr, *xptr;
    4006                 :            : 
    4007 [ #  # ][ #  # ]:          0 :         if ((Buf == NULL) || (*Ptr == StrBufNOTNULL)) {
    4008                 :          0 :                 *Ptr = StrBufNOTNULL;
    4009                 :          0 :                 return 0;
    4010                 :            :         }
    4011                 :            : 
    4012                 :          0 :         FlushStrBuf(LineBuf);
    4013         [ #  # ]:          0 :         if (*Ptr==NULL)
    4014                 :          0 :                 ptr = aptr = Buf->buf;
    4015                 :            :         else
    4016                 :          0 :                 ptr = aptr = *Ptr;
    4017                 :            : 
    4018                 :          0 :         optr = LineBuf->buf;
    4019                 :          0 :         eptr = Buf->buf + Buf->BufUsed;
    4020                 :          0 :         xptr = LineBuf->buf + LineBuf->BufSize - 1;
    4021                 :            : 
    4022 [ #  # ][ #  # ]:          0 :         while ((ptr <= eptr) && 
                 [ #  # ]
    4023                 :          0 :                (*ptr != '\n') &&
    4024                 :          0 :                (*ptr != '\r') )
    4025                 :            :         {
    4026                 :          0 :                 *optr = *ptr;
    4027                 :          0 :                 optr++; ptr++;
    4028         [ #  # ]:          0 :                 if (optr == xptr) {
    4029                 :          0 :                         LineBuf->BufUsed = optr - LineBuf->buf;
    4030                 :          0 :                         IncreaseBuf(LineBuf,  1, LineBuf->BufUsed + 1);
    4031                 :          0 :                         optr = LineBuf->buf + LineBuf->BufUsed;
    4032                 :          0 :                         xptr = LineBuf->buf + LineBuf->BufSize - 1;
    4033                 :            :                 }
    4034                 :            :         }
    4035                 :            : 
    4036 [ #  # ][ #  # ]:          0 :         if ((ptr >= eptr) && (optr > LineBuf->buf))
    4037                 :          0 :                 optr --;
    4038                 :          0 :         LineBuf->BufUsed = optr - LineBuf->buf;
    4039                 :          0 :         *optr = '\0';       
    4040 [ #  # ][ #  # ]:          0 :         if ((ptr <= eptr) && (*ptr == '\r'))
    4041                 :          0 :                 ptr ++;
    4042 [ #  # ][ #  # ]:          0 :         if ((ptr <= eptr) && (*ptr == '\n'))
    4043                 :          0 :                 ptr ++;
    4044                 :            :         
    4045         [ #  # ]:          0 :         if (ptr < eptr) {
    4046                 :          0 :                 *Ptr = ptr;
    4047                 :            :         }
    4048                 :            :         else {
    4049                 :          0 :                 *Ptr = StrBufNOTNULL;
    4050                 :            :         }
    4051                 :            : 
    4052                 :          0 :         return Buf->BufUsed - (ptr - Buf->buf);
    4053                 :            : }
    4054                 :            : 
    4055                 :            : 
    4056                 :            : /**
    4057                 :            :  * @ingroup StrBuf_IO
    4058                 :            :  * @brief removes double slashes from pathnames
    4059                 :            :  * @param Dir directory string to filter
    4060                 :            :  * @param RemoveTrailingSlash allows / disallows trailing slashes
    4061                 :            :  */
    4062                 :          0 : void StrBufStripSlashes(StrBuf *Dir, int RemoveTrailingSlash)
    4063                 :            : {
    4064                 :            :         char *a, *b;
    4065                 :            : 
    4066                 :          0 :         a = b = Dir->buf;
    4067                 :            : 
    4068         [ #  # ]:          0 :         while (!IsEmptyStr(a)) {
    4069         [ #  # ]:          0 :                 if (*a == '/') {
    4070         [ #  # ]:          0 :                         while (*a == '/')
    4071                 :          0 :                                 a++;
    4072                 :          0 :                         *b = '/';
    4073                 :          0 :                         b++;
    4074                 :            :                 }
    4075                 :            :                 else {
    4076                 :          0 :                         *b = *a;
    4077                 :          0 :                         b++; a++;
    4078                 :            :                 }
    4079                 :            :         }
    4080 [ #  # ][ #  # ]:          0 :         if ((RemoveTrailingSlash) && (*(b - 1) != '/')){
    4081                 :          0 :                 *b = '/';
    4082                 :          0 :                 b++;
    4083                 :            :         }
    4084                 :          0 :         *b = '\0';
    4085                 :          0 :         Dir->BufUsed = b - Dir->buf;
    4086                 :          0 : }
    4087                 :            : 
    4088                 :            : 

Generated by: LCOV version 1.8