7 #include <sys/select.h>
9 #define SHOW_ME_VAPPEND_PRINTF
11 #include "libcitadel.h"
22 inline const char *ChrPtr(StrBuf *Str)
29 inline int StrLength(StrBuf *Str)
31 return (Str != NULL) ? Str->BufUsed : 0;
34 StrBuf* NewStrBuf(void)
38 NewBuf = (StrBuf*) malloc(sizeof(StrBuf));
39 NewBuf->buf = (char*) malloc(SIZ);
40 NewBuf->buf[0] = '\0';
41 NewBuf->BufSize = SIZ;
48 StrBuf* NewStrBufPlain(const char* ptr, int nChars)
54 NewBuf = (StrBuf*) malloc(sizeof(StrBuf));
56 CopySize = strlen((ptr != NULL)?ptr:"");
60 while (Siz <= CopySize)
63 NewBuf->buf = (char*) malloc(Siz);
64 NewBuf->BufSize = Siz;
66 memcpy(NewBuf->buf, ptr, CopySize);
67 NewBuf->buf[CopySize] = '\0';
68 NewBuf->BufUsed = CopySize;
71 NewBuf->buf[0] = '\0';
79 StrBuf* _NewConstStrBuf(const char* StringConstant, size_t SizeOfStrConstant)
83 NewBuf = (StrBuf*) malloc(sizeof(StrBuf));
84 NewBuf->buf = (char*) StringConstant;
85 NewBuf->BufSize = SizeOfStrConstant;
86 NewBuf->BufUsed = SizeOfStrConstant;
92 static int IncreaseBuf(StrBuf *Buf, int KeepOriginal, int DestSize)
95 size_t NewSize = Buf->BufSize * 2;
101 while (NewSize < DestSize)
104 NewBuf= (char*) malloc(NewSize);
107 memcpy(NewBuf, Buf->buf, Buf->BufUsed);
120 int FlushStrBuf(StrBuf *buf)
129 void FreeStrBuf (StrBuf **FreeMe)
133 if (!(*FreeMe)->ConstBuf)
134 free((*FreeMe)->buf);
139 void HFreeStrBuf (void *VFreeMe)
141 StrBuf *FreeMe = (StrBuf*)VFreeMe;
144 if (!FreeMe->ConstBuf)
149 long StrTol(StrBuf *Buf)
152 return atol(Buf->buf);
157 int StrBufPlain(StrBuf *Buf, const char* ptr, int nChars)
159 size_t Siz = Buf->BufSize;
163 CopySize = strlen(ptr);
167 while (Siz <= CopySize)
170 if (Siz != Buf->BufSize)
171 IncreaseBuf(Buf, 0, Siz);
172 memcpy(Buf->buf, ptr, CopySize);
173 Buf->buf[CopySize] = '\0';
174 Buf->BufUsed = CopySize;
179 void StrBufAppendBuf(StrBuf *Buf, StrBuf *AppendBuf, size_t Offset)
181 if ((AppendBuf == NULL) || (Buf == NULL))
184 if (Buf->BufSize - Offset < AppendBuf->BufUsed + Buf->BufUsed)
187 AppendBuf->BufUsed + Buf->BufUsed);
189 memcpy(Buf->buf + Buf->BufUsed,
190 AppendBuf->buf + Offset,
191 AppendBuf->BufUsed - Offset);
192 Buf->BufUsed += AppendBuf->BufUsed - Offset;
193 Buf->buf[Buf->BufUsed] = '\0';
197 void StrBufAppendBufPlain(StrBuf *Buf, const char *AppendBuf, long AppendSize, size_t Offset)
201 if ((AppendBuf == NULL) || (Buf == NULL))
205 aps = strlen(AppendBuf + Offset);
207 aps = AppendSize - Offset;
209 if (Buf->BufSize < Buf->BufUsed + aps)
210 IncreaseBuf(Buf, (Buf->BufUsed > 0), Buf->BufUsed + aps);
212 memcpy(Buf->buf + Buf->BufUsed,
216 Buf->buf[Buf->BufUsed] = '\0';
220 inline int StrBufNum_tokens(const StrBuf *source, char tok)
222 return num_tokens(source->buf, tok);
226 int StrBufSub(StrBuf *dest, const StrBuf *Source, size_t Offset, size_t nChars)
229 if (Offset > Source->BufUsed)
234 if (Offset + nChars < Source->BufUsed)
236 if (nChars > dest->BufSize)
237 IncreaseBuf(dest, 0, nChars + 1);
238 memcpy(dest->buf, Source->buf + Offset, nChars);
239 dest->BufUsed = nChars;
240 dest->buf[dest->BufUsed] = '\0';
243 NCharsRemain = Source->BufUsed - Offset;
244 if (NCharsRemain > dest->BufSize)
245 IncreaseBuf(dest, 0, NCharsRemain + 1);
246 memcpy(dest->buf, Source->buf + Offset, NCharsRemain);
247 dest->BufUsed = NCharsRemain;
248 dest->buf[dest->BufUsed] = '\0';
253 void StrBufVAppendPrintf(StrBuf *Buf, const char *format, va_list ap)
255 size_t nWritten = Buf->BufSize + 1;
256 size_t Offset = Buf->BufUsed;
258 while (Offset + nWritten >= Buf->BufSize) {
259 nWritten = vsnprintf(Buf->buf + Offset,
260 Buf->BufSize - Offset,
262 Buf->BufUsed = Offset + nWritten ;
263 if (nWritten >= Buf->BufSize)
264 IncreaseBuf(Buf, 0, 0);
268 void StrBufPrintf(StrBuf *Buf, const char *format, ...)
270 size_t nWritten = Buf->BufSize + 1;
273 while (nWritten >= Buf->BufSize) {
274 va_start(arg_ptr, format);
275 nWritten = vsnprintf(Buf->buf, Buf->BufSize, format, arg_ptr);
277 Buf->BufUsed = nWritten ;
278 if (nWritten >= Buf->BufSize)
279 IncreaseBuf(Buf, 0, 0);
285 * \brief a string tokenizer
286 * \param dest Destination StringBuffer
287 * \param Source StringBuffer to read into
288 * \param separator tokenizer param
289 * \returns -1 if not found, else length of token.
291 int StrBufExtract_token(StrBuf *dest, const StrBuf *Source, int parmnum, char separator)
293 const char *s, *e; //* source * /
294 int len = 0; //* running total length of extracted string * /
295 int current_token = 0; //* token currently being processed * /
297 if ((Source == NULL) || (Source->BufUsed ==0)) {
301 e = s + Source->BufUsed;
307 //lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
311 while ((s<e) && !IsEmptyStr(s)) {
312 if (*s == separator) {
315 if (len >= dest->BufSize)
316 if (!IncreaseBuf(dest, 1, -1))
318 if ( (current_token == parmnum) &&
323 else if (current_token > parmnum) {
329 dest->buf[len] = '\0';
332 if (current_token < parmnum) {
333 //lprintf (CTDL_DEBUG,"test <!: %s\n", dest);
336 //lprintf (CTDL_DEBUG,"test <: %d; %s\n", len, dest);
342 * extract_int() - extract an int parm w/o supplying a buffer
344 int StrBufExtract_int(const StrBuf* Source, int parmnum, char separator)
353 if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0)
360 * extract_long() - extract an long parm w/o supplying a buffer
362 long StrBufExtract_long(const StrBuf* Source, int parmnum, char separator)
371 if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0)
379 * extract_unsigned_long() - extract an unsigned long parm
381 unsigned long StrBufExtract_unsigned_long(const StrBuf* Source, int parmnum, char separator)
390 if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0)
399 * \brief Input binary data from socket
400 * \param buf the buffer to get the input to
401 * \param bytes the maximal number of bytes to read
403 int StrBufTCP_read_line(StrBuf *buf, int *fd, int append, const char **Error)
410 slen = len = buf->BufUsed;
412 rlen = read(*fd, &buf->buf[len], 1);
414 *Error = strerror(errno);
421 if (buf->buf[len] == '\n')
423 if (buf->buf[len] != '\r')
425 if (!(len < buf->BufSize)) {
427 buf->buf[len+1] = '\0';
428 IncreaseBuf(buf, 1, -1);
432 buf->buf[len] = '\0';
437 * \brief Input binary data from socket
438 * \param buf the buffer to get the input to
439 * \param bytes the maximal number of bytes to read
441 int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **Error)
449 if ((Buf == NULL) || (*fd == -1))
453 if (Buf->BufUsed + nBytes > Buf->BufSize)
454 IncreaseBuf(Buf, 1, Buf->BufUsed + nBytes);
456 ptr = Buf->buf + Buf->BufUsed;
458 slen = len = Buf->BufUsed;
460 fdflags = fcntl(*fd, F_GETFL);
462 while (nRead < nBytes) {
463 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
466 if (select(*fd + 1, NULL, &wset, NULL, NULL) == -1) {
467 *Error = strerror(errno);
472 if ((rlen = read(*fd,
474 nBytes - nRead)) == -1) {
477 *Error = strerror(errno);
481 Buf->BufUsed += rlen;
483 Buf->buf[Buf->BufUsed] = '\0';
487 void StrBufCutLeft(StrBuf *Buf, int nChars)
489 if (nChars >= Buf->BufUsed) {
493 memmove(Buf->buf, Buf->buf + nChars, Buf->BufUsed - nChars);
494 Buf->BufUsed -= nChars;
495 Buf->buf[Buf->BufUsed] = '\0';
498 void StrBufCutRight(StrBuf *Buf, int nChars)
500 if (nChars >= Buf->BufUsed) {
504 Buf->BufUsed -= nChars;
505 Buf->buf[Buf->BufUsed] = '\0';
510 * string conversion function
512 void StrBufEUid_unescapize(StrBuf *target, StrBuf *source)
520 if (source == NULL ||target == NULL)
525 len = source->BufUsed;
526 for (a = 0; a < len; ++a) {
527 if (target->BufUsed >= target->BufSize)
528 IncreaseBuf(target, 1, -1);
530 if (source->buf[a] == '=') {
531 hex[0] = source->buf[a + 1];
532 hex[1] = source->buf[a + 2];
535 sscanf(hex, "%02x", &b);
536 target->buf[target->BufUsed] = b;
537 target->buf[++target->BufUsed] = 0;
541 target->buf[target->BufUsed] = source->buf[a];
542 target->buf[++target->BufUsed] = 0;
549 * string conversion function
551 void StrBufEUid_escapize(StrBuf *target, StrBuf *source)
558 if (source == NULL ||target == NULL)
563 len = source->BufUsed;
564 for (i=0; i<len; ++i) {
565 if (target->BufUsed + 4 >= target->BufSize)
566 IncreaseBuf(target, 1, -1);
567 if ( (isalnum(source->buf[i])) ||
568 (source->buf[i]=='-') ||
569 (source->buf[i]=='_') ) {
570 target->buf[target->BufUsed++] = source->buf[i];
573 sprintf(&target->buf[target->BufUsed],
575 (0xFF &source->buf[i]));
576 target->BufUsed += 3;
579 target->buf[target->BufUsed + 1] = '\0';
583 * \brief uses the same calling syntax as compress2(), but it
584 * creates a stream compatible with HTTP "Content-encoding: gzip"
587 #define DEF_MEM_LEVEL 8 /*< memlevel??? */
588 #define OS_CODE 0x03 /*< unix */
589 int ZEXPORT compress_gzip(Bytef * dest, /*< compressed buffer*/
590 size_t * destLen, /*< length of the compresed data */
591 const Bytef * source, /*< source to encode */
592 uLong sourceLen, /*< length of source to encode */
593 int level) /*< compression level */
595 const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */
597 /* write gzip header */
598 snprintf((char *) dest, *destLen,
599 "%c%c%c%c%c%c%c%c%c%c",
600 gz_magic[0], gz_magic[1], Z_DEFLATED,
601 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /* xflags */ ,
607 stream.next_in = (Bytef *) source;
608 stream.avail_in = (uInt) sourceLen;
609 stream.next_out = dest + 10L; // after header
610 stream.avail_out = (uInt) * destLen;
611 if ((uLong) stream.avail_out != *destLen)
614 stream.zalloc = (alloc_func) 0;
615 stream.zfree = (free_func) 0;
616 stream.opaque = (voidpf) 0;
618 err = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS,
619 DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
623 err = deflate(&stream, Z_FINISH);
624 if (err != Z_STREAM_END) {
626 return err == Z_OK ? Z_BUF_ERROR : err;
628 *destLen = stream.total_out + 10L;
630 /* write CRC and Length */
631 uLong crc = crc32(0L, source, sourceLen);
633 for (n = 0; n < 4; ++n, ++*destLen) {
634 dest[*destLen] = (int) (crc & 0xff);
637 uLong len = stream.total_in;
638 for (n = 0; n < 4; ++n, ++*destLen) {
639 dest[*destLen] = (int) (len & 0xff);
642 err = deflateEnd(&stream);
649 * Attention! If you feed this a Const String, you must maintain the uncompressed buffer yourself!
651 int CompressBuffer(StrBuf *Buf)
654 char *compressed_data = NULL;
655 size_t compressed_len, bufsize;
657 bufsize = compressed_len = ((Buf->BufUsed * 101) / 100) + 100;
658 compressed_data = malloc(compressed_len);
660 if (compress_gzip((Bytef *) compressed_data,
663 (uLongf) Buf->BufUsed, Z_BEST_SPEED) == Z_OK) {
666 Buf->buf = compressed_data;
667 Buf->BufUsed = compressed_len;
668 Buf->BufSize = bufsize;
671 free(compressed_data);
673 #endif /* HAVE_ZLIB */
677 int StrBufDecodeBase64(StrBuf *Buf)
681 if (Buf == NULL) return -1;
683 xferbuf = (char*) malloc(Buf->BufSize);
684 siz = CtdlDecodeBase64(xferbuf,