*/
void ReAdjustEmptyBuf(StrBuf *Buf, long ThreshHold, long NewSize)
{
- if (Buf->BufUsed > ThreshHold) {
+ if ((Buf != NULL) && (Buf->BufUsed > ThreshHold)) {
free(Buf->buf);
Buf->buf = (char*) malloc(NewSize);
Buf->BufUsed = 0;
*/
long StrBufShrinkToFit(StrBuf *Buf, int Force)
{
+ if (Buf == NULL)
+ return -1;
if (Force ||
(Buf->BufUsed + (Buf->BufUsed / 3) > Buf->BufSize))
{
return 0;
return 0;
}
+
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
* @brief modifies a Single char of the Buf
* You can point to it via char* or a zero-based integer
* @param Buf The buffer to manipulate
}
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
+ * @brief modifies a range of chars of the Buf
+ * You can point to it via char* or a zero-based integer
+ * @param Buf The buffer to manipulate
+ * @param ptr char* to zero; use NULL if unused
+ * @param nThChar zero based pointer into the string; use -1 if unused
+ * @param nChars how many chars are to be flushed?
+ * @param PookValue The Character to place into that area
+ */
+long StrBufPook(StrBuf *Buf, const char* ptr, long nThChar, long nChars, char PookValue)
+{
+ if (Buf == NULL)
+ return -1;
+ if (ptr != NULL)
+ nThChar = ptr - Buf->buf;
+ if ((nThChar < 0) || (nThChar > Buf->BufUsed))
+ return -1;
+ if (nThChar + nChars > Buf->BufUsed)
+ nChars = Buf->BufUsed - nThChar;
+
+ memset(Buf->buf + nThChar, PookValue, nChars);
+ /* just to be shure... */
+ Buf->buf[Buf->BufUsed] = 0;
+ return nChars;
+}
+
+/**
+ * @ingroup StrBuf_Filler
* @brief Append a StringBuffer to the buffer
* @param Buf Buffer to modify
* @param AppendBuf Buffer to copy at the end of our buffer
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
* @brief Append a C-String to the buffer
* @param Buf Buffer to modify
* @param AppendBuf Buffer to copy at the end of our buffer
}
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
* @brief sprintf like function appending the formated string to the buffer
* vsnprintf version to wrap into own calls
* @param Buf Buffer to extend by format and Params
}
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
* @brief sprintf like function appending the formated string to the buffer
* @param Buf Buffer to extend by format and Params
* @param format printf alike format to add
}
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
* @brief sprintf like function putting the formated string into the buffer
* @param Buf Buffer to extend by format and Parameters
* @param format printf alike format to add
}
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
* @brief Callback for cURL to append the webserver reply to a buffer
* @param ptr pre-defined by the cURL API; see man 3 curl for mre info
* @param size pre-defined by the cURL API; see man 3 curl for mre info
size_t NCharsRemain;
if (Offset > Source->BufUsed)
{
- FlushStrBuf(dest);
+ if (dest != NULL)
+ FlushStrBuf(dest);
return 0;
}
if (Offset + nChars < Source->BufUsed)
int delta = 0;
if ((Buf == NULL) || (Buf->BufUsed == 0)) return;
+ while ((Buf->BufUsed > 0) &&
+ isspace(Buf->buf[Buf->BufUsed - 1]))
+ {
+ Buf->BufUsed --;
+ }
+ Buf->buf[Buf->BufUsed] = '\0';
+
+ if (Buf->BufUsed == 0) return;
+
while ((Buf->BufUsed > delta) && (isspace(Buf->buf[delta]))){
delta ++;
}
if (delta > 0) StrBufCutLeft(Buf, delta);
+}
- if (Buf->BufUsed == 0) return;
- while (isspace(Buf->buf[Buf->BufUsed - 1])){
- Buf->BufUsed --;
+void StrBufStripAllBut(StrBuf *Buf, char leftboundary, char rightboundary)
+{
+ const char *pBuff;
+ const char *pLeft;
+ const char *pRight;
+
+ if (Buf == NULL)
+ return;
+ pLeft = pBuff = Buf->buf;
+ while (pBuff != NULL) {
+ pLeft = pBuff;
+ pBuff = strchr(pBuff, leftboundary);
+ if (pBuff != NULL)
+ pBuff++;
}
- Buf->buf[Buf->BufUsed] = '\0';
+
+ if (pLeft != NULL)
+ pBuff = pLeft;
+ else
+ pBuff = Buf->buf;
+ pRight = strchr(pBuff, rightboundary);
+ if (pRight != NULL)
+ StrBufCutAt(Buf, 0, pRight);
+ if (pLeft != NULL)
+ StrBufCutLeft(Buf, pLeft - Buf->buf);
}
+
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
* @brief uppercase the contents of a buffer
* @param Buf the buffer to translate
*/
/**
- * @ingroup StrBuf
+ * @ingroup StrBuf_Filler
* @brief lowercase the contents of a buffer
* @param Buf the buffer to translate
*/
* a tokenizer that kills, maims, and destroys *
*******************************************************************************/
+/**
+ * @ingroup StrBuf_Tokenizer
+ * @brief Replace a token at a given place with a given length by another token with given length
+ * @param Buf String where to work on
+ * @param where where inside of the Buf is the search-token
+ * @param HowLong How long is the token to be replaced
+ * @param Repl Token to insert at 'where'
+ * @param ReplLen Length of repl
+ * @returns -1 if fail else length of resulting Buf
+ */
+int StrBufReplaceToken(StrBuf *Buf, long where, long HowLong,
+ const char *Repl, long ReplLen)
+{
+
+ if ((Buf == NULL) ||
+ (where > Buf->BufUsed) ||
+ (where + HowLong > Buf->BufUsed))
+ return -1;
+
+ if (where + ReplLen - HowLong > Buf->BufSize)
+ if (IncreaseBuf(Buf, 1, Buf->BufUsed + ReplLen) < 0)
+ return -1;
+
+ memmove(Buf->buf + where + ReplLen,
+ Buf->buf + where + HowLong,
+ Buf->BufUsed - where - HowLong);
+
+ memcpy(Buf->buf + where,
+ Repl, ReplLen);
+
+ Buf->BufUsed += ReplLen - HowLong;
+
+ return Buf->BufUsed;
+}
+
/**
* @ingroup StrBuf_Tokenizer
* @brief Counts the numbmer of tokens in a buffer
(*pch >= '@' && *pch <= 'Z') || /* @ A-Z */
(*pch >= '0' && *pch <= ':') || /* 0-9 : */
(*pch == '!') || (*pch == '_') ||
- (*pch == ',') || (*pch == '.') ||
- (*pch == ','))
+ (*pch == ',') || (*pch == '.'))
{
*(pt++) = *(pch++);
OutBuf->BufUsed++;
*pt = '\0';
}
+/**
+ * @ingroup StrBuf_DeEnCoder
+ * @brief append a string in hex encoding to the buffer
+ * @param OutBuf the output buffer
+ * @param In Buffer to encode
+ * @param PlainIn way in from plain old c strings
+ */
+void StrBufHexescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn)
+{
+ const char *pch, *pche;
+ char *pt, *pte;
+ int len;
+
+ if (((In == NULL) && (PlainIn == NULL)) || (OutBuf == NULL) )
+ return;
+ if (PlainIn != NULL) {
+ len = strlen(PlainIn);
+ pch = PlainIn;
+ pche = pch + len;
+ }
+ else {
+ pch = In->buf;
+ pche = pch + In->BufUsed;
+ len = In->BufUsed;
+ }
+
+ if (len == 0)
+ return;
+
+ pt = OutBuf->buf + OutBuf->BufUsed;
+ pte = OutBuf->buf + OutBuf->BufSize - 3; /**< we max append 3 chars at once plus the \0 */
+
+ while (pch < pche) {
+ if (pt >= pte) {
+ IncreaseBuf(OutBuf, 1, -1);
+ pte = OutBuf->buf + OutBuf->BufSize - 3; /**< we max append 3 chars at once plus the \0 */
+ pt = OutBuf->buf + OutBuf->BufUsed;
+ }
+
+ *pt = HexList[(unsigned char)*pch][0];
+ pt ++;
+ *pt = HexList[(unsigned char)*pch][1];
+ pt ++; pch ++; OutBuf->BufUsed += 2;
+ }
+ *pt = '\0';
+}
+
/**
* @ingroup StrBuf_DeEnCoder
* @brief Append a string, escaping characters which have meaning in HTML.
char hex[3];
long len;
+ if (Buf == NULL)
+ return -1;
+
while ((Buf->BufUsed > 0) && (isspace(Buf->buf[Buf->BufUsed - 1]))){
Buf->buf[Buf->BufUsed - 1] = '\0';
Buf->BufUsed --;
}
+/**
+ * @ingroup StrBuf
+ * @brief removes all \r s from the string, or replaces them with \n if its not a combination of both.
+ * @param buf Buffer to modify
+ */
+void StrBufToUnixLF(StrBuf *buf)
+{
+ char *pche, *pchS, *pchT;
+ if (buf == NULL)
+ return;
+
+ pche = buf->buf + buf->BufUsed;
+ pchS = pchT = buf->buf;
+ while (pchS < pche)
+ {
+ if (*pchS == '\r')
+ {
+ pchS ++;
+ if (*pchS != '\n') {
+ *pchT = '\n';
+ pchT++;
+ }
+ }
+ *pchT = *pchS;
+ pchT++; pchS++;
+ }
+ *pchT = '\0';
+ buf->BufUsed = pchT - buf->buf;
+}
+
/*******************************************************************************
* Iconv Wrapper; RFC822 de/encoding *
* @param bptr where to start searching
* @returns found position, NULL if none.
*/
-static inline char *FindNextEnd (const StrBuf *Buf, char *bptr)
+static inline const char *FindNextEnd (const StrBuf *Buf, const char *bptr)
{
- char * end;
+ const char * end;
/* Find the next ?Q? */
if (Buf->BufUsed - (bptr - Buf->buf) < 6)
return NULL;
*/
inline static void DecodeSegment(StrBuf *Target,
const StrBuf *DecodeMe,
- char *SegmentStart,
- char *SegmentEnd,
+ const char *SegmentStart,
+ const char *SegmentEnd,
StrBuf *ConvertBuf,
StrBuf *ConvertBuf2,
StrBuf *FoundCharset)
/* Now we handle foreign character sets properly encoded
* in RFC2047 format.
*/
- StaticBuf.buf = SegmentStart;
+ StaticBuf.buf = (char*) SegmentStart; /*< it will just be read there... */
StaticBuf.BufUsed = SegmentEnd - SegmentStart;
StaticBuf.BufSize = DecodeMe->BufSize - (SegmentStart - DecodeMe->buf);
extract_token(charset, SegmentStart, 1, '?', sizeof charset);
StrBuf *DecodedInvalidBuf = NULL;
StrBuf *ConvertBuf, *ConvertBuf2;
const StrBuf *DecodeMee = DecodeMe;
- char *start, *end, *next, *nextend, *ptr = NULL;
+ const char *start, *end, *next, *nextend, *ptr = NULL;
#ifdef HAVE_ICONV
iconv_t ic = (iconv_t)(-1) ;
#endif
const char *eptr;
int passes = 0;
- int i, len, delta;
+ int i, len;
int illegal_non_rfc2047_encoding = 0;
/* Sometimes, badly formed messages contain strings which were simply
(*ptr == '\n') ||
(*ptr == '\t')))
ptr ++;
- /* did we find a gab just filled with blanks? */
- if (ptr == next)
+ /*
+ * did we find a gab just filled with blanks?
+ * if not, copy its stuff over.
+ */
+ if (ptr != next)
{
- long gap = next - start;
- memmove (end + 2,
- next,
- len - (gap));
- len -= gap;
- /* now terminate the gab at the end */
- delta = (next - end) - 2; ////TODO: const!
- ((StrBuf*)DecodeMee)->BufUsed -= delta;
- ((StrBuf*)DecodeMee)->buf[DecodeMee->BufUsed] = '\0';
-
- /* move next to its new location. */
- next -= delta;
- nextend -= delta;
+ StrBufAppendBufPlain(Target,
+ end + 2,
+ next - end - 2,
+ 0);
}
}
/* our next-pair is our new first pair now. */
* @ingroup StrBuf_BufferedIO
* @brief Read a line from socket
* flushes and closes the FD on error
- * @param Line Line to read from the fd / I/O Buffer
- * @param IOBuf the buffer to get the input to
- * @param Pos pointer to the current read position, should be NULL initialized!
+ * @param Line where to append our Line read from the fd / I/O Buffer;
+ * @param IOBuf the buffer to get the input to; lifetime pair to FD
+ * @param Pos pointer to the current read position, should be NULL initialized on opening the FD it belongs to.!
* @param fd pointer to the filedescriptor to read
* @param timeout number of successless selects until we bail out
* @param selectresolution how long to wait on each select
* @param Error strerror() on error
- * @returns numbers of chars read
+ * @returns numbers of chars read or -1 in case of error. "\n" will become 0
*/
int StrBufTCP_read_buffered_line_fast(StrBuf *Line,
StrBuf *IOBuf,
{
const char *pche = NULL;
const char *pos = NULL;
- int len, rlen;
+ const char *pLF;
+ int len, rlen, retlen;
int nSuccessLess = 0;
fd_set rfds;
const char *pch = NULL;
int IsNonBlock;
struct timeval tv;
+ retlen = 0;
if ((Line == NULL) ||
(Pos == NULL) ||
(IOBuf == NULL) ||
(pos != NULL) &&
(pos < IOBuf->buf + IOBuf->BufUsed))
{
+ char *pcht;
+
pche = IOBuf->buf + IOBuf->BufUsed;
pch = pos;
+ pcht = Line->buf;
+
while ((pch < pche) && (*pch != '\n'))
- pch ++;
+ {
+ if (Line->BufUsed + 10 > Line->BufSize)
+ {
+ long apos;
+ apos = pcht - Line->buf;
+ *pcht = '\0';
+ IncreaseBuf(Line, 1, -1);
+ pcht = Line->buf + apos;
+ }
+ *pcht++ = *pch++;
+ Line->BufUsed++;
+ retlen++;
+ }
+
+ len = pch - pos;
+ if (len > 0 && (*(pch - 1) == '\r') )
+ {
+ retlen--;
+ len --;
+ pcht --;
+ Line->BufUsed --;
+ }
+ *pcht = '\0';
+
if ((pch >= pche) || (*pch == '\0'))
+ {
+ FlushStrBuf(IOBuf);
+ *Pos = NULL;
pch = NULL;
+ pos = 0;
+ }
+
if ((pch != NULL) &&
(pch <= pche))
{
- rlen = 0;
- len = pch - pos;
- if (len > 0 && (*(pch - 1) == '\r') )
- rlen ++;
- StrBufSub(Line, IOBuf, (pos - IOBuf->buf), len - rlen);
- *Pos = pch + 1;
- return len - rlen;
+ if (pch + 1 >= pche) {
+ *Pos = NULL;
+ FlushStrBuf(IOBuf);
+ }
+ else
+ *Pos = pch + 1;
+
+ return retlen;
}
- }
-
- if (pos != NULL) {
- if (pos > pche)
- FlushStrBuf(IOBuf);
else
- StrBufCutLeft(IOBuf, (pos - IOBuf->buf));
- *Pos = NULL;
+ FlushStrBuf(IOBuf);
}
+
+ /* If we come here, Pos is Unset since we read everything into Line, and now go for more. */
- if (IOBuf->BufSize - IOBuf->BufUsed < 10) {
+ if (IOBuf->BufSize - IOBuf->BufUsed < 10)
IncreaseBuf(IOBuf, 1, -1);
- *Pos = NULL;
- }
fdflags = fcntl(*fd, F_GETFL);
IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK;
- pch = NULL;
+ pLF = NULL;
while ((nSuccessLess < timeout) &&
- (pch == NULL) &&
+ (pLF == NULL) &&
(*fd != -1)) {
if (IsNonBlock)
{
}
else if (rlen > 0) {
nSuccessLess = 0;
+ pLF = IOBuf->buf + IOBuf->BufUsed;
IOBuf->BufUsed += rlen;
IOBuf->buf[IOBuf->BufUsed] = '\0';
- if (IOBuf->BufUsed + 10 > IOBuf->BufSize) {
- IncreaseBuf(IOBuf, 1, -1);
- *Pos = NULL;
- }
pche = IOBuf->buf + IOBuf->BufUsed;
- pch = IOBuf->buf;
- while ((pch < pche) && (*pch != '\n'))
- pch ++;
- if ((pch >= pche) || (*pch == '\0'))
- pch = NULL;
+
+ while ((pLF < pche) && (*pLF != '\n'))
+ pLF ++;
+ if ((pLF >= pche) || (*pLF == '\0'))
+ pLF = NULL;
+
+ if (IOBuf->BufUsed + 10 > IOBuf->BufSize)
+ {
+ long apos;
+
+ if (pLF != NULL) apos = pLF - IOBuf->buf;
+ IncreaseBuf(IOBuf, 1, -1);
+ if (pLF != NULL) pLF = IOBuf->buf + apos;
+ }
+
continue;
}
}
- if (pch != NULL) {
+ *Pos = NULL;
+ if (pLF != NULL) {
pos = IOBuf->buf;
- rlen = 0;
- len = pch - pos;
- if (len > 0 && (*(pch - 1) == '\r') )
- rlen ++;
- StrBufSub(Line, IOBuf, 0, len - rlen);
- *Pos = pos + len + 1;
- return len - rlen;
+ len = pLF - pos;
+ if (len > 0 && (*(pLF - 1) == '\r') )
+ len --;
+ StrBufAppendBufPlain(Line, ChrPtr(IOBuf), len, 0);
+ if (pLF + 1 >= IOBuf->buf + IOBuf->BufUsed)
+ {
+ FlushStrBuf(IOBuf);
+ }
+ else
+ *Pos = pLF + 1;
+ return retlen + len;
}
*Error = ErrRBLF_NotEnoughSentFromServer;
return -1;
pos = *Pos;
- if (pos > 0)
+ if (pos != NULL)
len = pos - IOBuf->buf;
rlen = IOBuf->BufUsed - len;