LCOV - code coverage report
Current view: top level - lib - tools.c (source / functions) Hit Total Coverage
Test: libcitadel.info Lines: 114 444 25.7 %
Date: 2010-12-07 Functions: 7 36 19.4 %
Branches: 68 312 21.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * A basic toolset containing miscellaneous functions for string manipluation,
       3                 :            :  * encoding/decoding, and a bunch of other stuff.
       4                 :            :  */
       5                 :            : 
       6                 :            : 
       7                 :            : #include <stdlib.h>
       8                 :            : #include <unistd.h>
       9                 :            : #include <stdio.h>
      10                 :            : #include <signal.h>
      11                 :            : #include <sys/types.h>
      12                 :            : #include <ctype.h>
      13                 :            : #include <string.h>
      14                 :            : #include <sys/stat.h>
      15                 :            : #include <errno.h>
      16                 :            : #include <limits.h>
      17                 :            : 
      18                 :            : #if TIME_WITH_SYS_TIME
      19                 :            : # include <sys/time.h>
      20                 :            : # include <time.h>
      21                 :            : #else
      22                 :            : # if HAVE_SYS_TIME_H
      23                 :            : #  include <sys/time.h>
      24                 :            : # else
      25                 :            : #  include <time.h>
      26                 :            : # endif
      27                 :            : #endif
      28                 :            : 
      29                 :            : #include "libcitadel.h"
      30                 :            : 
      31                 :            : 
      32                 :            : #define TRUE  1
      33                 :            : #define FALSE 0
      34                 :            : 
      35                 :            : typedef unsigned char byte;           /* Byte type */
      36                 :            : 
      37                 :            : /* Base64 encoding table */
      38                 :            : const byte etable[256] = {
      39                 :            :         65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
      40                 :            :         82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103,
      41                 :            :         104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
      42                 :            :         118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43,
      43                 :            :         47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      44                 :            :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      45                 :            :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      46                 :            :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      47                 :            :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      48                 :            :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      49                 :            :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      50                 :            :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      51                 :            :         0, 0, 0, 0, 0, 0, 0, 0, 0
      52                 :            : };
      53                 :            : 
      54                 :            : /* Base64 decoding table */
      55                 :            : const byte dtable[256] = {
      56                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      57                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      58                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      59                 :            :         128, 62, 128, 128, 128, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
      60                 :            :         128, 128, 128, 0, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
      61                 :            :         12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128,
      62                 :            :         128, 128, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
      63                 :            :         40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128,
      64                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      65                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      66                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      67                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      68                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      69                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      70                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      71                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      72                 :            :         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      73                 :            :         128, 128, 0
      74                 :            : };
      75                 :            : 
      76                 :            : /*
      77                 :            :  * copy a string into a buffer of a known size. abort if we exceed the limits
      78                 :            :  *
      79                 :            :  * dest the targetbuffer
      80                 :            :  * src  the source string
      81                 :            :  * n    the size od dest
      82                 :            :  *
      83                 :            :  * returns the number of characters copied if dest is big enough, -n if not.
      84                 :            :  */
      85                 :          0 : int safestrncpy(char *dest, const char *src, size_t n)
      86                 :            : {
      87                 :          0 :         int i = 0;
      88                 :            : 
      89 [ #  # ][ #  # ]:          0 :         if (dest == NULL || src == NULL) {
      90                 :          0 :                 fprintf(stderr, "safestrncpy: NULL argument\n");
      91                 :          0 :                 abort();
      92                 :            :         }
      93                 :            : 
      94                 :            :         do {
      95                 :          0 :                 dest[i] = src[i];
      96         [ #  # ]:          0 :                 if (dest[i] == 0) return i;
      97                 :          0 :                 ++i;
      98         [ #  # ]:          0 :         } while (i<n);
      99                 :          0 :         dest[n - 1] = 0;
     100                 :          0 :         return -i;
     101                 :            : }
     102                 :            : 
     103                 :            : 
     104                 :            : 
     105                 :            : /*
     106                 :            :  * num_tokens()  -  discover number of parameters/tokens in a string
     107                 :            :  */
     108                 :          0 : int num_tokens(const char *source, char tok)
     109                 :            : {
     110                 :          0 :         int count = 1;
     111                 :          0 :         const char *ptr = source;
     112                 :            : 
     113         [ #  # ]:          0 :         if (source == NULL) {
     114                 :          0 :                 return (0);
     115                 :            :         }
     116                 :            : 
     117         [ #  # ]:          0 :         while (*ptr != '\0') {
     118         [ #  # ]:          0 :                 if (*ptr++ == tok) {
     119                 :          0 :                         ++count;
     120                 :            :                 }
     121                 :            :         }
     122                 :            :         
     123                 :          0 :         return (count);
     124                 :            : }
     125                 :            : 
     126                 :            : //extern void cit_backtrace(void);
     127                 :            : 
     128                 :            : 
     129                 :            : /*
     130                 :            :  * extract_token() - a string tokenizer
     131                 :            :  * returns -1 if not found, or length of token.
     132                 :            :  */
     133                 :         40 : long extract_token(char *dest, const char *source, int parmnum, char separator, int maxlen)
     134                 :            : {
     135                 :            :         const char *s;                  //* source * /
     136                 :         40 :         int len = 0;                    //* running total length of extracted string * /
     137                 :         40 :         int current_token = 0;          //* token currently being processed * /
     138                 :            : 
     139                 :         40 :         s = source;
     140                 :            : 
     141         [ -  + ]:         40 :         if (dest == NULL) {
     142                 :          0 :                 return(-1);
     143                 :            :         }
     144                 :            : 
     145                 :            :         //cit_backtrace();
     146                 :            :         //lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
     147                 :         40 :         dest[0] = 0;
     148                 :            : 
     149         [ -  + ]:         40 :         if (s == NULL) {
     150                 :          0 :                 return(-1);
     151                 :            :         }
     152                 :            :         
     153                 :         40 :         maxlen--;
     154                 :            : 
     155         [ +  - ]:        560 :         while (*s) {
     156         [ +  + ]:        560 :                 if (*s == separator) {
     157                 :        100 :                         ++current_token;
     158                 :            :                 }
     159 [ +  + ][ +  + ]:        560 :                 if ( (current_token == parmnum) && 
                 [ +  - ]
     160                 :        260 :                      (*s != separator) && 
     161                 :            :                      (len < maxlen) ) {
     162                 :        220 :                         dest[len] = *s;
     163                 :        220 :                         ++len;
     164                 :            :                 }
     165 [ +  + ][ +  - ]:        340 :                 else if ((current_token > parmnum) || (len >= maxlen)) {
     166                 :            :                         break;
     167                 :            :                 }
     168                 :        520 :                 ++s;
     169                 :            :         }
     170                 :            : 
     171                 :         40 :         dest[len] = '\0';
     172         [ -  + ]:         40 :         if (current_token < parmnum) {
     173                 :            :                 //lprintf (CTDL_DEBUG,"test <!: %s\n", dest);
     174                 :          0 :                 return(-1);
     175                 :            :         }
     176                 :            :         //lprintf (CTDL_DEBUG,"test <: %d; %s\n", len, dest);
     177                 :         40 :         return(len);
     178                 :            : }
     179                 :            : //*/
     180                 :            : 
     181                 :            : 
     182                 :            : /*
     183                 :            :  * extract_token() - a string tokenizer
     184                 :            :  * /
     185                 :            : long extract_token(char *dest, const char *source, int parmnum, char separator, int maxlen)
     186                 :            : {
     187                 :            :         char *d;                // dest
     188                 :            :         const char *s;          // source
     189                 :            :         int count = 0;
     190                 :            :         int len = 0;
     191                 :            : 
     192                 :            :         
     193                 :            :         //cit_backtrace();
     194                 :            :         //lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
     195                 :            :         strcpy(dest, "");
     196                 :            : 
     197                 :            :         //  Locate desired parameter 
     198                 :            :         s = source;
     199                 :            :         while (count < parmnum) {
     200                 :            :                 //  End of string, bail!
     201                 :            :                 if (!*s) {
     202                 :            :                         s = NULL;
     203                 :            :                         break;
     204                 :            :                 }
     205                 :            :                 if (*s == separator) {
     206                 :            :                         count++;
     207                 :            :                 }
     208                 :            :                 s++;
     209                 :            :         }
     210                 :            :         if (!s) {
     211                 :            :                 //lprintf (CTDL_DEBUG,"test <!: %s\n", dest);
     212                 :            :                 return -1;              // Parameter not found
     213                 :            :         }
     214                 :            :         
     215                 :            :         for (d = dest; *s && *s != separator && ++len<maxlen; s++, d++) {
     216                 :            :                 *d = *s;
     217                 :            :         }
     218                 :            :         *d = 0;
     219                 :            :         //lprintf (CTDL_DEBUG,"test <: %d; %s\n", len, dest);
     220                 :            :         return 0;
     221                 :            : }
     222                 :            : */
     223                 :            : 
     224                 :            : 
     225                 :            : /*
     226                 :            :  * remove_token() - a tokenizer that kills, maims, and destroys
     227                 :            :  */
     228                 :          0 : void remove_token(char *source, int parmnum, char separator)
     229                 :            : {
     230                 :            :         char *d, *s;            /* dest, source */
     231                 :          0 :         int count = 0;
     232                 :            : 
     233                 :            :         /* Find desired parameter */
     234                 :          0 :         d = source;
     235         [ #  # ]:          0 :         while (count < parmnum) {
     236                 :            :                 /* End of string, bail! */
     237         [ #  # ]:          0 :                 if (!*d) {
     238                 :          0 :                         d = NULL;
     239                 :          0 :                         break;
     240                 :            :                 }
     241         [ #  # ]:          0 :                 if (*d == separator) {
     242                 :          0 :                         count++;
     243                 :            :                 }
     244                 :          0 :                 d++;
     245                 :            :         }
     246         [ #  # ]:          0 :         if (!d) return;         /* Parameter not found */
     247                 :            : 
     248                 :            :         /* Find next parameter */
     249                 :          0 :         s = d;
     250 [ #  # ][ #  # ]:          0 :         while (*s && *s != separator) {
     251                 :          0 :                 s++;
     252                 :            :         }
     253                 :            : 
     254                 :            :         /* Hack and slash */
     255         [ #  # ]:          0 :         if (*s)
     256                 :          0 :                 strcpy(d, ++s);
     257         [ #  # ]:          0 :         else if (d == source)
     258                 :          0 :                 *d = 0;
     259                 :            :         else
     260                 :          0 :                 *--d = 0;
     261                 :            :         /*
     262                 :            :         while (*s) {
     263                 :            :                 *d++ = *s++;
     264                 :            :         }
     265                 :            :         *d = 0;
     266                 :            :         */
     267                 :            : }
     268                 :            : 
     269                 :            : 
     270                 :            : /*
     271                 :            :  * extract_int()  -  extract an int parm w/o supplying a buffer
     272                 :            :  */
     273                 :          0 : int extract_int(const char *source, int parmnum)
     274                 :            : {
     275                 :            :         char buf[32];
     276                 :            :         
     277         [ #  # ]:          0 :         if (extract_token(buf, source, parmnum, '|', sizeof buf) > 0)
     278                 :          0 :                 return(atoi(buf));
     279                 :            :         else
     280                 :          0 :                 return 0;
     281                 :            : }
     282                 :            : 
     283                 :            : /*
     284                 :            :  * extract_long()  -  extract an long parm w/o supplying a buffer
     285                 :            :  */
     286                 :          0 : long extract_long(const char *source, int parmnum)
     287                 :            : {
     288                 :            :         char buf[32];
     289                 :            :         
     290         [ #  # ]:          0 :         if (extract_token(buf, source, parmnum, '|', sizeof buf) > 0)
     291                 :          0 :                 return(atol(buf));
     292                 :            :         else
     293                 :          0 :                 return 0;
     294                 :            : }
     295                 :            : 
     296                 :            : 
     297                 :            : /*
     298                 :            :  * extract_unsigned_long() - extract an unsigned long parm
     299                 :            :  */
     300                 :          0 : unsigned long extract_unsigned_long(const char *source, int parmnum)
     301                 :            : {
     302                 :            :         char buf[32];
     303                 :            : 
     304         [ #  # ]:          0 :         if (extract_token(buf, source, parmnum, '|', sizeof buf) > 0)
     305                 :          0 :                 return strtoul(buf, NULL, 10);
     306                 :            :         else 
     307                 :          0 :                 return 0;
     308                 :            : }
     309                 :            : 
     310                 :            : 
     311                 :            : /*
     312                 :            :  * CtdlDecodeBase64() and CtdlEncodeBase64() are adaptations of code by John Walker.
     313                 :            :  */
     314                 :            : 
     315                 :          0 : size_t CtdlEncodeBase64(char *dest, const char *source, size_t sourcelen, int linebreaks)
     316                 :            : {
     317                 :          0 :         int i, hiteof = FALSE;
     318                 :          0 :         int spos = 0;
     319                 :          0 :         int dpos = 0;
     320                 :          0 :         int thisline = 0;
     321                 :            : 
     322         [ #  # ]:          0 :         while (!hiteof) {
     323                 :            :                 byte igroup[3], ogroup[4];
     324                 :            :                 int c, n;
     325                 :            : 
     326                 :          0 :                 igroup[0] = igroup[1] = igroup[2] = 0;
     327         [ #  # ]:          0 :                 for (n = 0; n < 3; n++) {
     328         [ #  # ]:          0 :                         if (spos >= sourcelen) {
     329                 :          0 :                                 hiteof = TRUE;
     330                 :          0 :                                 break;
     331                 :            :                         }
     332                 :          0 :                         c = source[spos++];
     333                 :          0 :                         igroup[n] = (byte) c;
     334                 :            :                 }
     335         [ #  # ]:          0 :                 if (n > 0) {
     336                 :          0 :                         ogroup[0] = etable[igroup[0] >> 2];
     337                 :          0 :                         ogroup[1] =
     338                 :          0 :                             etable[((igroup[0] & 3) << 4) |
     339                 :          0 :                                    (igroup[1] >> 4)];
     340                 :          0 :                         ogroup[2] =
     341                 :          0 :                             etable[((igroup[1] & 0xF) << 2) |
     342                 :          0 :                                    (igroup[2] >> 6)];
     343                 :          0 :                         ogroup[3] = etable[igroup[2] & 0x3F];
     344                 :            : 
     345                 :            :                         /*
     346                 :            :                          * Replace characters in output stream with "=" pad
     347                 :            :                          * characters if fewer than three characters were
     348                 :            :                          * read from the end of the input stream. 
     349                 :            :                          */
     350                 :            : 
     351         [ #  # ]:          0 :                         if (n < 3) {
     352                 :          0 :                                 ogroup[3] = '=';
     353         [ #  # ]:          0 :                                 if (n < 2) {
     354                 :          0 :                                         ogroup[2] = '=';
     355                 :            :                                 }
     356                 :            :                         }
     357         [ #  # ]:          0 :                         for (i = 0; i < 4; i++) {
     358                 :          0 :                                 dest[dpos++] = ogroup[i];
     359                 :          0 :                                 dest[dpos] = 0;
     360                 :            :                         }
     361                 :          0 :                         thisline += 4;
     362 [ #  # ][ #  # ]:          0 :                         if ( (linebreaks) && (thisline > 70) ) {
     363                 :          0 :                                 dest[dpos++] = '\r';
     364                 :          0 :                                 dest[dpos++] = '\n';
     365                 :          0 :                                 dest[dpos] = 0;
     366                 :          0 :                                 thisline = 0;
     367                 :            :                         }
     368                 :            :                 }
     369                 :            :         }
     370 [ #  # ][ #  # ]:          0 :         if ( (linebreaks) && (thisline > 70) ) {
     371                 :          0 :                 dest[dpos++] = '\r';
     372                 :          0 :                 dest[dpos++] = '\n';
     373                 :          0 :                 dest[dpos] = 0;
     374                 :          0 :                 thisline = 0;
     375                 :            :         }
     376                 :            : 
     377                 :          0 :         return(dpos);
     378                 :            : }
     379                 :            : 
     380                 :            : 
     381                 :            : 
     382                 :            : /* 
     383                 :            :  * Convert base64-encoded to binary.  Returns the length of the decoded data.
     384                 :            :  * It will stop after reading 'length' bytes.
     385                 :            :  */
     386                 :       1236 : int CtdlDecodeBase64(char *dest, const char *source, size_t length)
     387                 :            : {
     388                 :            :     int i, c;
     389                 :       1236 :     int dpos = 0;
     390                 :       1236 :     int spos = 0;
     391                 :            : 
     392                 :            :     while (TRUE) {
     393                 :            :         byte a[4], b[4], o[3];
     394                 :            : 
     395         [ +  + ]:  163803132 :         for (i = 0; i < 4; i++) {
     396         [ +  + ]:  131385529 :             if (spos >= length) {
     397                 :        393 :                 return(dpos);
     398                 :            :             }
     399                 :  131385136 :             c = source[spos++];
     400                 :            : 
     401         [ -  + ]:  131385136 :             if (c == 0) {
     402         [ #  # ]:          0 :                 if (i > 0) {
     403                 :          0 :                     return(dpos);
     404                 :            :                 }
     405                 :          0 :                 return(dpos);
     406                 :            :             }
     407         [ +  + ]:  131385136 :             if (dtable[c] & 0x80) {
     408                 :            :                 /* Ignoring errors: discard invalid character. */
     409                 :    1714724 :                 i--;
     410                 :    1714724 :                 continue;
     411                 :            :             }
     412                 :  129670412 :             a[i] = (byte) c;
     413                 :  129670412 :             b[i] = (byte) dtable[c];
     414                 :            :         }
     415                 :   32417603 :         o[0] = (b[0] << 2) | (b[1] >> 4);
     416                 :   32417603 :         o[1] = (b[1] << 4) | (b[2] >> 2);
     417                 :   32417603 :         o[2] = (b[2] << 6) | b[3];
     418 [ +  + ][ +  + ]:   32417603 :         i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
     419         [ +  - ]:   32417603 :         if (i>=1) dest[dpos++] = o[0];
     420         [ +  + ]:   32417603 :         if (i>=2) dest[dpos++] = o[1];
     421         [ +  + ]:   32417603 :         if (i>=3) dest[dpos++] = o[2];
     422                 :   32417603 :         dest[dpos] = 0;
     423         [ +  + ]:   32417603 :         if (i < 3) {
     424                 :        843 :             return(dpos);
     425                 :            :         }
     426                 :   32417996 :     }
     427                 :            : }
     428                 :            : 
     429                 :            : 
     430                 :            : /*
     431                 :            :  * if we send out non ascii subjects, we encode it this way.
     432                 :            :  */
     433                 :          0 : char *rfc2047encode(char *line, long length)
     434                 :            : {
     435                 :            :         char *AlreadyEncoded;
     436                 :            :         char *result;
     437                 :            :         long end;
     438                 :            : #define UTF8_HEADER "=?UTF-8?B?"
     439                 :            : 
     440                 :            :         /* check if we're already done */
     441                 :          0 :         AlreadyEncoded = strstr(line, "=?");
     442 [ #  # ][ #  # ]:          0 :         if ((AlreadyEncoded != NULL) &&
                 [ #  # ]
     443                 :          0 :             ((strstr(AlreadyEncoded, "?B?") != NULL)||
     444                 :          0 :              (strstr(AlreadyEncoded, "?Q?") != NULL)))
     445                 :            :         {
     446                 :          0 :                 return strdup(line);
     447                 :            :         }
     448                 :            : 
     449                 :          0 :         result = (char*) malloc(sizeof(UTF8_HEADER) + 4 + length * 2);
     450                 :          0 :         strncpy (result, UTF8_HEADER, strlen (UTF8_HEADER));
     451                 :          0 :         CtdlEncodeBase64(result + strlen(UTF8_HEADER), line, length, 0);
     452                 :          0 :         end = strlen (result);
     453                 :          0 :         result[end]='?';
     454                 :          0 :         result[end+1]='=';
     455                 :          0 :         result[end+2]='\0';
     456                 :          0 :         return result;
     457                 :            : }
     458                 :            : 
     459                 :            : /*
     460                 :            :  * removes double slashes from pathnames
     461                 :            :  * allows / disallows trailing slashes
     462                 :            :  */
     463                 :          0 : void StripSlashes(char *Dir, int TrailingSlash)
     464                 :            : {
     465                 :            :         char *a, *b;
     466                 :            : 
     467                 :          0 :         a = b = Dir;
     468                 :            : 
     469         [ #  # ]:          0 :         while (!IsEmptyStr(a)) {
     470         [ #  # ]:          0 :                 if (*a == '/') {
     471         [ #  # ]:          0 :                         while (*a == '/')
     472                 :          0 :                                 a++;
     473                 :          0 :                         *b = '/';
     474                 :          0 :                         b++;
     475                 :            :                 }
     476                 :            :                 else {
     477                 :          0 :                         *b = *a;
     478                 :          0 :                         b++; a++;
     479                 :            :                 }
     480                 :            :         }
     481 [ #  # ][ #  # ]:          0 :         if ((TrailingSlash) && (*(b - 1) != '/')){
     482                 :          0 :                 *b = '/';
     483                 :          0 :                 b++;
     484                 :            :         }
     485                 :          0 :         *b = '\0';
     486                 :            : 
     487                 :          0 : }
     488                 :            : 
     489                 :            : /*
     490                 :            :  * Strip leading and trailing spaces from a string
     491                 :            :  */
     492                 :       7725 : size_t striplt(char *buf) {
     493                 :       7725 :         char *first_nonspace = NULL;
     494                 :       7725 :         char *last_nonspace = NULL;
     495                 :            :         char *ptr;
     496                 :       7725 :         size_t new_len = 0;
     497                 :            : 
     498 [ +  - ][ -  + ]:       7725 :         if ((buf == NULL) || (*buf == '\0')) {
     499                 :          0 :                 return 0;
     500                 :            :         }
     501                 :            : 
     502         [ +  + ]:     204499 :         for (ptr=buf; *ptr!=0; ++ptr) {
     503         [ +  + ]:     196774 :                 if (!isspace(*ptr)) {
     504         [ +  + ]:     186836 :                         if (!first_nonspace) {
     505                 :       7725 :                                 first_nonspace = ptr;
     506                 :            :                         }
     507                 :     186836 :                         last_nonspace = ptr;
     508                 :            :                 }
     509                 :            :         }
     510                 :            : 
     511 [ +  - ][ -  + ]:       7725 :         if ((!first_nonspace) || (!last_nonspace)) {
     512                 :          0 :                 buf[0] = 0;
     513                 :          0 :                 return 0;
     514                 :            :         }
     515                 :            : 
     516                 :       7725 :         new_len = last_nonspace - first_nonspace + 1;
     517                 :       7725 :         memmove(buf, first_nonspace, new_len);
     518                 :       7725 :         buf[new_len] = 0;
     519                 :       7725 :         return new_len;
     520                 :            : }
     521                 :            : 
     522                 :            : 
     523                 :            : /**
     524                 :            :  * \brief check for the presence of a character within a string (returns count)
     525                 :            :  * \param st the string to examine
     526                 :            :  * \param ch the char to search
     527                 :            :  * \return the number of times ch appears in st
     528                 :            :  */
     529                 :          0 : int haschar(const char *st, int ch)
     530                 :            : {
     531                 :            :         const char *ptr;
     532                 :            :         int b;
     533                 :          0 :         b = 0;
     534                 :          0 :         ptr = st;
     535         [ #  # ]:          0 :         while (!IsEmptyStr(ptr))
     536                 :            :         {
     537         [ #  # ]:          0 :                 if (*ptr == ch)
     538                 :          0 :                         ++b;
     539                 :          0 :                 ptr ++;
     540                 :            :         }
     541                 :          0 :         return (b);
     542                 :            : }
     543                 :            : 
     544                 :            : 
     545                 :            : 
     546                 :            : 
     547                 :            : 
     548                 :            : /*
     549                 :            :  * Format a date/time stamp for output 
     550                 :            :  * seconds is whether to print the seconds
     551                 :            :  */
     552                 :          0 : void fmt_date(char *buf, size_t n, time_t thetime, int seconds) {
     553                 :            :         struct tm tm;
     554                 :            :         int hour;
     555                 :            : 
     556                 :            :         /* Month strings for date conversions ... this needs to be localized eventually */
     557                 :            :         char *fmt_date_months[12] = {
     558                 :            :                 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
     559                 :          0 :         };
     560                 :            : 
     561                 :          0 :         strcpy(buf, "");
     562                 :          0 :         localtime_r(&thetime, &tm);
     563                 :            : 
     564                 :          0 :         hour = tm.tm_hour;
     565         [ #  # ]:          0 :         if (hour == 0)  hour = 12;
     566         [ #  # ]:          0 :         else if (hour > 12) hour = hour - 12;
     567                 :            : 
     568         [ #  # ]:          0 :         if (seconds) {
     569         [ #  # ]:          0 :                 snprintf(buf, n, "%s %d %4d %d:%02d:%02d%s",
     570                 :          0 :                         fmt_date_months[tm.tm_mon],
     571                 :            :                         tm.tm_mday,
     572                 :            :                         tm.tm_year + 1900,
     573                 :            :                         hour,
     574                 :            :                         tm.tm_min,
     575                 :            :                         tm.tm_sec,
     576                 :          0 :                         ( (tm.tm_hour >= 12) ? "pm" : "am" )
     577                 :            :                 );
     578                 :            :         } else {
     579         [ #  # ]:          0 :                 snprintf(buf, n, "%s %d %4d %d:%02d%s",
     580                 :          0 :                         fmt_date_months[tm.tm_mon],
     581                 :            :                         tm.tm_mday,
     582                 :            :                         tm.tm_year + 1900,
     583                 :            :                         hour,
     584                 :            :                         tm.tm_min,
     585                 :          0 :                         ( (tm.tm_hour >= 12) ? "pm" : "am" )
     586                 :            :                 );
     587                 :            :         }
     588                 :          0 : }
     589                 :            : 
     590                 :            : 
     591                 :            : 
     592                 :            : /*
     593                 :            :  * Determine whether the specified message number is contained within the
     594                 :            :  * specified sequence set.
     595                 :            :  */
     596                 :          0 : int is_msg_in_sequence_set(const char *mset, long msgnum) {
     597                 :            :         int num_sets;
     598                 :            :         int s;
     599                 :            :         char setstr[128], lostr[128], histr[128];
     600                 :            :         long lo, hi;
     601                 :            : 
     602                 :          0 :         num_sets = num_tokens(mset, ',');
     603         [ #  # ]:          0 :         for (s=0; s<num_sets; ++s) {
     604                 :          0 :                 extract_token(setstr, mset, s, ',', sizeof setstr);
     605                 :            : 
     606                 :          0 :                 extract_token(lostr, setstr, 0, ':', sizeof lostr);
     607         [ #  # ]:          0 :                 if (num_tokens(setstr, ':') >= 2) {
     608                 :          0 :                         extract_token(histr, setstr, 1, ':', sizeof histr);
     609         [ #  # ]:          0 :                         if (!strcmp(histr, "*")) {
     610                 :          0 :                                 snprintf(histr, sizeof histr, "%ld", LONG_MAX);
     611                 :            :                         }
     612                 :            :                 } 
     613                 :            :                 else {
     614                 :          0 :                         strcpy(histr, lostr);
     615                 :            :                 }
     616                 :          0 :                 lo = atol(lostr);
     617                 :          0 :                 hi = atol(histr);
     618                 :            : 
     619   [ #  #  #  # ]:          0 :                 if ((msgnum >= lo) && (msgnum <= hi)) return(1);
     620                 :            :         }
     621                 :            : 
     622                 :          0 :         return(0);
     623                 :            : }
     624                 :            : 
     625                 :            : /** 
     626                 :            :  * \brief Utility function to "readline" from memory
     627                 :            :  * \param start Location in memory from which we are reading.
     628                 :            :  * \param buf the buffer to place the string in.
     629                 :            :  * \param maxlen Size of string buffer
     630                 :            :  * \return Pointer to the source memory right after we stopped reading.
     631                 :            :  */
     632                 :          0 : char *memreadline(char *start, char *buf, int maxlen)
     633                 :            : {
     634                 :            :         char ch;
     635                 :            :         char *ptr;
     636                 :          0 :         int len = 0;            /**< tally our own length to avoid strlen() delays */
     637                 :            : 
     638                 :          0 :         ptr = start;
     639                 :            : 
     640                 :            :         while (1) {
     641                 :          0 :                 ch = *ptr++;
     642 [ #  # ][ #  # ]:          0 :                 if ((len + 1 < (maxlen)) && (ch != 13) && (ch != 10)) {
                 [ #  # ]
     643                 :          0 :                         buf[len++] = ch;
     644                 :            :                 }
     645 [ #  # ][ #  # ]:          0 :                 if ((ch == 10) || (ch == 0)) {
     646                 :          0 :                         buf[len] = 0;
     647                 :          0 :                         return ptr;
     648                 :            :                 }
     649                 :          0 :         }
     650                 :            : }
     651                 :            : 
     652                 :            : 
     653                 :            : /** 
     654                 :            :  * \brief Utility function to "readline" from memory
     655                 :            :  * \param start Location in memory from which we are reading.
     656                 :            :  * \param buf the buffer to place the string in.
     657                 :            :  * \param maxlen Size of string buffer
     658                 :            :  * \param retlen the length of the returned string
     659                 :            :  * \return Pointer to the source memory right after we stopped reading.
     660                 :            :  */
     661                 :      19370 : char *memreadlinelen(char *start, char *buf, int maxlen, int *retlen)
     662                 :            : {
     663                 :            :         char ch;
     664                 :            :         char *ptr;
     665                 :      19370 :         int len = 0;            /**< tally our own length to avoid strlen() delays */
     666                 :            : 
     667                 :      19370 :         ptr = start;
     668                 :            : 
     669                 :            :         while (1) {
     670                 :     637677 :                 ch = *ptr++;
     671 [ +  - ][ +  + ]:     637677 :                 if ((len + 1 < (maxlen)) && (ch != 13) && (ch != 10)) {
                 [ +  + ]
     672                 :     615431 :                         buf[len++] = ch;
     673                 :            :                 }
     674 [ +  + ][ -  + ]:     637677 :                 if ((ch == 10) || (ch == 0)) {
     675                 :      19370 :                         buf[len] = 0;
     676                 :      19370 :                         *retlen = len;
     677                 :      19370 :                         return ptr;
     678                 :            :                 }
     679                 :     618307 :         }
     680                 :            : }
     681                 :            : 
     682                 :            : 
     683                 :            : /** 
     684                 :            :  * \brief Utility function to "readline" from memory
     685                 :            :  * \param start Location in memory from which we are reading.
     686                 :            :  * \param buf the buffer to place the string in.
     687                 :            :  * \param maxlen Size of string buffer
     688                 :            :  * \return Pointer to the source memory right after we stopped reading.
     689                 :            :  */
     690                 :          0 : const char *cmemreadline(const char *start, char *buf, int maxlen)
     691                 :            : {
     692                 :            :         char ch;
     693                 :            :         const char *ptr;
     694                 :          0 :         int len = 0;            /**< tally our own length to avoid strlen() delays */
     695                 :            : 
     696                 :          0 :         ptr = start;
     697                 :            : 
     698                 :            :         while (1) {
     699                 :          0 :                 ch = *ptr++;
     700 [ #  # ][ #  # ]:          0 :                 if ((len + 1 < (maxlen)) && (ch != 13) && (ch != 10)) {
                 [ #  # ]
     701                 :          0 :                         buf[len++] = ch;
     702                 :            :                 }
     703 [ #  # ][ #  # ]:          0 :                 if ((ch == 10) || (ch == 0)) {
     704                 :          0 :                         buf[len] = 0;
     705                 :          0 :                         return ptr;
     706                 :            :                 }
     707                 :          0 :         }
     708                 :            : }
     709                 :            : 
     710                 :            : 
     711                 :            : /** 
     712                 :            :  * \brief Utility function to "readline" from memory
     713                 :            :  * \param start Location in memory from which we are reading.
     714                 :            :  * \param buf the buffer to place the string in.
     715                 :            :  * \param maxlen Size of string buffer
     716                 :            :  * \param retlen the length of the returned string
     717                 :            :  * \return Pointer to the source memory right after we stopped reading.
     718                 :            :  */
     719                 :          0 : const char *cmemreadlinelen(const char *start, char *buf, int maxlen, int *retlen)
     720                 :            : {
     721                 :            :         char ch;
     722                 :            :         const char *ptr;
     723                 :          0 :         int len = 0;            /**< tally our own length to avoid strlen() delays */
     724                 :            : 
     725                 :          0 :         ptr = start;
     726                 :            : 
     727                 :            :         while (1) {
     728                 :          0 :                 ch = *ptr++;
     729 [ #  # ][ #  # ]:          0 :                 if ((len + 1 < (maxlen)) && (ch != 13) && (ch != 10)) {
                 [ #  # ]
     730                 :          0 :                         buf[len++] = ch;
     731                 :            :                 }
     732 [ #  # ][ #  # ]:          0 :                 if ((ch == 10) || (ch == 0)) {
     733                 :          0 :                         buf[len] = 0;
     734                 :          0 :                         *retlen = len;
     735                 :          0 :                         return ptr;
     736                 :            :                 }
     737                 :          0 :         }
     738                 :            : }
     739                 :            : 
     740                 :            : 
     741                 :            : 
     742                 :            : 
     743                 :            : /*
     744                 :            :  * Strip a boundarized substring out of a string (for example, remove
     745                 :            :  * parentheses and anything inside them).
     746                 :            :  */
     747                 :          0 : int stripout(char *str, char leftboundary, char rightboundary) {
     748                 :            :         int a;
     749                 :          0 :         int lb = (-1);
     750                 :          0 :         int rb = (-1);
     751                 :            : 
     752         [ #  # ]:          0 :         for (a = 0; a < strlen(str); ++a) {
     753         [ #  # ]:          0 :                 if (str[a] == leftboundary) lb = a;
     754         [ #  # ]:          0 :                 if (str[a] == rightboundary) rb = a;
     755                 :            :         }
     756                 :            : 
     757 [ #  # ][ #  # ]:          0 :         if ( (lb > 0) && (rb > lb) ) {
     758                 :          0 :                 strcpy(&str[lb - 1], &str[rb + 1]);
     759                 :          0 :                 return 1;
     760                 :            :         }
     761                 :            : 
     762 [ #  # ][ #  # ]:          0 :         else if ( (lb == 0) && (rb > lb) ) {
     763                 :          0 :                 strcpy(str, &str[rb + 1]);
     764                 :          0 :                 return 1;
     765                 :            :         }
     766                 :          0 :         return 0;
     767                 :            : }
     768                 :            : 
     769                 :            : 
     770                 :            : /*
     771                 :            :  * Reduce a string down to a boundarized substring (for example, remove
     772                 :            :  * parentheses and anything outside them).
     773                 :            :  */
     774                 :       1240 : long stripallbut(char *str, char leftboundary, char rightboundary) {
     775                 :       1240 :         long len = 0;
     776                 :            : 
     777                 :       1240 :         char *lb = NULL;
     778                 :       1240 :         char *rb = NULL;
     779                 :            : 
     780                 :       1240 :         lb = strrchr(str, leftboundary);
     781         [ +  - ]:       1240 :         if (lb != NULL) {
     782                 :       1240 :                 ++lb;
     783                 :       1240 :                 rb = strchr(str, rightboundary);
     784 [ +  - ][ +  - ]:       1240 :                 if ((rb != NULL) && (rb >= lb))  {
     785                 :       1240 :                         *rb = 0;
     786                 :       1240 :                         fflush(stderr);
     787                 :       1240 :                         len = (long)rb - (long)lb;
     788                 :       1240 :                         memmove(str, lb, len);
     789                 :       1240 :                         str[len] = 0;
     790                 :       1240 :                         return(len);
     791                 :            :                 }
     792                 :            :         }
     793                 :            : 
     794                 :       1240 :         return (long)strlen(str);
     795                 :            : }
     796                 :            : 
     797                 :            : 
     798                 :          0 : char *myfgets(char *s, int size, FILE *stream) {
     799                 :          0 :         char *ret = fgets(s, size, stream);
     800                 :            :         char *nl;
     801                 :            : 
     802         [ #  # ]:          0 :         if (ret != NULL) {
     803                 :          0 :                 nl = strchr(s, '\n');
     804                 :            : 
     805         [ #  # ]:          0 :                 if (nl != NULL)
     806                 :          0 :                         *nl = 0;
     807                 :            :         }
     808                 :            : 
     809                 :          0 :         return ret;
     810                 :            : }
     811                 :            : 
     812                 :            : /** 
     813                 :            :  * \brief Escape a string for feeding out as a URL.
     814                 :            :  * \param outbuf the output buffer
     815                 :            :  * \param oblen the size of outbuf to sanitize
     816                 :            :  * \param strbuf the input buffer
     817                 :            :  */
     818                 :          0 : void urlesc(char *outbuf, size_t oblen, char *strbuf)
     819                 :            : {
     820                 :            :         int a, b, c, len, eclen, olen;
     821                 :          0 :         char *ec = " +#&;`'|*?-~<>^()[]{}/$\"\\";
     822                 :            : 
     823                 :          0 :         strcpy(outbuf, "");
     824                 :          0 :         len = strlen(strbuf);
     825                 :          0 :         eclen = strlen(ec);
     826                 :          0 :         olen = 0;
     827         [ #  # ]:          0 :         for (a = 0; a < len; ++a) {
     828                 :          0 :                 c = 0;
     829         [ #  # ]:          0 :                 for (b = 0; b < eclen; ++b) {
     830         [ #  # ]:          0 :                         if (strbuf[a] == ec[b])
     831                 :          0 :                                 c = 1;
     832                 :            :                 }
     833         [ #  # ]:          0 :                 if (c == 1) {
     834                 :          0 :                         snprintf(&outbuf[olen], oblen - olen, "%%%02x", strbuf[a]);
     835                 :          0 :                         olen += 3;
     836                 :            :                 }
     837                 :            :                 else 
     838                 :          0 :                         outbuf[olen ++] = strbuf[a];
     839                 :            :         }
     840                 :          0 :         outbuf[olen] = '\0';
     841                 :          0 : }
     842                 :            : 
     843                 :            : 
     844                 :            : 
     845                 :            : /*
     846                 :            :  * In our world, we want strcpy() to be able to work with overlapping strings.
     847                 :            :  */
     848                 :            : #ifdef strcpy
     849                 :            : #undef strcpy
     850                 :            : #endif
     851                 :            : char *strcpy(char *dest, const char *src) {
     852                 :       7007 :         memmove(dest, src, (strlen(src) + 1) );
     853                 :       7007 :         return(dest);
     854                 :            : }
     855                 :            : 
     856                 :            : 
     857                 :            : /*
     858                 :            :  * Generate a new, globally unique UID parameter for a calendar etc. object
     859                 :            :  */
     860                 :          0 : void generate_uuid(char *buf) {
     861                 :            :         static int seq = 0;
     862                 :            : 
     863                 :          0 :         sprintf(buf, "%lx-%lx-%x",
     864                 :            :                 time(NULL),
     865                 :            :                 (long)getpid(),
     866                 :            :                 (seq++)
     867                 :            :         );
     868                 :          0 : }
     869                 :            : 
     870                 :            : /*
     871                 :            :  * bmstrcasestr() -- case-insensitive substring search
     872                 :            :  *
     873                 :            :  * This uses the Boyer-Moore search algorithm and is therefore quite fast.
     874                 :            :  * The code is roughly based on the strstr() replacement from 'tin' written
     875                 :            :  * by Urs Jannsen.
     876                 :            :  */
     877                 :       9988 : inline static char *_bmstrcasestr_len(char *text, size_t textlen, const char *pattern, size_t patlen) {
     878                 :            : 
     879                 :            :         register unsigned char *p, *t;
     880                 :            :         register int i, j, *delta;
     881                 :            :         register size_t p1;
     882                 :            :         int deltaspace[256];
     883                 :            : 
     884         [ -  + ]:       9988 :         if (!text) return(NULL);
     885         [ -  + ]:       9988 :         if (!pattern) return(NULL);
     886                 :            : 
     887                 :            :         /* algorithm fails if pattern is empty */
     888         [ -  + ]:       9988 :         if ((p1 = patlen) == 0)
     889                 :          0 :                 return (text);
     890                 :            : 
     891                 :            :         /* code below fails (whenever i is unsigned) if pattern too long */
     892         [ +  + ]:       9988 :         if (p1 > textlen)
     893                 :        141 :                 return (NULL);
     894                 :            : 
     895                 :            :         /* set up deltas */
     896                 :       9847 :         delta = deltaspace;
     897         [ +  + ]:    2530679 :         for (i = 0; i <= 255; i++)
     898                 :    2520832 :                 delta[i] = p1;
     899         [ +  + ]:      61426 :         for (p = (unsigned char *) pattern, i = p1; --i > 0;)
     900                 :      51579 :                 delta[tolower(*p++)] = i;
     901                 :            : 
     902                 :            :         /*
     903                 :            :          * From now on, we want patlen - 1.
     904                 :            :          * In the loop below, p points to the end of the pattern,
     905                 :            :          * t points to the end of the text to be tested against the
     906                 :            :          * pattern, and i counts the amount of text remaining, not
     907                 :            :          * including the part to be tested.
     908                 :            :          */
     909                 :       9847 :         p1--;
     910                 :       9847 :         p = (unsigned char *) pattern + p1;
     911                 :       9847 :         t = (unsigned char *) text + p1;
     912                 :       9847 :         i = textlen - patlen;
     913                 :            :         while(1) {
     914         [ +  + ]:      50672 :                 if (tolower(p[0]) == tolower(t[0])) {
     915         [ +  + ]:       4246 :                         if (strncasecmp ((const char *)(p - p1), (const char *)(t - p1), p1) == 0) {
     916                 :       3052 :                                 return ((char *)t - p1);
     917                 :            :                         }
     918                 :            :                 }
     919                 :      47620 :                 j = delta[tolower(t[0])];
     920         [ +  + ]:      47620 :                 if (i < j)
     921                 :            :                         break;
     922                 :      40825 :                 i -= j;
     923                 :      40825 :                 t += j;
     924                 :      50813 :         }
     925                 :       6795 :         return (NULL);
     926                 :            : }
     927                 :            : 
     928                 :            : /*
     929                 :            :  * bmstrcasestr() -- case-insensitive substring search
     930                 :            :  *
     931                 :            :  * This uses the Boyer-Moore search algorithm and is therefore quite fast.
     932                 :            :  * The code is roughly based on the strstr() replacement from 'tin' written
     933                 :            :  * by Urs Jannsen.
     934                 :            :  */
     935                 :          0 : char *bmstrcasestr(char *text, const char *pattern) {
     936                 :            :         size_t textlen;
     937                 :            :         size_t patlen;
     938                 :            : 
     939         [ #  # ]:          0 :         if (!text) return(NULL);
     940         [ #  # ]:          0 :         if (!pattern) return(NULL);
     941                 :            : 
     942                 :          0 :         textlen = strlen (text);
     943                 :          0 :         patlen = strlen (pattern);
     944                 :            : 
     945                 :          0 :         return _bmstrcasestr_len(text, textlen, pattern, patlen);
     946                 :            : }
     947                 :            : 
     948                 :       9988 : char *bmstrcasestr_len(char *text, size_t textlen, const char *pattern, size_t patlen) {
     949                 :       9988 :         return _bmstrcasestr_len(text, textlen, pattern, patlen);
     950                 :            : }
     951                 :            : 
     952                 :            : 
     953                 :            : 
     954                 :            : 
     955                 :            : /*
     956                 :            :  * bmstrcasestr() -- case-insensitive substring search
     957                 :            :  *
     958                 :            :  * This uses the Boyer-Moore search algorithm and is therefore quite fast.
     959                 :            :  * The code is roughly based on the strstr() replacement from 'tin' written
     960                 :            :  * by Urs Jannsen.
     961                 :            :  */
     962                 :          0 : inline static const char *_cbmstrcasestr_len(const char *text, size_t textlen, const char *pattern, size_t patlen) {
     963                 :            : 
     964                 :            :         register unsigned char *p, *t;
     965                 :            :         register int i, j, *delta;
     966                 :            :         register size_t p1;
     967                 :            :         int deltaspace[256];
     968                 :            : 
     969         [ #  # ]:          0 :         if (!text) return(NULL);
     970         [ #  # ]:          0 :         if (!pattern) return(NULL);
     971                 :            : 
     972                 :            :         /* algorithm fails if pattern is empty */
     973         [ #  # ]:          0 :         if ((p1 = patlen) == 0)
     974                 :          0 :                 return (text);
     975                 :            : 
     976                 :            :         /* code below fails (whenever i is unsigned) if pattern too long */
     977         [ #  # ]:          0 :         if (p1 > textlen)
     978                 :          0 :                 return (NULL);
     979                 :            : 
     980                 :            :         /* set up deltas */
     981                 :          0 :         delta = deltaspace;
     982         [ #  # ]:          0 :         for (i = 0; i <= 255; i++)
     983                 :          0 :                 delta[i] = p1;
     984         [ #  # ]:          0 :         for (p = (unsigned char *) pattern, i = p1; --i > 0;)
     985                 :          0 :                 delta[tolower(*p++)] = i;
     986                 :            : 
     987                 :            :         /*
     988                 :            :          * From now on, we want patlen - 1.
     989                 :            :          * In the loop below, p points to the end of the pattern,
     990                 :            :          * t points to the end of the text to be tested against the
     991                 :            :          * pattern, and i counts the amount of text remaining, not
     992                 :            :          * including the part to be tested.
     993                 :            :          */
     994                 :          0 :         p1--;
     995                 :          0 :         p = (unsigned char *) pattern + p1;
     996                 :          0 :         t = (unsigned char *) text + p1;
     997                 :          0 :         i = textlen - patlen;
     998                 :            :         while(1) {
     999         [ #  # ]:          0 :                 if (tolower(p[0]) == tolower(t[0])) {
    1000         [ #  # ]:          0 :                         if (strncasecmp ((const char *)(p - p1), (const char *)(t - p1), p1) == 0) {
    1001                 :          0 :                                 return ((char *)t - p1);
    1002                 :            :                         }
    1003                 :            :                 }
    1004                 :          0 :                 j = delta[tolower(t[0])];
    1005         [ #  # ]:          0 :                 if (i < j)
    1006                 :            :                         break;
    1007                 :          0 :                 i -= j;
    1008                 :          0 :                 t += j;
    1009                 :          0 :         }
    1010                 :          0 :         return (NULL);
    1011                 :            : }
    1012                 :            : 
    1013                 :            : /*
    1014                 :            :  * bmstrcasestr() -- case-insensitive substring search
    1015                 :            :  *
    1016                 :            :  * This uses the Boyer-Moore search algorithm and is therefore quite fast.
    1017                 :            :  * The code is roughly based on the strstr() replacement from 'tin' written
    1018                 :            :  * by Urs Jannsen.
    1019                 :            :  */
    1020                 :          0 : const char *cbmstrcasestr(const char *text, const char *pattern) {
    1021                 :            :         size_t textlen;
    1022                 :            :         size_t patlen;
    1023                 :            : 
    1024         [ #  # ]:          0 :         if (!text) return(NULL);
    1025         [ #  # ]:          0 :         if (!pattern) return(NULL);
    1026                 :            : 
    1027                 :          0 :         textlen = strlen (text);
    1028                 :          0 :         patlen = strlen (pattern);
    1029                 :            : 
    1030                 :          0 :         return _cbmstrcasestr_len(text, textlen, pattern, patlen);
    1031                 :            : }
    1032                 :            : 
    1033                 :          0 : const char *cbmstrcasestr_len(const char *text, size_t textlen, const char *pattern, size_t patlen) {
    1034                 :          0 :         return _cbmstrcasestr_len(text, textlen, pattern, patlen);
    1035                 :            : }
    1036                 :            : 
    1037                 :            : /*
    1038                 :            :  * Local replacement for controversial C library function that generates
    1039                 :            :  * names for temporary files.  Included to shut up compiler warnings.
    1040                 :            :  */
    1041                 :          0 : void CtdlMakeTempFileName(char *name, int len) {
    1042                 :          0 :         int i = 0;
    1043                 :            : 
    1044         [ #  # ]:          0 :         while (i++, i < 100) {
    1045                 :          0 :                 snprintf(name, len, "/tmp/ctdl.%04lx.%04x",
    1046                 :            :                         (long)getpid(),
    1047                 :            :                         rand()
    1048                 :            :                 );
    1049         [ #  # ]:          0 :                 if (!access(name, F_OK)) {
    1050                 :          0 :                         return;
    1051                 :            :                 }
    1052                 :            :         }
    1053                 :            : }
    1054                 :            : 
    1055                 :            : 
    1056                 :            : 
    1057                 :            : /*
    1058                 :            :  * Determine whether the specified message number is contained within the specified set.
    1059                 :            :  * Returns nonzero if the specified message number is in the specified message set string.
    1060                 :            :  */
    1061                 :          0 : int is_msg_in_mset(const char *mset, long msgnum) {
    1062                 :            :         int num_sets;
    1063                 :            :         int s;
    1064                 :            :         char setstr[SIZ], lostr[SIZ], histr[SIZ];       /* was 1024 */
    1065                 :            :         long lo, hi;
    1066                 :            : 
    1067                 :            :         /*
    1068                 :            :          * Now set it for all specified messages.
    1069                 :            :          */
    1070                 :          0 :         num_sets = num_tokens(mset, ',');
    1071         [ #  # ]:          0 :         for (s=0; s<num_sets; ++s) {
    1072                 :          0 :                 extract_token(setstr, mset, s, ',', sizeof setstr);
    1073                 :            : 
    1074                 :          0 :                 extract_token(lostr, setstr, 0, ':', sizeof lostr);
    1075         [ #  # ]:          0 :                 if (num_tokens(setstr, ':') >= 2) {
    1076                 :          0 :                         extract_token(histr, setstr, 1, ':', sizeof histr);
    1077         [ #  # ]:          0 :                         if (!strcmp(histr, "*")) {
    1078                 :          0 :                                 snprintf(histr, sizeof histr, "%ld", LONG_MAX);
    1079                 :            :                         }
    1080                 :            :                 }
    1081                 :            :                 else {
    1082                 :          0 :                         strcpy(histr, lostr);
    1083                 :            :                 }
    1084                 :          0 :                 lo = atol(lostr);
    1085                 :          0 :                 hi = atol(histr);
    1086                 :            : 
    1087   [ #  #  #  # ]:          0 :                 if ((msgnum >= lo) && (msgnum <= hi)) return(1);
    1088                 :            :         }
    1089                 :            : 
    1090                 :          0 :         return(0);
    1091                 :            : }
    1092                 :            : 
    1093                 :            : 
    1094                 :            : /*
    1095                 :            :  * searches for a pattern within a search string
    1096                 :            :  * returns position in string
    1097                 :            :  */
    1098                 :          0 : int pattern2(char *search, char *patn)
    1099                 :            : {
    1100                 :            :         int a;
    1101                 :            :         int len, plen;
    1102                 :          0 :         len = strlen (search);
    1103                 :          0 :         plen = strlen (patn);
    1104         [ #  # ]:          0 :         for (a = 0; a < len; ++a) {
    1105         [ #  # ]:          0 :                 if (!strncasecmp(&search[a], patn, plen))
    1106                 :          0 :                         return (a);
    1107                 :            :         }
    1108                 :          0 :         return (-1);
    1109                 :            : }
    1110                 :            : 
    1111                 :            : 
    1112                 :            : /*
    1113                 :            :  * Strip leading and trailing spaces from a string; with premeasured and adjusted length.
    1114                 :            :  * buf - the string to modify
    1115                 :            :  * len - length of the string. 
    1116                 :            :  */
    1117                 :          0 : void stripltlen(char *buf, int *len)
    1118                 :            : {
    1119                 :          0 :         int delta = 0;
    1120         [ #  # ]:          0 :         if (*len == 0) return;
    1121 [ #  # ][ #  # ]:          0 :         while ((*len > delta) && (isspace(buf[delta]))){
    1122                 :          0 :                 delta ++;
    1123                 :            :         }
    1124                 :          0 :         memmove (buf, &buf[delta], *len - delta + 1);
    1125                 :          0 :         (*len) -=delta;
    1126                 :            : 
    1127         [ #  # ]:          0 :         if (*len == 0) return;
    1128         [ #  # ]:          0 :         while (isspace(buf[(*len) - 1])){
    1129                 :          0 :                 buf[--(*len)] = '\0';
    1130                 :            :         }
    1131                 :            : }
    1132                 :            : 
    1133                 :            : 
    1134                 :            : /*
    1135                 :            :  * Convert all whitespace characters in a supplied string to underscores
    1136                 :            :  */
    1137                 :          0 : void convert_spaces_to_underscores(char *str)
    1138                 :            : {
    1139                 :            :         int len;
    1140                 :            :         int i;
    1141                 :            : 
    1142         [ #  # ]:          0 :         if (!str) return;
    1143                 :            : 
    1144                 :          0 :         len = strlen(str);
    1145         [ #  # ]:          0 :         for (i=0; i<len; ++i) {
    1146         [ #  # ]:          0 :                 if (isspace(str[i])) {
    1147                 :          0 :                         str[i] = '_';
    1148                 :            :                 }
    1149                 :            :         }
    1150                 :            : }
    1151                 :            : 
    1152                 :            : 
    1153                 :            : /*
    1154                 :            :  * check whether the provided string needs to be qp encoded or not
    1155                 :            :  */
    1156                 :          0 : int CheckEncode(const char *pch, long len, const char *pche)
    1157                 :            : {
    1158         [ #  # ]:          0 :         if (pche == NULL)
    1159                 :          0 :                 pche = pch + len;
    1160         [ #  # ]:          0 :         while (pch < pche) {
    1161 [ #  # ][ #  # ]:          0 :                 if (((unsigned char) *pch < 32) || 
    1162                 :          0 :                     ((unsigned char) *pch > 126)) {
    1163                 :          0 :                         return 1;
    1164                 :            :                 }
    1165                 :          0 :                 pch++;
    1166                 :            :         }
    1167                 :          0 :         return 0;
    1168                 :            : }
    1169                 :            : 

Generated by: LCOV version 1.8