8 #include <sys/select.h>
10 #define SHOW_ME_VAPPEND_PRINTF
12 #include "libcitadel.h"
25 int ZEXPORT
compress_gzip(Bytef
* dest
, size_t * destLen
,
26 const Bytef
* source
, uLong sourceLen
, int level
);
30 * Private Structure for the Stringbuffer
33 char *buf
; /**< the pointer to the dynamic buffer */
34 long BufSize
; /**< how many spcae do we optain */
35 long BufUsed
; /**< StNumber of Chars used excluding the trailing \0 */
36 int ConstBuf
; /**< are we just a wrapper arround a static buffer and musn't we be changed? */
41 * \Brief Cast operator to Plain String
42 * Note: if the buffer is altered by StrBuf operations, this pointer may become
43 * invalid. So don't lean on it after altering the buffer!
44 * Since this operation is considered cheap, rather call it often than risking
45 * your pointer to become invalid!
46 * \param Str the string we want to get the c-string representation for
47 * \returns the Pointer to the Content. Don't mess with it!
49 inline const char *ChrPtr(const StrBuf
*Str
)
57 * \brief since we know strlen()'s result, provide it here.
58 * \param Str the string to return the length to
59 * \returns contentlength of the buffer
61 inline int StrLength(const StrBuf
*Str
)
63 return (Str
!= NULL
) ? Str
->BufUsed
: 0;
67 * \brief local utility function to resize the buffer
68 * \param Buf the buffer whichs storage we should increase
69 * \param KeepOriginal should we copy the original buffer or just start over with a new one
70 * \param DestSize what should fit in after?
72 static int IncreaseBuf(StrBuf
*Buf
, int KeepOriginal
, int DestSize
)
75 size_t NewSize
= Buf
->BufSize
* 2;
81 while (NewSize
<= DestSize
)
84 NewBuf
= (char*) malloc(NewSize
);
85 if (KeepOriginal
&& (Buf
->BufUsed
> 0))
87 memcpy(NewBuf
, Buf
->buf
, Buf
->BufUsed
);
101 * Allocate a new buffer with default buffer size
102 * \returns the new stringbuffer
104 StrBuf
* NewStrBuf(void)
108 NewBuf
= (StrBuf
*) malloc(sizeof(StrBuf
));
109 NewBuf
->buf
= (char*) malloc(SIZ
);
110 NewBuf
->buf
[0] = '\0';
111 NewBuf
->BufSize
= SIZ
;
113 NewBuf
->ConstBuf
= 0;
118 * \brief Copy Constructor; returns a duplicate of CopyMe
119 * \params CopyMe Buffer to faxmilate
120 * \returns the new stringbuffer
122 StrBuf
* NewStrBufDup(const StrBuf
*CopyMe
)
129 NewBuf
= (StrBuf
*) malloc(sizeof(StrBuf
));
130 NewBuf
->buf
= (char*) malloc(CopyMe
->BufSize
);
131 memcpy(NewBuf
->buf
, CopyMe
->buf
, CopyMe
->BufUsed
+ 1);
132 NewBuf
->BufUsed
= CopyMe
->BufUsed
;
133 NewBuf
->BufSize
= CopyMe
->BufSize
;
134 NewBuf
->ConstBuf
= 0;
139 * \brief create a new Buffer using an existing c-string
140 * this function should also be used if you want to pre-suggest
141 * the buffer size to allocate in conjunction with ptr == NULL
142 * \param ptr the c-string to copy; may be NULL to create a blank instance
143 * \param nChars How many chars should we copy; -1 if we should measure the length ourselves
144 * \returns the new stringbuffer
146 StrBuf
* NewStrBufPlain(const char* ptr
, int nChars
)
152 NewBuf
= (StrBuf
*) malloc(sizeof(StrBuf
));
154 CopySize
= strlen((ptr
!= NULL
)?ptr
:"");
158 while (Siz
<= CopySize
)
161 NewBuf
->buf
= (char*) malloc(Siz
);
162 NewBuf
->BufSize
= Siz
;
164 memcpy(NewBuf
->buf
, ptr
, CopySize
);
165 NewBuf
->buf
[CopySize
] = '\0';
166 NewBuf
->BufUsed
= CopySize
;
169 NewBuf
->buf
[0] = '\0';
172 NewBuf
->ConstBuf
= 0;
177 * \brief Set an existing buffer from a c-string
178 * \param ptr c-string to put into
179 * \param nChars set to -1 if we should work 0-terminated
180 * \returns the new length of the string
182 int StrBufPlain(StrBuf
*Buf
, const char* ptr
, int nChars
)
184 size_t Siz
= Buf
->BufSize
;
188 CopySize
= strlen(ptr
);
192 while (Siz
<= CopySize
)
195 if (Siz
!= Buf
->BufSize
)
196 IncreaseBuf(Buf
, 0, Siz
);
197 memcpy(Buf
->buf
, ptr
, CopySize
);
198 Buf
->buf
[CopySize
] = '\0';
199 Buf
->BufUsed
= CopySize
;
206 * \brief use strbuf as wrapper for a string constant for easy handling
207 * \param StringConstant a string to wrap
208 * \param SizeOfConstant should be sizeof(StringConstant)-1
210 StrBuf
* _NewConstStrBuf(const char* StringConstant
, size_t SizeOfStrConstant
)
214 NewBuf
= (StrBuf
*) malloc(sizeof(StrBuf
));
215 NewBuf
->buf
= (char*) StringConstant
;
216 NewBuf
->BufSize
= SizeOfStrConstant
;
217 NewBuf
->BufUsed
= SizeOfStrConstant
;
218 NewBuf
->ConstBuf
= 1;
224 * \brief flush the content of a Buf; keep its struct
225 * \param buf Buffer to flush
227 int FlushStrBuf(StrBuf
*buf
)
239 * \brief Release a Buffer
240 * Its a double pointer, so it can NULL your pointer
241 * so fancy SIG11 appear instead of random results
242 * \param FreeMe Pointer Pointer to the buffer to free
244 void FreeStrBuf (StrBuf
**FreeMe
)
248 if (!(*FreeMe
)->ConstBuf
)
249 free((*FreeMe
)->buf
);
255 * \brief Release the buffer
256 * If you want put your StrBuf into a Hash, use this as Destructor.
257 * \param VFreeMe untyped pointer to a StrBuf. be shure to do the right thing [TM]
259 void HFreeStrBuf (void *VFreeMe
)
261 StrBuf
*FreeMe
= (StrBuf
*)VFreeMe
;
264 if (!FreeMe
->ConstBuf
)
270 * \brief Wrapper around atol
272 long StrTol(const StrBuf
*Buf
)
277 return atol(Buf
->buf
);
283 * \brief Wrapper around atoi
285 int StrToi(const StrBuf
*Buf
)
289 if (Buf
->BufUsed
> 0)
290 return atoi(Buf
->buf
);
295 * \brief Checks to see if the string is a pure number
297 int StrBufIsNumber(const StrBuf
*Buf
) {
302 strtoll(Buf
->buf
, &pEnd
, 10);
303 if (pEnd
== NULL
&& ((Buf
->buf
)-pEnd
) != 0) {
309 * \brief modifies a Single char of the Buf
310 * You can point to it via char* or a zero-based integer
311 * \param ptr char* to zero; use NULL if unused
312 * \param nThChar zero based pointer into the string; use -1 if unused
313 * \param PeekValue The Character to place into the position
315 long StrBufPeek(StrBuf
*Buf
, const char* ptr
, long nThChar
, char PeekValue
)
320 nThChar
= ptr
- Buf
->buf
;
321 if ((nThChar
< 0) || (nThChar
> Buf
->BufUsed
))
323 Buf
->buf
[nThChar
] = PeekValue
;
328 * \brief Append a StringBuffer to the buffer
329 * \param Buf Buffer to modify
330 * \param AppendBuf Buffer to copy at the end of our buffer
331 * \param Offset Should we start copying from an offset?
333 void StrBufAppendBuf(StrBuf
*Buf
, const StrBuf
*AppendBuf
, unsigned long Offset
)
335 if ((AppendBuf
== NULL
) || (Buf
== NULL
) || (AppendBuf
->buf
== NULL
))
338 if (Buf
->BufSize
- Offset
< AppendBuf
->BufUsed
+ Buf
->BufUsed
)
341 AppendBuf
->BufUsed
+ Buf
->BufUsed
);
343 memcpy(Buf
->buf
+ Buf
->BufUsed
,
344 AppendBuf
->buf
+ Offset
,
345 AppendBuf
->BufUsed
- Offset
);
346 Buf
->BufUsed
+= AppendBuf
->BufUsed
- Offset
;
347 Buf
->buf
[Buf
->BufUsed
] = '\0';
352 * \brief Append a C-String to the buffer
353 * \param Buf Buffer to modify
354 * \param AppendBuf Buffer to copy at the end of our buffer
355 * \param AppendSize number of bytes to copy; set to -1 if we should count it in advance
356 * \param Offset Should we start copying from an offset?
358 void StrBufAppendBufPlain(StrBuf
*Buf
, const char *AppendBuf
, long AppendSize
, unsigned long Offset
)
361 long BufSizeRequired
;
363 if ((AppendBuf
== NULL
) || (Buf
== NULL
))
367 aps
= strlen(AppendBuf
+ Offset
);
369 aps
= AppendSize
- Offset
;
371 BufSizeRequired
= Buf
->BufUsed
+ aps
+ 1;
372 if (Buf
->BufSize
<= BufSizeRequired
)
373 IncreaseBuf(Buf
, (Buf
->BufUsed
> 0), BufSizeRequired
);
375 memcpy(Buf
->buf
+ Buf
->BufUsed
,
379 Buf
->buf
[Buf
->BufUsed
] = '\0';
384 * \brief Escape a string for feeding out as a URL while appending it to a Buffer
385 * \param outbuf the output buffer
386 * \param oblen the size of outbuf to sanitize
387 * \param strbuf the input buffer
389 void StrBufUrlescAppend(StrBuf
*OutBuf
, const StrBuf
*In
, const char *PlainIn
)
391 const char *pch
, *pche
;
394 const char ec
[] = " +#&;`'|*?-~<>^()[]{}/$\"\\";
395 int eclen
= sizeof(ec
) -1;
397 if (((In
== NULL
) && (PlainIn
== NULL
)) || (OutBuf
== NULL
) )
399 if (PlainIn
!= NULL
) {
400 len
= strlen(PlainIn
);
406 pche
= pch
+ In
->BufUsed
;
413 pt
= OutBuf
->buf
+ OutBuf
->BufUsed
;
414 pte
= OutBuf
->buf
+ OutBuf
->BufSize
- 4; /**< we max append 3 chars at once plus the \0 */
418 IncreaseBuf(OutBuf
, 1, -1);
419 pte
= OutBuf
->buf
+ OutBuf
->BufSize
- 4; /**< we max append 3 chars at once plus the \0 */
420 pt
= OutBuf
->buf
+ OutBuf
->BufUsed
;
424 for (b
= 0; b
< eclen
; ++b
) {
431 sprintf(pt
,"%%%02X", *pch
);
433 OutBuf
->BufUsed
+= 3;
445 * \brief Append a string, escaping characters which have meaning in HTML.
447 * \param Target target buffer
448 * \param Source source buffer; set to NULL if you just have a C-String
449 * \param PlainIn Plain-C string to append; set to NULL if unused
450 * \param nbsp If nonzero, spaces are converted to non-breaking spaces.
451 * \param nolinebreaks if set to 1, linebreaks are removed from the string.
452 * if set to 2, linebreaks are replaced by <br/>
454 long StrEscAppend(StrBuf
*Target
, const StrBuf
*Source
, const char *PlainIn
, int nbsp
, int nolinebreaks
)
456 const char *aptr
, *eiptr
;
460 if (((Source
== NULL
) && (PlainIn
== NULL
)) || (Target
== NULL
) )
463 if (PlainIn
!= NULL
) {
465 len
= strlen(PlainIn
);
470 eiptr
= aptr
+ Source
->BufUsed
;
471 len
= Source
->BufUsed
;
477 bptr
= Target
->buf
+ Target
->BufUsed
;
478 eptr
= Target
->buf
+ Target
->BufSize
- 11; /* our biggest unit to put in... */
480 while (aptr
< eiptr
){
482 IncreaseBuf(Target
, 1, -1);
483 eptr
= Target
->buf
+ Target
->BufSize
- 11; /* our biggest unit to put in... */
484 bptr
= Target
->buf
+ Target
->BufUsed
;
487 memcpy(bptr
, "<", 4);
489 Target
->BufUsed
+= 4;
491 else if (*aptr
== '>') {
492 memcpy(bptr
, ">", 4);
494 Target
->BufUsed
+= 4;
496 else if (*aptr
== '&') {
497 memcpy(bptr
, "&", 5);
499 Target
->BufUsed
+= 5;
501 else if (*aptr
== '"') {
502 memcpy(bptr
, """, 6);
504 Target
->BufUsed
+= 6;
506 else if (*aptr
== '\'') {
507 memcpy(bptr
, "'", 5);
509 Target
->BufUsed
+= 5;
511 else if (*aptr
== LB
) {
516 else if (*aptr
== RB
) {
521 else if (*aptr
== QU
) {
526 else if ((*aptr
== 32) && (nbsp
== 1)) {
527 memcpy(bptr
, " ", 6);
529 Target
->BufUsed
+= 6;
531 else if ((*aptr
== '\n') && (nolinebreaks
== 1)) {
532 *bptr
='\0'; /* nothing */
534 else if ((*aptr
== '\n') && (nolinebreaks
== 2)) {
535 memcpy(bptr
, "<br/>", 11);
537 Target
->BufUsed
+= 11;
541 else if ((*aptr
== '\r') && (nolinebreaks
!= 0)) {
542 *bptr
='\0'; /* nothing */
552 if ((bptr
= eptr
- 1 ) && !IsEmptyStr(aptr
) )
554 return Target
->BufUsed
;
558 * \brief Append a string, escaping characters which have meaning in HTML.
559 * Converts linebreaks into blanks; escapes single quotes
560 * \param Target target buffer
561 * \param Source source buffer; set to NULL if you just have a C-String
562 * \param PlainIn Plain-C string to append; set to NULL if unused
564 void StrMsgEscAppend(StrBuf
*Target
, StrBuf
*Source
, const char *PlainIn
)
566 const char *aptr
, *eiptr
;
570 if (((Source
== NULL
) && (PlainIn
== NULL
)) || (Target
== NULL
) )
573 if (PlainIn
!= NULL
) {
575 len
= strlen(PlainIn
);
580 eiptr
= aptr
+ Source
->BufUsed
;
581 len
= Source
->BufUsed
;
587 eptr
= Target
->buf
+ Target
->BufSize
- 6;
588 tptr
= Target
->buf
+ Target
->BufUsed
;
590 while (aptr
< eiptr
){
592 IncreaseBuf(Target
, 1, -1);
593 eptr
= Target
->buf
+ Target
->BufSize
- 6;
594 tptr
= Target
->buf
+ Target
->BufUsed
;
601 else if (*aptr
== '\r') {
605 else if (*aptr
== '\'') {
611 Target
->BufUsed
+= 5;
622 * \brief Append a string, escaping characters which have meaning in JavaScript strings .
624 * \param Target target buffer
625 * \param Source source buffer; set to NULL if you just have a C-String
626 * \param PlainIn Plain-C string to append; set to NULL if unused
628 long StrECMAEscAppend(StrBuf
*Target
, const StrBuf
*Source
, const char *PlainIn
)
630 const char *aptr
, *eiptr
;
634 if (((Source
== NULL
) && (PlainIn
== NULL
)) || (Target
== NULL
) )
637 if (PlainIn
!= NULL
) {
639 len
= strlen(PlainIn
);
644 eiptr
= aptr
+ Source
->BufUsed
;
645 len
= Source
->BufUsed
;
651 bptr
= Target
->buf
+ Target
->BufUsed
;
652 eptr
= Target
->buf
+ Target
->BufSize
- 2; /* our biggest unit to put in... */
654 while (aptr
< eiptr
){
656 IncreaseBuf(Target
, 1, -1);
657 eptr
= Target
->buf
+ Target
->BufSize
- 2;
658 bptr
= Target
->buf
+ Target
->BufUsed
;
660 else if (*aptr
== '"') {
661 memcpy(bptr
, "\\\"", 2);
663 Target
->BufUsed
+= 2;
664 } else if (*aptr
== '\\') {
665 memcpy(bptr
, "\\\\", 2);
667 Target
->BufUsed
+= 2;
677 if ((bptr
= eptr
- 1 ) && !IsEmptyStr(aptr
) )
679 return Target
->BufUsed
;
683 * \brief extracts a substring from Source into dest
684 * \param dest buffer to place substring into
685 * \param Source string to copy substring from
686 * \param Offset chars to skip from start
687 * \param nChars number of chars to copy
688 * \returns the number of chars copied; may be different from nChars due to the size of Source
690 int StrBufSub(StrBuf
*dest
, const StrBuf
*Source
, unsigned long Offset
, size_t nChars
)
693 if (Offset
> Source
->BufUsed
)
698 if (Offset
+ nChars
< Source
->BufUsed
)
700 if (nChars
> dest
->BufSize
)
701 IncreaseBuf(dest
, 0, nChars
+ 1);
702 memcpy(dest
->buf
, Source
->buf
+ Offset
, nChars
);
703 dest
->BufUsed
= nChars
;
704 dest
->buf
[dest
->BufUsed
] = '\0';
707 NCharsRemain
= Source
->BufUsed
- Offset
;
708 if (NCharsRemain
> dest
->BufSize
)
709 IncreaseBuf(dest
, 0, NCharsRemain
+ 1);
710 memcpy(dest
->buf
, Source
->buf
+ Offset
, NCharsRemain
);
711 dest
->BufUsed
= NCharsRemain
;
712 dest
->buf
[dest
->BufUsed
] = '\0';
717 * \brief sprintf like function appending the formated string to the buffer
718 * vsnprintf version to wrap into own calls
719 * \param Buf Buffer to extend by format and params
720 * \param format printf alike format to add
721 * \param ap va_list containing the items for format
723 void StrBufVAppendPrintf(StrBuf
*Buf
, const char *format
, va_list ap
)
726 size_t BufSize
= Buf
->BufSize
;
727 size_t nWritten
= Buf
->BufSize
+ 1;
728 size_t Offset
= Buf
->BufUsed
;
729 size_t newused
= Offset
+ nWritten
;
731 while (newused
>= BufSize
) {
733 nWritten
= vsnprintf(Buf
->buf
+ Offset
,
734 Buf
->BufSize
- Offset
,
737 newused
= Offset
+ nWritten
;
738 if (newused
>= Buf
->BufSize
) {
739 IncreaseBuf(Buf
, 1, newused
);
742 Buf
->BufUsed
= Offset
+ nWritten
;
743 BufSize
= Buf
->BufSize
;
750 * \brief sprintf like function appending the formated string to the buffer
751 * \param Buf Buffer to extend by format and params
752 * \param format printf alike format to add
753 * \param ap va_list containing the items for format
755 void StrBufAppendPrintf(StrBuf
*Buf
, const char *format
, ...)
757 size_t BufSize
= Buf
->BufSize
;
758 size_t nWritten
= Buf
->BufSize
+ 1;
759 size_t Offset
= Buf
->BufUsed
;
760 size_t newused
= Offset
+ nWritten
;
763 while (newused
>= BufSize
) {
764 va_start(arg_ptr
, format
);
765 nWritten
= vsnprintf(Buf
->buf
+ Buf
->BufUsed
,
766 Buf
->BufSize
- Buf
->BufUsed
,
769 newused
= Buf
->BufUsed
+ nWritten
;
770 if (newused
>= Buf
->BufSize
) {
771 IncreaseBuf(Buf
, 1, newused
);
774 Buf
->BufUsed
+= nWritten
;
775 BufSize
= Buf
->BufSize
;
782 * \brief sprintf like function putting the formated string into the buffer
783 * \param Buf Buffer to extend by format and params
784 * \param format printf alike format to add
785 * \param ap va_list containing the items for format
787 void StrBufPrintf(StrBuf
*Buf
, const char *format
, ...)
789 size_t nWritten
= Buf
->BufSize
+ 1;
792 while (nWritten
>= Buf
->BufSize
) {
793 va_start(arg_ptr
, format
);
794 nWritten
= vsnprintf(Buf
->buf
, Buf
->BufSize
, format
, arg_ptr
);
796 Buf
->BufUsed
= nWritten
;
797 if (nWritten
>= Buf
->BufSize
)
798 IncreaseBuf(Buf
, 0, 0);
804 * \brief Counts the numbmer of tokens in a buffer
805 * \param Source String to count tokens in
806 * \param tok Tokenizer char to count
807 * \returns numbers of tokenizer chars found
809 inline int StrBufNum_tokens(const StrBuf
*source
, char tok
)
813 return num_tokens(source
->buf
, tok
);
817 * remove_token() - a tokenizer that kills, maims, and destroys
820 * \brief a string tokenizer
821 * \param Source StringBuffer to read into
822 * \param parmnum n'th parameter to remove
823 * \param separator tokenizer param
824 * \returns -1 if not found, else length of token.
826 int StrBufRemove_token(StrBuf
*Source
, int parmnum
, char separator
)
829 char *d
, *s
; /* dest, source */
832 /* Find desired parameter */
834 while (count
< parmnum
) {
835 /* End of string, bail! */
840 if (*d
== separator
) {
845 if (!d
) return 0; /* Parameter not found */
847 /* Find next parameter */
849 while (*s
&& *s
!= separator
) {
857 memmove(d
, s
, Source
->BufUsed
- (s
- Source
->buf
));
858 Source
->BufUsed
-= (ReducedBy
+ 1);
860 else if (d
== Source
->buf
) {
866 Source
->BufUsed
-= (ReducedBy
+ 1);
879 * \brief a string tokenizer
880 * \param dest Destination StringBuffer
881 * \param Source StringBuffer to read into
882 * \param parmnum n'th parameter to extract
883 * \param separator tokenizer param
884 * \returns -1 if not found, else length of token.
886 int StrBufExtract_token(StrBuf
*dest
, const StrBuf
*Source
, int parmnum
, char separator
)
888 const char *s
, *e
; //* source * /
889 int len
= 0; //* running total length of extracted string * /
890 int current_token
= 0; //* token currently being processed * /
899 if ((Source
== NULL
) || (Source
->BufUsed
==0)) {
903 e
= s
+ Source
->BufUsed
;
906 //lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source);
908 while ((s
<e
) && !IsEmptyStr(s
)) {
909 if (*s
== separator
) {
912 if (len
>= dest
->BufSize
)
913 if (!IncreaseBuf(dest
, 1, -1))
915 if ( (current_token
== parmnum
) &&
920 else if (current_token
> parmnum
) {
926 dest
->buf
[len
] = '\0';
929 if (current_token
< parmnum
) {
930 //lprintf (CTDL_DEBUG,"test <!: %s\n", dest);
933 //lprintf (CTDL_DEBUG,"test <: %d; %s\n", len, dest);
939 * \brief a string tokenizer to fetch an integer
940 * \param dest Destination StringBuffer
941 * \param parmnum n'th parameter to extract
942 * \param separator tokenizer param
943 * \returns 0 if not found, else integer representation of the token
945 int StrBufExtract_int(const StrBuf
* Source
, int parmnum
, char separator
)
954 if (StrBufExtract_token(&tmp
, Source
, parmnum
, separator
) > 0)
961 * \brief a string tokenizer to fetch a long integer
962 * \param dest Destination StringBuffer
963 * \param parmnum n'th parameter to extract
964 * \param separator tokenizer param
965 * \returns 0 if not found, else long integer representation of the token
967 long StrBufExtract_long(const StrBuf
* Source
, int parmnum
, char separator
)
976 if (StrBufExtract_token(&tmp
, Source
, parmnum
, separator
) > 0)
984 * \brief a string tokenizer to fetch an unsigned long
985 * \param dest Destination StringBuffer
986 * \param parmnum n'th parameter to extract
987 * \param separator tokenizer param
988 * \returns 0 if not found, else unsigned long representation of the token
990 unsigned long StrBufExtract_unsigned_long(const StrBuf
* Source
, int parmnum
, char separator
)
1000 if (StrBufExtract_token(&tmp
, Source
, parmnum
, separator
) > 0) {
1004 return (unsigned long) atol(pnum
);
1013 * \brief Read a line from socket
1014 * flushes and closes the FD on error
1015 * \param buf the buffer to get the input to
1016 * \param fd pointer to the filedescriptor to read
1017 * \param append Append to an existing string or replace?
1018 * \param Error strerror() on error
1019 * \returns numbers of chars read
1021 int StrBufTCP_read_line(StrBuf
*buf
, int *fd
, int append
, const char **Error
)
1023 int len
, rlen
, slen
;
1028 slen
= len
= buf
->BufUsed
;
1030 rlen
= read(*fd
, &buf
->buf
[len
], 1);
1032 *Error
= strerror(errno
);
1039 if (buf
->buf
[len
] == '\n')
1041 if (buf
->buf
[len
] != '\r')
1043 if (!(len
< buf
->BufSize
)) {
1045 buf
->buf
[len
+1] = '\0';
1046 IncreaseBuf(buf
, 1, -1);
1050 buf
->buf
[len
] = '\0';
1055 * \brief Read a line from socket
1056 * flushes and closes the FD on error
1057 * \param buf the buffer to get the input to
1058 * \param fd pointer to the filedescriptor to read
1059 * \param append Append to an existing string or replace?
1060 * \param Error strerror() on error
1061 * \returns numbers of chars read
1063 int StrBufTCP_read_buffered_line(StrBuf
*Line
,
1067 int selectresolution
,
1071 int nSuccessLess
= 0;
1077 if (buf
->BufUsed
> 0) {
1078 pch
= strchr(buf
->buf
, '\n');
1081 len
= pch
- buf
->buf
;
1082 if (len
> 0 && (*(pch
- 1) == '\r') )
1084 StrBufSub(Line
, buf
, 0, len
- rlen
);
1085 StrBufCutLeft(buf
, len
+ 1);
1090 if (buf
->BufSize
- buf
->BufUsed
< 10)
1091 IncreaseBuf(buf
, 1, -1);
1093 fdflags
= fcntl(*fd
, F_GETFL
);
1094 if ((fdflags
& O_NONBLOCK
) == O_NONBLOCK
)
1097 while ((nSuccessLess
< timeout
) && (pch
== NULL
)) {
1098 tv
.tv_sec
= selectresolution
;
1103 if (select(*fd
+ 1, NULL
, &rfds
, NULL
, &tv
) == -1) {
1104 *Error
= strerror(errno
);
1109 if (FD_ISSET(*fd
, &rfds
)) {
1111 &buf
->buf
[buf
->BufUsed
],
1112 buf
->BufSize
- buf
->BufUsed
- 1);
1114 *Error
= strerror(errno
);
1119 else if (rlen
> 0) {
1121 buf
->BufUsed
+= rlen
;
1122 buf
->buf
[buf
->BufUsed
] = '\0';
1123 if (buf
->BufUsed
+ 10 > buf
->BufSize
) {
1124 IncreaseBuf(buf
, 1, -1);
1126 pch
= strchr(buf
->buf
, '\n');
1134 len
= pch
- buf
->buf
;
1135 if (len
> 0 && (*(pch
- 1) == '\r') )
1137 StrBufSub(Line
, buf
, 0, len
- rlen
);
1138 StrBufCutLeft(buf
, len
+ 1);
1146 * \brief Input binary data from socket
1147 * flushes and closes the FD on error
1148 * \param buf the buffer to get the input to
1149 * \param fd pointer to the filedescriptor to read
1150 * \param append Append to an existing string or replace?
1151 * \param nBytes the maximal number of bytes to read
1152 * \param Error strerror() on error
1153 * \returns numbers of chars read
1155 int StrBufReadBLOB(StrBuf
*Buf
, int *fd
, int append
, long nBytes
, const char **Error
)
1159 int len
, rlen
, slen
;
1163 if ((Buf
== NULL
) || (*fd
== -1))
1167 if (Buf
->BufUsed
+ nBytes
> Buf
->BufSize
)
1168 IncreaseBuf(Buf
, 1, Buf
->BufUsed
+ nBytes
);
1170 ptr
= Buf
->buf
+ Buf
->BufUsed
;
1172 slen
= len
= Buf
->BufUsed
;
1174 fdflags
= fcntl(*fd
, F_GETFL
);
1176 while (nRead
< nBytes
) {
1177 if ((fdflags
& O_NONBLOCK
) == O_NONBLOCK
) {
1180 if (select(*fd
+ 1, NULL
, &wset
, NULL
, NULL
) == -1) {
1181 *Error
= strerror(errno
);
1186 if ((rlen
= read(*fd
,
1188 nBytes
- nRead
)) == -1) {
1191 *Error
= strerror(errno
);
1196 Buf
->BufUsed
+= rlen
;
1198 Buf
->buf
[Buf
->BufUsed
] = '\0';
1203 * \brief Cut nChars from the start of the string
1204 * \param Buf Buffer to modify
1205 * \param nChars how many chars should be skipped?
1207 void StrBufCutLeft(StrBuf
*Buf
, int nChars
)
1209 if (nChars
>= Buf
->BufUsed
) {
1213 memmove(Buf
->buf
, Buf
->buf
+ nChars
, Buf
->BufUsed
- nChars
);
1214 Buf
->BufUsed
-= nChars
;
1215 Buf
->buf
[Buf
->BufUsed
] = '\0';
1219 * \brief Cut the trailing n Chars from the string
1220 * \param Buf Buffer to modify
1221 * \param nChars how many chars should be trunkated?
1223 void StrBufCutRight(StrBuf
*Buf
, int nChars
)
1225 if (nChars
>= Buf
->BufUsed
) {
1229 Buf
->BufUsed
-= nChars
;
1230 Buf
->buf
[Buf
->BufUsed
] = '\0';
1234 * \brief Cut the string after n Chars
1235 * \param Buf Buffer to modify
1236 * \param AfternChars after how many chars should we trunkate the string?
1237 * \param At if non-null and points inside of our string, cut it there.
1239 void StrBufCutAt(StrBuf
*Buf
, int AfternChars
, const char *At
)
1242 AfternChars
= At
- Buf
->buf
;
1245 if ((AfternChars
< 0) || (AfternChars
>= Buf
->BufUsed
))
1247 Buf
->BufUsed
= AfternChars
;
1248 Buf
->buf
[Buf
->BufUsed
] = '\0';
1253 * Strip leading and trailing spaces from a string; with premeasured and adjusted length.
1254 * buf - the string to modify
1255 * len - length of the string.
1257 void StrBufTrim(StrBuf
*Buf
)
1260 if ((Buf
== NULL
) || (Buf
->BufUsed
== 0)) return;
1262 while ((Buf
->BufUsed
> delta
) && (isspace(Buf
->buf
[delta
]))){
1265 if (delta
> 0) StrBufCutLeft(Buf
, delta
);
1267 if (Buf
->BufUsed
== 0) return;
1268 while (isspace(Buf
->buf
[Buf
->BufUsed
- 1])){
1271 Buf
->buf
[Buf
->BufUsed
] = '\0';
1275 void StrBufUpCase(StrBuf
*Buf
)
1280 pche
= pch
+ Buf
->BufUsed
;
1281 while (pch
< pche
) {
1282 *pch
= toupper(*pch
);
1288 void StrBufLowerCase(StrBuf
*Buf
)
1293 pche
= pch
+ Buf
->BufUsed
;
1294 while (pch
< pche
) {
1295 *pch
= tolower(*pch
);
1302 * \brief unhide special chars hidden to the HTML escaper
1303 * \param target buffer to put the unescaped string in
1304 * \param source buffer to unescape
1306 void StrBufEUid_unescapize(StrBuf
*target
, const StrBuf
*source
)
1312 FlushStrBuf(target
);
1314 if (source
== NULL
||target
== NULL
)
1319 len
= source
->BufUsed
;
1320 for (a
= 0; a
< len
; ++a
) {
1321 if (target
->BufUsed
>= target
->BufSize
)
1322 IncreaseBuf(target
, 1, -1);
1324 if (source
->buf
[a
] == '=') {
1325 hex
[0] = source
->buf
[a
+ 1];
1326 hex
[1] = source
->buf
[a
+ 2];
1329 sscanf(hex
, "%02x", &b
);
1330 target
->buf
[target
->BufUsed
] = b
;
1331 target
->buf
[++target
->BufUsed
] = 0;
1335 target
->buf
[target
->BufUsed
] = source
->buf
[a
];
1336 target
->buf
[++target
->BufUsed
] = 0;
1343 * \brief hide special chars from the HTML escapers and friends
1344 * \param target buffer to put the escaped string in
1345 * \param source buffer to escape
1347 void StrBufEUid_escapize(StrBuf
*target
, const StrBuf
*source
)
1352 FlushStrBuf(target
);
1354 if (source
== NULL
||target
== NULL
)
1359 len
= source
->BufUsed
;
1360 for (i
=0; i
<len
; ++i
) {
1361 if (target
->BufUsed
+ 4 >= target
->BufSize
)
1362 IncreaseBuf(target
, 1, -1);
1363 if ( (isalnum(source
->buf
[i
])) ||
1364 (source
->buf
[i
]=='-') ||
1365 (source
->buf
[i
]=='_') ) {
1366 target
->buf
[target
->BufUsed
++] = source
->buf
[i
];
1369 sprintf(&target
->buf
[target
->BufUsed
],
1371 (0xFF &source
->buf
[i
]));
1372 target
->BufUsed
+= 3;
1375 target
->buf
[target
->BufUsed
+ 1] = '\0';
1379 * \brief uses the same calling syntax as compress2(), but it
1380 * creates a stream compatible with HTTP "Content-encoding: gzip"
1383 #define DEF_MEM_LEVEL 8 /*< memlevel??? */
1384 #define OS_CODE 0x03 /*< unix */
1385 int ZEXPORT
compress_gzip(Bytef
* dest
, /*< compressed buffer*/
1386 size_t * destLen
, /*< length of the compresed data */
1387 const Bytef
* source
, /*< source to encode */
1388 uLong sourceLen
, /*< length of source to encode */
1389 int level
) /*< compression level */
1391 const int gz_magic
[2] = { 0x1f, 0x8b }; /* gzip magic header */
1393 /* write gzip header */
1394 snprintf((char *) dest
, *destLen
,
1395 "%c%c%c%c%c%c%c%c%c%c",
1396 gz_magic
[0], gz_magic
[1], Z_DEFLATED
,
1397 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /* xflags */ ,
1400 /* normal deflate */
1403 stream
.next_in
= (Bytef
*) source
;
1404 stream
.avail_in
= (uInt
) sourceLen
;
1405 stream
.next_out
= dest
+ 10L; // after header
1406 stream
.avail_out
= (uInt
) * destLen
;
1407 if ((uLong
) stream
.avail_out
!= *destLen
)
1410 stream
.zalloc
= (alloc_func
) 0;
1411 stream
.zfree
= (free_func
) 0;
1412 stream
.opaque
= (voidpf
) 0;
1414 err
= deflateInit2(&stream
, level
, Z_DEFLATED
, -MAX_WBITS
,
1415 DEF_MEM_LEVEL
, Z_DEFAULT_STRATEGY
);
1419 err
= deflate(&stream
, Z_FINISH
);
1420 if (err
!= Z_STREAM_END
) {
1421 deflateEnd(&stream
);
1422 return err
== Z_OK
? Z_BUF_ERROR
: err
;
1424 *destLen
= stream
.total_out
+ 10L;
1426 /* write CRC and Length */
1427 uLong crc
= crc32(0L, source
, sourceLen
);
1429 for (n
= 0; n
< 4; ++n
, ++*destLen
) {
1430 dest
[*destLen
] = (int) (crc
& 0xff);
1433 uLong len
= stream
.total_in
;
1434 for (n
= 0; n
< 4; ++n
, ++*destLen
) {
1435 dest
[*destLen
] = (int) (len
& 0xff);
1438 err
= deflateEnd(&stream
);
1445 * Attention! If you feed this a Const String, you must maintain the uncompressed buffer yourself!
1447 int CompressBuffer(StrBuf
*Buf
)
1450 char *compressed_data
= NULL
;
1451 size_t compressed_len
, bufsize
;
1453 bufsize
= compressed_len
= ((Buf
->BufUsed
* 101) / 100) + 100;
1454 compressed_data
= malloc(compressed_len
);
1456 if (compress_gzip((Bytef
*) compressed_data
,
1459 (uLongf
) Buf
->BufUsed
, Z_BEST_SPEED
) == Z_OK
) {
1462 Buf
->buf
= compressed_data
;
1463 Buf
->BufUsed
= compressed_len
;
1464 Buf
->BufSize
= bufsize
;
1467 free(compressed_data
);
1469 #endif /* HAVE_ZLIB */
1474 * \brief decode a buffer from base 64 encoding; destroys original
1475 * \param Buf Buffor to transform
1477 int StrBufDecodeBase64(StrBuf
*Buf
)
1481 if (Buf
== NULL
) return -1;
1483 xferbuf
= (char*) malloc(Buf
->BufSize
);
1484 siz
= CtdlDecodeBase64(xferbuf
,
1495 * \brief remove escaped strings from i.e. the url string (like %20 for blanks)
1496 * \param Buf Buffer to translate
1497 * \param StripBlanks Reduce several blanks to one?
1499 long StrBufUnescape(StrBuf
*Buf
, int StripBlanks
)
1505 while ((Buf
->BufUsed
> 0) && (isspace(Buf
->buf
[Buf
->BufUsed
- 1]))){
1506 Buf
->buf
[Buf
->BufUsed
- 1] = '\0';
1511 while (a
< Buf
->BufUsed
) {
1512 if (Buf
->buf
[a
] == '+')
1514 else if (Buf
->buf
[a
] == '%') {
1515 /* don't let % chars through, rather truncate the input. */
1516 if (a
+ 2 > Buf
->BufUsed
) {
1521 hex
[0] = Buf
->buf
[a
+ 1];
1522 hex
[1] = Buf
->buf
[a
+ 2];
1525 sscanf(hex
, "%02x", &b
);
1526 Buf
->buf
[a
] = (char) b
;
1527 len
= Buf
->BufUsed
- a
- 2;
1529 memmove(&Buf
->buf
[a
+ 1], &Buf
->buf
[a
+ 3], len
);
1541 * \brief RFC2047-encode a header field if necessary.
1542 * If no non-ASCII characters are found, the string
1543 * will be copied verbatim without encoding.
1545 * \param target Target buffer.
1546 * \param source Source string to be encoded.
1547 * \returns encoded length; -1 if non success.
1549 int StrBufRFC2047encode(StrBuf
**target
, const StrBuf
*source
)
1551 const char headerStr
[] = "=?UTF-8?Q?";
1552 int need_to_encode
= 0;
1556 if ((source
== NULL
) ||
1560 while ((i
< source
->BufUsed
) &&
1561 (!IsEmptyStr (&source
->buf
[i
])) &&
1562 (need_to_encode
== 0)) {
1563 if (((unsigned char) source
->buf
[i
] < 32) ||
1564 ((unsigned char) source
->buf
[i
] > 126)) {
1570 if (!need_to_encode
) {
1571 if (*target
== NULL
) {
1572 *target
= NewStrBufPlain(source
->buf
, source
->BufUsed
);
1575 FlushStrBuf(*target
);
1576 StrBufAppendBuf(*target
, source
, 0);
1578 return (*target
)->BufUsed
;
1580 if (*target
== NULL
)
1581 *target
= NewStrBufPlain(NULL
, sizeof(headerStr
) + source
->BufUsed
* 2);
1582 else if (sizeof(headerStr
) + source
->BufUsed
> (*target
)->BufSize
)
1583 IncreaseBuf(*target
, sizeof(headerStr
) + source
->BufUsed
, 0);
1584 memcpy ((*target
)->buf
, headerStr
, sizeof(headerStr
) - 1);
1585 (*target
)->BufUsed
= sizeof(headerStr
) - 1;
1586 for (i
=0; (i
< source
->BufUsed
); ++i
) {
1587 if ((*target
)->BufUsed
+ 4 > (*target
)->BufSize
)
1588 IncreaseBuf(*target
, 1, 0);
1589 ch
= (unsigned char) source
->buf
[i
];
1590 if ((ch
< 32) || (ch
> 126) || (ch
== 61)) {
1591 sprintf(&(*target
)->buf
[(*target
)->BufUsed
], "=%02X", ch
);
1592 (*target
)->BufUsed
+= 3;
1595 (*target
)->buf
[(*target
)->BufUsed
] = ch
;
1596 (*target
)->BufUsed
++;
1600 if ((*target
)->BufUsed
+ 4 > (*target
)->BufSize
)
1601 IncreaseBuf(*target
, 1, 0);
1603 (*target
)->buf
[(*target
)->BufUsed
++] = '?';
1604 (*target
)->buf
[(*target
)->BufUsed
++] = '=';
1605 (*target
)->buf
[(*target
)->BufUsed
] = '\0';
1606 return (*target
)->BufUsed
;;
1610 * \brief replaces all occurances of 'search' by 'replace'
1611 * \param buf Buffer to modify
1612 * \param search character to search
1613 * \param relpace character to replace search by
1615 void StrBufReplaceChars(StrBuf
*buf
, char search
, char replace
)
1620 for (i
=0; i
<buf
->BufUsed
; i
++)
1621 if (buf
->buf
[i
] == search
)
1622 buf
->buf
[i
] = replace
;
1629 * Wrapper around iconv_open()
1630 * Our version adds aliases for non-standard Microsoft charsets
1631 * such as 'MS950', aliasing them to names like 'CP950'
1633 * tocode Target encoding
1634 * fromcode Source encoding
1636 void ctdl_iconv_open(const char *tocode
, const char *fromcode
, void *pic
)
1639 iconv_t ic
= (iconv_t
)(-1) ;
1640 ic
= iconv_open(tocode
, fromcode
);
1641 if (ic
== (iconv_t
)(-1) ) {
1642 char alias_fromcode
[64];
1643 if ( (strlen(fromcode
) == 5) && (!strncasecmp(fromcode
, "MS", 2)) ) {
1644 safestrncpy(alias_fromcode
, fromcode
, sizeof alias_fromcode
);
1645 alias_fromcode
[0] = 'C';
1646 alias_fromcode
[1] = 'P';
1647 ic
= iconv_open(tocode
, alias_fromcode
);
1650 *(iconv_t
*)pic
= ic
;
1656 static inline char *FindNextEnd (const StrBuf
*Buf
, char *bptr
)
1659 /* Find the next ?Q? */
1660 if (Buf
->BufUsed
- (bptr
- Buf
->buf
) < 6)
1663 end
= strchr(bptr
+ 2, '?');
1668 if ((Buf
->BufUsed
- (end
- Buf
->buf
) > 3) &&
1669 ((*(end
+ 1) == 'B') || (*(end
+ 1) == 'Q')) &&
1670 (*(end
+ 2) == '?')) {
1671 /* skip on to the end of the cluster, the next ?= */
1672 end
= strstr(end
+ 3, "?=");
1675 /* sort of half valid encoding, try to find an end. */
1676 end
= strstr(bptr
, "?=");
1681 void StrBufConvert(StrBuf
*ConvertBuf
, StrBuf
*TmpBuf
, void *pic
)
1686 char *ibuf
; /**< Buffer of characters to be converted */
1687 char *obuf
; /**< Buffer for converted characters */
1688 size_t ibuflen
; /**< Length of input buffer */
1689 size_t obuflen
; /**< Length of output buffer */
1692 if (ConvertBuf
->BufUsed
> TmpBuf
->BufSize
)
1693 IncreaseBuf(TmpBuf
, 0, ConvertBuf
->BufUsed
);
1695 ic
= *(iconv_t
*)pic
;
1696 ibuf
= ConvertBuf
->buf
;
1697 ibuflen
= ConvertBuf
->BufUsed
;
1699 obuflen
= TmpBuf
->BufSize
;
1701 iconv(ic
, &ibuf
, &ibuflen
, &obuf
, &obuflen
);
1703 /* little card game: wheres the red lady? */
1704 ibuf
= ConvertBuf
->buf
;
1705 BufSize
= ConvertBuf
->BufSize
;
1707 ConvertBuf
->buf
= TmpBuf
->buf
;
1708 ConvertBuf
->BufSize
= TmpBuf
->BufSize
;
1709 ConvertBuf
->BufUsed
= TmpBuf
->BufSize
- obuflen
;
1710 ConvertBuf
->buf
[ConvertBuf
->BufUsed
] = '\0';
1713 TmpBuf
->BufSize
= BufSize
;
1714 TmpBuf
->BufUsed
= 0;
1715 TmpBuf
->buf
[0] = '\0';
1722 inline static void DecodeSegment(StrBuf
*Target
,
1723 const StrBuf
*DecodeMe
,
1727 StrBuf
*ConvertBuf2
,
1728 StrBuf
*FoundCharset
)
1733 iconv_t ic
= (iconv_t
)(-1);
1735 /* Now we handle foreign character sets properly encoded
1736 * in RFC2047 format.
1738 StaticBuf
.buf
= SegmentStart
;
1739 StaticBuf
.BufUsed
= SegmentEnd
- SegmentStart
;
1740 StaticBuf
.BufSize
= DecodeMe
->BufSize
- (SegmentStart
- DecodeMe
->buf
);
1741 extract_token(charset
, SegmentStart
, 1, '?', sizeof charset
);
1742 if (FoundCharset
!= NULL
) {
1743 FlushStrBuf(FoundCharset
);
1744 StrBufAppendBufPlain(FoundCharset
, charset
, -1, 0);
1746 extract_token(encoding
, SegmentStart
, 2, '?', sizeof encoding
);
1747 StrBufExtract_token(ConvertBuf
, &StaticBuf
, 3, '?');
1749 *encoding
= toupper(*encoding
);
1750 if (*encoding
== 'B') { /**< base64 */
1751 ConvertBuf2
->BufUsed
= CtdlDecodeBase64(ConvertBuf2
->buf
,
1753 ConvertBuf
->BufUsed
);
1755 else if (*encoding
== 'Q') { /**< quoted-printable */
1759 while (pos
< ConvertBuf
->BufUsed
)
1761 if (ConvertBuf
->buf
[pos
] == '_')
1762 ConvertBuf
->buf
[pos
] = ' ';
1766 ConvertBuf2
->BufUsed
= CtdlDecodeQuotedPrintable(
1769 ConvertBuf
->BufUsed
);
1772 StrBufAppendBuf(ConvertBuf2
, ConvertBuf
, 0);
1775 ctdl_iconv_open("UTF-8", charset
, &ic
);
1776 if (ic
!= (iconv_t
)(-1) ) {
1777 StrBufConvert(ConvertBuf2
, ConvertBuf
, &ic
);
1778 StrBufAppendBuf(Target
, ConvertBuf2
, 0);
1782 StrBufAppendBufPlain(Target
, HKEY("(unreadable)"), 0);
1786 * Handle subjects with RFC2047 encoding such as:
1787 * =?koi8-r?B?78bP0s3Mxc7JxSDXz9rE1dvO2c3JINvB0sHNySDP?=
1789 void StrBuf_RFC822_to_Utf8(StrBuf
*Target
, const StrBuf
*DecodeMe
, const StrBuf
* DefaultCharset
, StrBuf
*FoundCharset
)
1791 StrBuf
*ConvertBuf
, *ConvertBuf2
;
1792 char *start
, *end
, *next
, *nextend
, *ptr
= NULL
;
1793 iconv_t ic
= (iconv_t
)(-1) ;
1797 int illegal_non_rfc2047_encoding
= 0;
1799 /* Sometimes, badly formed messages contain strings which were simply
1800 * written out directly in some foreign character set instead of
1801 * using RFC2047 encoding. This is illegal but we will attempt to
1802 * handle it anyway by converting from a user-specified default
1803 * charset to UTF-8 if we see any nonprintable characters.
1806 len
= StrLength(DecodeMe
);
1807 for (i
=0; i
<DecodeMe
->BufUsed
; ++i
) {
1808 if ((DecodeMe
->buf
[i
] < 32) || (DecodeMe
->buf
[i
] > 126)) {
1809 illegal_non_rfc2047_encoding
= 1;
1814 ConvertBuf
= NewStrBufPlain(NULL
, StrLength(DecodeMe
));
1815 if ((illegal_non_rfc2047_encoding
) &&
1816 (strcasecmp(ChrPtr(DefaultCharset
), "UTF-8")) &&
1817 (strcasecmp(ChrPtr(DefaultCharset
), "us-ascii")) )
1819 ctdl_iconv_open("UTF-8", ChrPtr(DefaultCharset
), &ic
);
1820 if (ic
!= (iconv_t
)(-1) ) {
1821 StrBufConvert((StrBuf
*)DecodeMe
, ConvertBuf
, &ic
);///TODO: don't void const?
1826 /* pre evaluate the first pair */
1827 nextend
= end
= NULL
;
1828 len
= StrLength(DecodeMe
);
1829 start
= strstr(DecodeMe
->buf
, "=?");
1830 eptr
= DecodeMe
->buf
+ DecodeMe
->BufUsed
;
1832 end
= FindNextEnd (DecodeMe
, start
);
1834 StrBufAppendBuf(Target
, DecodeMe
, 0);
1835 FreeStrBuf(&ConvertBuf
);
1839 ConvertBuf2
= NewStrBufPlain(NULL
, StrLength(DecodeMe
));
1841 if (start
!= DecodeMe
->buf
)
1842 StrBufAppendBufPlain(Target
, DecodeMe
->buf
, start
- DecodeMe
->buf
, 0);
1844 * Since spammers will go to all sorts of absurd lengths to get their
1845 * messages through, there are LOTS of corrupt headers out there.
1846 * So, prevent a really badly formed RFC2047 header from throwing
1847 * this function into an infinite loop.
1849 while ((start
!= NULL
) &&
1856 DecodeSegment(Target
,
1864 next
= strstr(end
, "=?");
1866 if ((next
!= NULL
) &&
1868 nextend
= FindNextEnd(DecodeMe
, next
);
1869 if (nextend
== NULL
)
1872 /* did we find two partitions */
1873 if ((next
!= NULL
) &&
1877 while ((ptr
< next
) &&
1883 /* did we find a gab just filled with blanks? */
1888 len
- (next
- start
));
1890 /* now terminate the gab at the end */
1891 delta
= (next
- end
) - 2; ////TODO: const!
1892 ((StrBuf
*)DecodeMe
)->BufUsed
-= delta
;
1893 ((StrBuf
*)DecodeMe
)->buf
[DecodeMe
->BufUsed
] = '\0';
1895 /* move next to its new location. */
1900 /* our next-pair is our new first pair now. */
1906 nextend
= DecodeMe
->buf
+ DecodeMe
->BufUsed
;
1907 if ((end
!= NULL
) && (end
< nextend
)) {
1909 while ( (ptr
< nextend
) &&
1916 StrBufAppendBufPlain(Target
, end
, nextend
- end
, 0);
1918 FreeStrBuf(&ConvertBuf
);
1919 FreeStrBuf(&ConvertBuf2
);
1924 long StrBuf_Utf8StrLen(StrBuf
*Buf
)
1926 return Ctdl_Utf8StrLen(Buf
->buf
);
1929 long StrBuf_Utf8StrCut(StrBuf
*Buf
, int maxlen
)
1933 CutAt
= Ctdl_Utf8StrCut(Buf
->buf
, maxlen
);
1934 if (CutAt
!= NULL
) {
1935 Buf
->BufUsed
= CutAt
- Buf
->buf
;
1936 Buf
->buf
[Buf
->BufUsed
] = '\0';
1938 return Buf
->BufUsed
;
1943 int StrBufSipLine(StrBuf
*LineBuf
, StrBuf
*Buf
, const char **Ptr
)
1945 const char *aptr
, *ptr
, *eptr
;
1952 ptr
= aptr
= Buf
->buf
;
1956 optr
= LineBuf
->buf
;
1957 eptr
= Buf
->buf
+ Buf
->BufUsed
;
1958 xptr
= LineBuf
->buf
+ LineBuf
->BufSize
;
1960 while ((*ptr
!= '\n') &&
1967 LineBuf
->BufUsed
= optr
- LineBuf
->buf
;
1968 IncreaseBuf(LineBuf
, 1, LineBuf
->BufUsed
+ 1);
1969 optr
= LineBuf
->buf
+ LineBuf
->BufUsed
;
1970 xptr
= LineBuf
->buf
+ LineBuf
->BufSize
;
1973 LineBuf
->BufUsed
= optr
- LineBuf
->buf
;
1982 return Buf
->BufUsed
- (ptr
- Buf
->buf
);