/**
* @ingroup StrBuf_DeConstructors
- * @brief shrink an _EMPTY_ buffer if its Buffer superseeds threshhold to NewSize. Buffercontent is thoroughly ignored and flushed.
+ * @brief shrink / increase an _EMPTY_ buffer to NewSize. Buffercontent is thoroughly ignored and flushed.
* @param Buf Buffer to shrink (has to be empty)
* @param ThreshHold if the buffer is bigger then this, its readjusted
* @param NewSize if we Shrink it, how big are we going to be afterwards?
*/
void ReAdjustEmptyBuf(StrBuf *Buf, long ThreshHold, long NewSize)
{
- if ((Buf != NULL) && (Buf->BufUsed > ThreshHold)) {
+ if ((Buf != NULL) &&
+ (Buf->BufUsed == 0) &&
+ (Buf->BufSize < ThreshHold)) {
free(Buf->buf);
Buf->buf = (char*) malloc(NewSize);
Buf->BufUsed = 0;
*/
int StrBufPlain(StrBuf *Buf, const char* ptr, int nChars)
{
- size_t Siz = Buf->BufSize;
+ size_t Siz;
size_t CopySize;
+ if (Buf == NULL)
+ return -1;
+ if (ptr == NULL) {
+ FlushStrBuf(Buf);
+ return -1;
+ }
+
+ Siz = Buf->BufSize;
+
if (nChars < 0)
CopySize = strlen(ptr);
else
while (pBuff != NULL) {
pLeft = pBuff;
pBuff = strchr(pBuff, leftboundary);
+ if (pBuff != NULL)
+ pBuff++;
}
if (pLeft != NULL)
pBuff = Buf->buf;
pRight = strchr(pBuff, rightboundary);
if (pRight != NULL)
- StrBufCutAt(Buf, 0, pRight - 1);
+ StrBufCutAt(Buf, 0, pRight);
if (pLeft != NULL)
- StrBufCutLeft(Buf, pLeft - Buf->buf + 1);
+ StrBufCutLeft(Buf, pLeft - Buf->buf);
}
if (IncreaseBuf(Buf, 1, Buf->BufUsed + ReplLen) < 0)
return -1;
- memmove(Buf->buf + where + HowLong,
- Buf->buf + where + ReplLen,
+ memmove(Buf->buf + where + ReplLen,
+ Buf->buf + where + HowLong,
Buf->BufUsed - where - HowLong);
memcpy(Buf->buf + where,
return (*target)->BufUsed;;
}
+
+
+static void AddRecipient(StrBuf *Target,
+ StrBuf *UserName,
+ StrBuf *EmailAddress,
+ StrBuf *EncBuf)
+{
+ int QuoteMe = 0;
+
+ if (StrLength(Target) > 0) StrBufAppendBufPlain(Target, HKEY(", "), 0);
+ if (strchr(ChrPtr(UserName), ',') != NULL) QuoteMe = 1;
+
+ if (QuoteMe) StrBufAppendBufPlain(Target, HKEY("\""), 0);
+ StrBufRFC2047encode(&EncBuf, UserName);
+ StrBufAppendBuf(Target, EncBuf, 0);
+ if (QuoteMe) StrBufAppendBufPlain(Target, HKEY("\" "), 0);
+ else StrBufAppendBufPlain(Target, HKEY(" "), 0);
+
+ if (StrLength(EmailAddress) > 0){
+ StrBufAppendBufPlain(Target, HKEY("<"), 0);
+ StrBufAppendBuf(Target, EmailAddress, 0); /* TODO: what about IDN???? */
+ StrBufAppendBufPlain(Target, HKEY(">"), 0);
+ }
+}
+
+
+/**
+ * \brief QP encode parts of an email TO/CC/BCC vector, and strip/filter invalid parts
+ * \param Recp Source list of email recipients
+ * \param UserName Temporary buffer for internal use; Please provide valid buffer.
+ * \param EmailAddress Temporary buffer for internal use; Please provide valid buffer.
+ * \param EncBuf Temporary buffer for internal use; Please provide valid buffer.
+ * \returns encoded & sanitized buffer with the contents of Recp; Caller owns this memory.
+ */
+StrBuf *StrBufSanitizeEmailRecipientVector(const StrBuf *Recp,
+ StrBuf *UserName,
+ StrBuf *EmailAddress,
+ StrBuf *EncBuf)
+{
+ StrBuf *Target;
+ int need_to_encode;
+
+ const char *pch, *pche;
+ const char *UserStart, *UserEnd, *EmailStart, *EmailEnd, *At;
+
+ if ((Recp == NULL) || (StrLength(Recp) == 0))
+ return NULL;
+
+ need_to_encode = 0;
+ pch = ChrPtr(Recp);
+ pche = pch + StrLength(Recp);
+
+ if (!CheckEncode(pch, -1, pche))
+ return NewStrBufDup(Recp);
+
+ Target = NewStrBufPlain(NULL, StrLength(Recp));
+
+ while ((pch != NULL) && (pch < pche))
+ {
+ int ColonOk = 0;
+
+ while (isspace(*pch)) pch++;
+ UserStart = UserEnd = EmailStart = EmailEnd = NULL;
+
+ if ((*pch == '"') || (*pch == '\'')) {
+ UserStart = pch + 1;
+
+ UserEnd = strchr(UserStart, *pch);
+ if (UserEnd == NULL)
+ break; ///TODO: Userfeedback??
+ EmailStart = UserEnd + 1;
+ while (isspace(*EmailStart))
+ EmailStart++;
+ if (UserEnd == UserStart) {
+ UserStart = UserEnd = NULL;
+ }
+
+ if (*EmailStart == '<') {
+ EmailStart++;
+ EmailEnd = strchr(EmailStart, '>');
+ if (EmailEnd == NULL)
+ EmailEnd = strchr(EmailStart, ',');
+
+ }
+ else {
+ EmailEnd = strchr(EmailStart, ',');
+ }
+ if (EmailEnd == NULL)
+ EmailEnd = pche;
+ pch = EmailEnd + 1;
+ ColonOk = 1;
+ }
+ else {
+ int gt = 0;
+ UserStart = pch;
+ EmailEnd = strchr(UserStart, ',');
+ if (EmailEnd == NULL) {
+ EmailEnd = strchr(pch, '>');
+ pch = NULL;
+ if (EmailEnd != NULL) {
+ gt = 1;
+ EmailEnd --;
+ }
+ else {
+ EmailEnd = pche;
+ }
+ }
+ else {
+
+ pch = EmailEnd + 1;
+ while ((EmailEnd > UserStart) &&
+ ((*EmailEnd == ',') ||
+ (*EmailEnd == '>') ||
+ (isspace(*EmailEnd))))
+ {
+ if (*EmailEnd == '>')
+ gt = 1;
+ EmailEnd--;
+ }
+ if (EmailEnd == UserStart)
+ break;
+ }
+ if (gt) {
+ EmailStart = strchr(UserStart, '<');
+ if ((EmailStart == NULL) || (EmailStart > EmailEnd))
+ break;
+ UserEnd = EmailStart - 1;
+ EmailStart ++;
+ if (UserStart >= UserEnd)
+ UserStart = UserEnd = NULL;
+ At = strchr(EmailStart, '@');
+ }
+ else { /* this is a local recipient... no domain, just a realname */
+ At = strchr(EmailStart, '@');
+ if (At == NULL) {
+ UserEnd = EmailEnd;
+ EmailEnd = NULL;
+ }
+ else {
+ EmailStart = UserStart;
+ UserStart = NULL;
+ }
+ }
+ }
+
+
+ if (UserStart != NULL)
+ StrBufPlain(UserName, UserStart, UserEnd - UserStart);
+ else
+ FlushStrBuf(UserName);
+ if (EmailStart != NULL)
+ StrBufPlain(EmailAddress, EmailStart, EmailEnd - EmailStart);
+ else
+ FlushStrBuf(EmailAddress);
+
+ AddRecipient(Target, UserName, EmailAddress, EncBuf);
+
+
+
+ if (*pch == ',')
+ pch ++;
+ while (isspace(*pch))
+ pch ++;
+ }
+ return Target;
+}
+
+
/**
* @ingroup StrBuf
* @brief replaces all occurances of 'search' by 'replace'
if (IOBuf->BufUsed + 10 > IOBuf->BufSize)
{
- long apos;
+ long apos = 0;
if (pLF != NULL) apos = pLF - IOBuf->buf;
IncreaseBuf(IOBuf, 1, -1);
}
const char *ErrRBB_BLOBFPreConditionFailed = "StrBufReadBLOBBuffered: to many selects; aborting.";
-const char *ErrRBB_too_many_selects = "StrBufReadBLOBBuffered: to many selects; aborting.";
+const char *ErrRBB_too_many_selects = "StrBufReadBLOBBuffered: to many selects; aborting.";
/**
* @ingroup StrBuf_BufferedIO
* @brief Input binary data from socket
{
const char *pche;
const char *pos;
- int nSelects = 0;
- int SelRes;
int fdflags;
int len = 0;
int rlen, slen;
fd_set rfds;
const char *pch;
struct timeval tv;
- int nSuccessLess;
+ int nSuccessLess = 0;
+ int MaxTries;
if ((Blob == NULL) || (*fd == -1) || (IOBuf == NULL) || (Pos == NULL))
{
fdflags = fcntl(*fd, F_GETFL);
IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK;
+ if (IsNonBlock)
+ MaxTries = 1000;
+ else
+ MaxTries = 100000;
- SelRes = 1;
nBytes -= nRead;
nRead = 0;
- while ((nRead < nBytes) &&
+ while ((nSuccessLess < MaxTries) &&
+ (nRead < nBytes) &&
(*fd != -1)) {
if (IsNonBlock)
{
continue;
}
}
- nSuccessLess = 0;
rlen = read(*fd,
ptr,
- nBytes - nRead);
+ IOBuf->BufSize - (ptr - IOBuf->buf));
if (rlen == -1) {
close(*fd);
*fd = -1;
return rlen;
}
else if (rlen == 0){
- nSuccessLess ++;
if ((check == NNN_TERM) &&
(nRead > 5) &&
(strncmp(IOBuf->buf + IOBuf->BufUsed - 5, "\n000\n", 5) == 0))
StrBufCutRight(Blob, 5);
return Blob->BufUsed;
}
- if (nSelects > 10) {
+ else if (!IsNonBlock)
+ nSuccessLess ++;
+ else if (nSuccessLess > MaxTries) {
FlushStrBuf(IOBuf);
*Error = ErrRBB_too_many_selects;
return -1;
}
}
else if (rlen > 0) {
+ nSuccessLess = 0;
nRead += rlen;
ptr += rlen;
IOBuf->BufUsed += rlen;
}
}
+ if (nSuccessLess >= MaxTries) {
+ FlushStrBuf(IOBuf);
+ *Error = ErrRBB_too_many_selects;
+ return -1;
+ }
+
if (nRead > nBytes) {
*Pos = IOBuf->buf + nBytes;
}