X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Ftools.c;h=f83a7d863bf60360d99fef3fe986a869b48a1909;hb=6ea3e52ceedf0dc7ab13d2e48987822eee61e8ee;hp=86fd68ec1e351f47eeddf8fc8e98fac886f32478;hpb=227c92b79dbb6aed6e4e0e045e4f2f63f77a7f2e;p=citadel.git diff --git a/webcit/tools.c b/webcit/tools.c index 86fd68ec1..f83a7d863 100644 --- a/webcit/tools.c +++ b/webcit/tools.c @@ -1,48 +1,30 @@ /* * $Id$ - * - * Miscellaneous routines + */ +/** + * \defgroup MiscRout Miscellaneous routines + * \ingroup tools */ -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#ifdef HAVE_FCNTL_H -#include -#endif -#include -#include -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_LIMITS_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include +/*@{*/ #include "webcit.h" #include "webserver.h" -typedef unsigned char byte; +typedef unsigned char byte; /**< byte data type */ -#define FALSE 0 -#define TRUE 1 +#define FALSE 0 /**< no. */ +#define TRUE 1 /**< yes. */ -static byte dtable[256]; /* base64 encode / decode table */ +static byte dtable[256]; /**< base64 encode / decode table */ +/** + * \brief sanitize strncopy. + * \param dest destination string + * \param src source string + * \param n length of source to copy + * \return result string + */ char *safestrncpy(char *dest, const char *src, size_t n) { if (dest == NULL || src == NULL) { @@ -55,65 +37,79 @@ char *safestrncpy(char *dest, const char *src, size_t n) -/* - * num_tokens() - discover number of parameters/tokens in a string +/** + * \brief discover number of parameters/tokens in a string + * \param source string to inspect + * \param tok seperation token + * \return number of tokenized parts found */ int num_tokens(char *source, char tok) { - int a; int count = 1; + char *ptr = source; - if (source == NULL) + if (source == NULL) { return (0); - for (a = 0; a < strlen(source); ++a) { - if (source[a] == tok) + } + + while (*ptr != '\0') { + if (*ptr++ == tok) { ++count; + } } + return (count); } /* * extract_token() - a string tokenizer + * returns -1 if not found, or length of token. */ -void extract_token(char *dest, const char *source, int parmnum, char separator, int maxlen) +long extract_token(char *dest, const char *source, int parmnum, char separator, int maxlen) { - char *d; /* dest */ - const char *s; /* source */ - int count = 0; - int len = 0; + const char *s; /* source */ + int len = 0; /* running total length of extracted string */ + int current_token = 0; /* token currently being processed */ + + s = source; + + if (dest == NULL) { + return(-1); + } dest[0] = 0; - /* Locate desired parameter */ - s = source; - while (count < parmnum) { - /* End of string, bail! */ - if (!*s) { - s = NULL; - break; - } + if (s == NULL) { + return(-1); + } + + while (*s) { if (*s == separator) { - count++; + ++current_token; + } + else if ( (current_token == parmnum) && (len < maxlen) ) { + dest[len] = *s; + ++len; } - s++; + ++s; } - if (!s) return; /* Parameter not found */ - for (d = dest; *s && *s != separator && ++len delta) && (isspace(buf[delta]))){ + delta ++; + } + memmove (buf, &buf[delta], *len - delta + 1); + (*len) -=delta; + + if (*len == 0) return; + while (isspace(buf[(*len) - 1])){ + buf[--(*len)] = '\0'; + } +} + +/** + * \brief Strip leading and trailing spaces from a string + * \param buf the string to modify */ void striplt(char *buf) { - if (strlen(buf) == 0) return; - while ((strlen(buf) > 0) && (isspace(buf[0]))) - strcpy(buf, &buf[1]); - if (strlen(buf) == 0) return; - while (isspace(buf[strlen(buf) - 1])) - buf[strlen(buf) - 1] = 0; + int len; + len = strlen(buf); + stripltlen(buf, &len); } -/* - * Determine whether the specified message number is contained within the +/** + * \brief Determine whether the specified message number is contained within the * specified set. + * + * \param mset Message set string + * \param msgnum Message number we are looking for + * + * \return Nonzero if the specified message number is in the specified message set string. */ int is_msg_in_mset(char *mset, long msgnum) { int num_sets; @@ -286,23 +325,28 @@ int is_msg_in_mset(char *mset, long msgnum) { -/* - * Strip a boundarized substring out of a string (for example, remove +/** + * \brief Strip a boundarized substring out of a string + * (for example, remove * parentheses and anything inside them). * * This improved version can strip out *multiple* boundarized substrings. + * \param str the string to process + * \param leftboundary the boundary character on the left side of the target string + * \param rightboundary the boundary character on the right side of the target string */ void stripout(char *str, char leftboundary, char rightboundary) { int a; int lb = (-1); int rb = (-1); + int len = strlen(str); do { lb = (-1); rb = (-1); - for (a = 0; a < strlen(str); ++a) { + for (a = 0; a < len; ++a) { if (str[a] == leftboundary) lb = a; if (str[a] == rightboundary) @@ -310,7 +354,8 @@ void stripout(char *str, char leftboundary, char rightboundary) } if ((lb > 0) && (rb > lb)) { - strcpy(&str[lb - 1], &str[rb + 1]); + memmove(&str[lb - 1], &str[rb + 1], len - rb); + len -= (rb - lb + 2); } } while ((lb > 0) && (rb > lb)); @@ -319,8 +364,9 @@ void stripout(char *str, char leftboundary, char rightboundary) -/* - * Replacement for sleep() that uses select() in order to avoid SIGALRM +/** + * \brief Replacement for sleep() that uses select() in order to avoid SIGALRM + * \param seconds how many seconds should we sleep? */ void sleeeeeeeeeep(int seconds) { @@ -333,19 +379,23 @@ void sleeeeeeeeeep(int seconds) -/* +/** + * \brief encode a string into base64 to for example tunnel it through mail transport * CtdlDecodeBase64() and CtdlEncodeBase64() are adaptations of code by * John Walker, copied over from the Citadel server. + * \param dest encrypted string + * \param source the string to encrypt + * \param sourcelen the length of the source data (may contain string terminators) */ -void CtdlEncodeBase64(char *dest, const char *source, size_t sourcelen) +void CtdlEncodeBase64(char *dest, const char *source, size_t sourcelen, int linebreaks) { int i, hiteof = FALSE; int spos = 0; int dpos = 0; int thisline = 0; - /* Fill dtable with character encodings. */ + /** Fill dtable with character encodings. */ for (i = 0; i < 26; i++) { dtable[i] = 'A' + i; @@ -380,9 +430,11 @@ void CtdlEncodeBase64(char *dest, const char *source, size_t sourcelen) (igroup[2] >> 6)]; ogroup[3] = dtable[igroup[2] & 0x3F]; - /* Replace characters in output stream with "=" pad - characters if fewer than three characters were - read from the end of the input stream. */ + /** + * Replace characters in output stream with "=" pad + * characters if fewer than three characters were + * read from the end of the input stream. + */ if (n < 3) { ogroup[3] = '='; @@ -395,7 +447,7 @@ void CtdlEncodeBase64(char *dest, const char *source, size_t sourcelen) dest[dpos] = 0; } thisline += 4; - if (thisline > 70) { + if ( (linebreaks) && (thisline > 70) ) { dest[dpos++] = '\r'; dest[dpos++] = '\n'; dest[dpos] = 0; @@ -403,7 +455,7 @@ void CtdlEncodeBase64(char *dest, const char *source, size_t sourcelen) } } } - if (thisline > 70) { + if ( (linebreaks) && (thisline > 70) ) { dest[dpos++] = '\r'; dest[dpos++] = '\n'; dest[dpos] = 0; @@ -412,9 +464,14 @@ void CtdlEncodeBase64(char *dest, const char *source, size_t sourcelen) } -/* - * Convert base64-encoded to binary. Returns the length of the decoded data. +/** + * \brief Convert base64-encoded to binary. * It will stop after reading 'length' bytes. + * + * \param dest The destination buffer + * \param source The base64 data to be decoded. + * \param length The number of bytes to decode. + * \return The actual length of the decoded data. */ int CtdlDecodeBase64(char *dest, const char *source, size_t length) { @@ -438,7 +495,7 @@ int CtdlDecodeBase64(char *dest, const char *source, size_t length) dtable['/'] = 63; dtable['='] = 0; - /*CONSTANTCONDITION*/ while (TRUE) { + /**CONSTANTCONDITION*/ while (TRUE) { byte a[4], b[4], o[3]; for (i = 0; i < 4; i++) { @@ -454,7 +511,7 @@ int CtdlDecodeBase64(char *dest, const char *source, size_t length) return (dpos); } if (dtable[c] & 0x80) { - /* Ignoring errors: discard invalid character */ + /** Ignoring errors: discard invalid character */ i--; continue; } @@ -480,17 +537,111 @@ int CtdlDecodeBase64(char *dest, const char *source, size_t length) -/* - * Generate a new, globally unique UID parameter for a calendar etc. object +/** + * \brief Generate a new, globally unique UID parameter for a calendar etc. object + * + * \param buf String buffer into which our newly created UUID should be placed */ void generate_uuid(char *buf) { static int seq = 0; - sprintf(buf, "%s-%lx-%x-%x", + sprintf(buf, "%s-%lx-%lx-%x", serv_info.serv_nodename, (long)time(NULL), - getpid(), + (long)getpid(), (seq++) ); } + +/** + * \brief Local replacement for controversial C library function that generates + * names for temporary files. Included to shut up compiler warnings. + * \todo return a fd to the file instead of the name for security reasons + * \param name the created filename + * \param len the length of the filename + */ +void CtdlMakeTempFileName(char *name, int len) { + int i = 0; + + while (i++, i < 100) { + snprintf(name, len, "/tmp/ctdl.%04x.%04x", + getpid(), + rand() + ); + if (!access(name, F_OK)) { + return; + } + } +} + + + +/* + * \brief case-insensitive substring search + * + * This uses the Boyer-Moore search algorithm and is therefore quite fast. + * The code is roughly based on the strstr() replacement from 'tin' written + * by Urs Jannsen. + * + * \param text String to be searched + * \param pattern String to search for + */ +char *bmstrcasestr(char *text, char *pattern) { + + register unsigned char *p, *t; + register int i, j, *delta; + register size_t p1; + int deltaspace[256]; + size_t textlen; + size_t patlen; + + textlen = strlen (text); + patlen = strlen (pattern); + + /* algorithm fails if pattern is empty */ + if ((p1 = patlen) == 0) + return (text); + + /* code below fails (whenever i is unsigned) if pattern too long */ + if (p1 > textlen) + return (NULL); + + /* set up deltas */ + delta = deltaspace; + for (i = 0; i <= 255; i++) + delta[i] = p1; + for (p = (unsigned char *) pattern, i = p1; --i > 0;) + delta[tolower(*p++)] = i; + + /* + * From now on, we want patlen - 1. + * In the loop below, p points to the end of the pattern, + * t points to the end of the text to be tested against the + * pattern, and i counts the amount of text remaining, not + * including the part to be tested. + */ + p1--; + p = (unsigned char *) pattern + p1; + t = (unsigned char *) text + p1; + i = textlen - patlen; + while(1) { + if (tolower(p[0]) == tolower(t[0])) { + if (strncasecmp ((const char *)(p - p1), (const char *)(t - p1), p1) == 0) { + return ((char *)t - p1); + } + } + j = delta[tolower(t[0])]; + if (i < j) + break; + i -= j; + t += j; + } + return (NULL); +} + + + + + +/*@}*/