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;
257 size_t newused = Offset + nWritten;
259 while (newused >= Buf->BufSize) {
260 nWritten = vsnprintf(Buf->buf + Offset,
261 Buf->BufSize - Offset,
263 newused = Offset + nWritten;
264 if (newused >= Buf->BufSize)
265 IncreaseBuf(Buf, 1, 0);
267 Buf->BufUsed = Offset + nWritten ;
272 void StrBufPrintf(StrBuf *Buf, const char *format, ...)
274 size_t nWritten = Buf->BufSize + 1;
277 while (nWritten >= Buf->BufSize) {
278 va_start(arg_ptr, format);
279 nWritten = vsnprintf(Buf->buf, Buf->BufSize, format, arg_ptr);
281 Buf->BufUsed = nWritten ;
282 if (nWritten >= Buf->BufSize)
283 IncreaseBuf(Buf, 0, 0);
289 * \brief a string tokenizer
290 * \param dest Destination StringBuffer
291 * \param Source StringBuffer to read into
292 * \param separator tokenizer param
293 * \returns -1 if not found, else length of token.
295 int StrBufExtract_token(StrBuf *dest, const StrBuf *Source, int parmnum, char separator)
297 const char *s, *e; //* source * /
298 int len = 0; //* running total length of extracted string * /
299 int current_token = 0; //* token currently being processed * /
301 if ((Source == NULL) || (Source->BufUsed ==0)) {
305 e = s + Source->BufUsed;
311 //lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
315 while ((s<e) && !IsEmptyStr(s)) {
316 if (*s == separator) {
319 if (len >= dest->BufSize)
320 if (!IncreaseBuf(dest, 1, -1))
322 if ( (current_token == parmnum) &&
327 else if (current_token > parmnum) {
333 dest->buf[len] = '\0';
336 if (current_token < parmnum) {
337 //lprintf (CTDL_DEBUG,"test <!: %s\n", dest);
340 //lprintf (CTDL_DEBUG,"test <: %d; %s\n", len, dest);
346 * extract_int() - extract an int parm w/o supplying a buffer
348 int StrBufExtract_int(const StrBuf* Source, int parmnum, char separator)
357 if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0)
364 * extract_long() - extract an long parm w/o supplying a buffer
366 long StrBufExtract_long(const StrBuf* Source, int parmnum, char separator)
375 if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0)
383 * extract_unsigned_long() - extract an unsigned long parm
385 unsigned long StrBufExtract_unsigned_long(const StrBuf* Source, int parmnum, char separator)
394 if (StrBufExtract_token(&tmp, Source, parmnum, separator) > 0)
403 * \brief Input binary data from socket
404 * \param buf the buffer to get the input to
405 * \param bytes the maximal number of bytes to read
407 int StrBufTCP_read_line(StrBuf *buf, int *fd, int append, const char **Error)
414 slen = len = buf->BufUsed;
416 rlen = read(*fd, &buf->buf[len], 1);
418 *Error = strerror(errno);
425 if (buf->buf[len] == '\n')
427 if (buf->buf[len] != '\r')
429 if (!(len < buf->BufSize)) {
431 buf->buf[len+1] = '\0';
432 IncreaseBuf(buf, 1, -1);
436 buf->buf[len] = '\0';
441 * \brief Input binary data from socket
442 * \param buf the buffer to get the input to
443 * \param bytes the maximal number of bytes to read
445 int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **Error)
453 if ((Buf == NULL) || (*fd == -1))
457 if (Buf->BufUsed + nBytes > Buf->BufSize)
458 IncreaseBuf(Buf, 1, Buf->BufUsed + nBytes);
460 ptr = Buf->buf + Buf->BufUsed;
462 slen = len = Buf->BufUsed;
464 fdflags = fcntl(*fd, F_GETFL);
466 while (nRead < nBytes) {
467 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
470 if (select(*fd + 1, NULL, &wset, NULL, NULL) == -1) {
471 *Error = strerror(errno);
476 if ((rlen = read(*fd,
478 nBytes - nRead)) == -1) {
481 *Error = strerror(errno);
485 Buf->BufUsed += rlen;
487 Buf->buf[Buf->BufUsed] = '\0';
491 void StrBufCutLeft(StrBuf *Buf, int nChars)
493 if (nChars >= Buf->BufUsed) {
497 memmove(Buf->buf, Buf->buf + nChars, Buf->BufUsed - nChars);
498 Buf->BufUsed -= nChars;
499 Buf->buf[Buf->BufUsed] = '\0';
502 void StrBufCutRight(StrBuf *Buf, int nChars)
504 if (nChars >= Buf->BufUsed) {
508 Buf->BufUsed -= nChars;
509 Buf->buf[Buf->BufUsed] = '\0';
514 * string conversion function
516 void StrBufEUid_unescapize(StrBuf *target, StrBuf *source)
524 if (source == NULL ||target == NULL)
529 len = source->BufUsed;
530 for (a = 0; a < len; ++a) {
531 if (target->BufUsed >= target->BufSize)
532 IncreaseBuf(target, 1, -1);
534 if (source->buf[a] == '=') {
535 hex[0] = source->buf[a + 1];
536 hex[1] = source->buf[a + 2];
539 sscanf(hex, "%02x", &b);
540 target->buf[target->BufUsed] = b;
541 target->buf[++target->BufUsed] = 0;
545 target->buf[target->BufUsed] = source->buf[a];
546 target->buf[++target->BufUsed] = 0;
553 * string conversion function
555 void StrBufEUid_escapize(StrBuf *target, StrBuf *source)
562 if (source == NULL ||target == NULL)
567 len = source->BufUsed;
568 for (i=0; i<len; ++i) {
569 if (target->BufUsed + 4 >= target->BufSize)
570 IncreaseBuf(target, 1, -1);
571 if ( (isalnum(source->buf[i])) ||
572 (source->buf[i]=='-') ||
573 (source->buf[i]=='_') ) {
574 target->buf[target->BufUsed++] = source->buf[i];
577 sprintf(&target->buf[target->BufUsed],
579 (0xFF &source->buf[i]));
580 target->BufUsed += 3;
583 target->buf[target->BufUsed + 1] = '\0';
587 * \brief uses the same calling syntax as compress2(), but it
588 * creates a stream compatible with HTTP "Content-encoding: gzip"
591 #define DEF_MEM_LEVEL 8 /*< memlevel??? */
592 #define OS_CODE 0x03 /*< unix */
593 int ZEXPORT compress_gzip(Bytef * dest, /*< compressed buffer*/
594 size_t * destLen, /*< length of the compresed data */
595 const Bytef * source, /*< source to encode */
596 uLong sourceLen, /*< length of source to encode */
597 int level) /*< compression level */
599 const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */
601 /* write gzip header */
602 snprintf((char *) dest, *destLen,
603 "%c%c%c%c%c%c%c%c%c%c",
604 gz_magic[0], gz_magic[1], Z_DEFLATED,
605 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /* xflags */ ,
611 stream.next_in = (Bytef *) source;
612 stream.avail_in = (uInt) sourceLen;
613 stream.next_out = dest + 10L; // after header
614 stream.avail_out = (uInt) * destLen;
615 if ((uLong) stream.avail_out != *destLen)
618 stream.zalloc = (alloc_func) 0;
619 stream.zfree = (free_func) 0;
620 stream.opaque = (voidpf) 0;
622 err = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS,
623 DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
627 err = deflate(&stream, Z_FINISH);
628 if (err != Z_STREAM_END) {
630 return err == Z_OK ? Z_BUF_ERROR : err;
632 *destLen = stream.total_out + 10L;
634 /* write CRC and Length */
635 uLong crc = crc32(0L, source, sourceLen);
637 for (n = 0; n < 4; ++n, ++*destLen) {
638 dest[*destLen] = (int) (crc & 0xff);
641 uLong len = stream.total_in;
642 for (n = 0; n < 4; ++n, ++*destLen) {
643 dest[*destLen] = (int) (len & 0xff);
646 err = deflateEnd(&stream);
653 * Attention! If you feed this a Const String, you must maintain the uncompressed buffer yourself!
655 int CompressBuffer(StrBuf *Buf)
658 char *compressed_data = NULL;
659 size_t compressed_len, bufsize;
661 bufsize = compressed_len = ((Buf->BufUsed * 101) / 100) + 100;
662 compressed_data = malloc(compressed_len);
664 if (compress_gzip((Bytef *) compressed_data,
667 (uLongf) Buf->BufUsed, Z_BEST_SPEED) == Z_OK) {
670 Buf->buf = compressed_data;
671 Buf->BufUsed = compressed_len;
672 Buf->BufSize = bufsize;
675 free(compressed_data);
677 #endif /* HAVE_ZLIB */
681 int StrBufDecodeBase64(StrBuf *Buf)
685 if (Buf == NULL) return -1;
687 xferbuf = (char*) malloc(Buf->BufSize);
688 siz = CtdlDecodeBase64(xferbuf,