X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=libcitadel%2Flib%2Fstringbuf.c;h=31e99b52f06c15a477990a726314595cdda34956;hb=0daf8cf6c657b725c2d53776ba766d632456a891;hp=f621255c8224363b10fd9a0ba31783f405e0aa58;hpb=0a200b8a84a25a77b9027fd7274beedad6314eae;p=citadel.git diff --git a/libcitadel/lib/stringbuf.c b/libcitadel/lib/stringbuf.c index f621255c8..31e99b52f 100644 --- a/libcitadel/lib/stringbuf.c +++ b/libcitadel/lib/stringbuf.c @@ -1,3 +1,22 @@ +/* + * Copyright (c) 1987-2011 by the citadel.org team + * + * This program is open source software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define _GNU_SOURCE #include "sysdep.h" #include #include @@ -10,6 +29,10 @@ #include #define SHOW_ME_VAPPEND_PRINTF #include + +#ifndef LINUX_SENDFILE +#include +#endif #include "libcitadel.h" #ifdef HAVE_ICONV @@ -20,6 +43,10 @@ #include #endif +#ifdef LINUX_SENDFILE +#include +#endif + #ifdef HAVE_ZLIB #include int ZEXPORT compress_gzip(Bytef * dest, size_t * destLen, @@ -276,9 +303,12 @@ static int IncreaseBuf(StrBuf *Buf, int KeepOriginal, int DestSize) return -1; if (DestSize > 0) - while (NewSize <= DestSize) + while ((NewSize <= DestSize) && (NewSize != 0)) NewSize *= 2; + if (NewSize == 0) + return -1; + NewBuf= (char*) malloc(NewSize); if (NewBuf == NULL) return -1; @@ -479,9 +509,14 @@ StrBuf* NewStrBufPlain(const char* ptr, int nChars) else CopySize = nChars; - while (Siz <= CopySize) + while ((Siz <= CopySize) && (Siz != 0)) Siz *= 2; + if (Siz == 0) + { + return NULL; + } + NewBuf->buf = (char*) malloc(Siz); if (NewBuf->buf == NULL) { @@ -532,9 +567,14 @@ int StrBufPlain(StrBuf *Buf, const char* ptr, int nChars) else CopySize = nChars; - while (Siz <= CopySize) + while ((Siz <= CopySize) && (Siz != 0)) Siz *= 2; + if (Siz == 0) { + FlushStrBuf(Buf); + return -1; + } + if (Siz != Buf->BufSize) IncreaseBuf(Buf, 0, Siz); memcpy(Buf->buf, ptr, CopySize); @@ -858,7 +898,8 @@ void StrBufVAppendPrintf(StrBuf *Buf, const char *format, va_list ap) va_end(apl); newused = Offset + nWritten; if (newused >= Buf->BufSize) { - IncreaseBuf(Buf, 1, newused); + if (IncreaseBuf(Buf, 1, newused) == -1) + return; /* TODO: error handling? */ newused = Buf->BufSize + 1; } else { @@ -899,7 +940,8 @@ void StrBufAppendPrintf(StrBuf *Buf, const char *format, ...) va_end(arg_ptr); newused = Buf->BufUsed + nWritten; if (newused >= Buf->BufSize) { - IncreaseBuf(Buf, 1, newused); + if (IncreaseBuf(Buf, 1, newused) == -1) + return; /* TODO: error handling? */ newused = Buf->BufSize + 1; } else { @@ -930,7 +972,8 @@ void StrBufPrintf(StrBuf *Buf, const char *format, ...) nWritten = vsnprintf(Buf->buf, Buf->BufSize, format, arg_ptr); va_end(arg_ptr); if (nWritten >= Buf->BufSize) { - IncreaseBuf(Buf, 0, 0); + if (IncreaseBuf(Buf, 0, 0) == -1) + return; /* TODO: error handling? */ nWritten = Buf->BufSize + 1; continue; } @@ -1333,7 +1376,7 @@ int StrBufExtract_token(StrBuf *dest, const StrBuf *Source, int parmnum, char se //cit_backtrace(); //lprintf (CTDL_DEBUG, "test >: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source); - while ((s: n: %d sep: %c source: %s \n willi \n", parmnum, separator, source); - while ((sBufUsed; } + if (len == 0) + return; + + pt = OutBuf->buf + OutBuf->BufUsed; + pte = OutBuf->buf + OutBuf->BufSize - 4; /**< 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 - 4; /**< we max append 3 chars at once plus the \0 */ + pt = OutBuf->buf + OutBuf->BufUsed; + } + + if((*pch >= 'a' && *pch <= 'z') || + (*pch >= 'A' && *pch <= 'Z') || /* A-Z */ + (*pch >= '0' && *pch <= ':') || /* 0-9 : */ + (*pch == '!') || (*pch == '_') || + (*pch == ',') || (*pch == '.')) + { + *(pt++) = *(pch++); + OutBuf->BufUsed++; + } + else { + *pt = '%'; + *(pt + 1) = HexList[(unsigned char)*pch][0]; + *(pt + 2) = HexList[(unsigned char)*pch][1]; + pt += 3; + OutBuf->BufUsed += 3; + pch ++; + } + } + *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 + * @param PlainInLen way in from plain old c strings; maybe you've got binary data or know the length? + */ +void StrBufHexEscAppend(StrBuf *OutBuf, const StrBuf *In, const unsigned char *PlainIn, long PlainInLen) +{ + const unsigned char *pch, *pche; + char *pt, *pte; + int len; + + if (((In == NULL) && (PlainIn == NULL)) || (OutBuf == NULL) ) + return; + if (PlainIn != NULL) { + if (PlainInLen < 0) + len = strlen((const char*)PlainIn); + else + len = PlainInLen; + pch = PlainIn; + pche = pch + len; + } + else { + pch = (const unsigned char*)In->buf; + pche = pch + In->BufUsed; + len = In->BufUsed; + } + if (len == 0) return; @@ -1820,14 +1927,26 @@ void StrBufHexescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn) pt = OutBuf->buf + OutBuf->BufUsed; } - *pt = HexList[(unsigned char)*pch][0]; + *pt = HexList[*pch][0]; pt ++; - *pt = HexList[(unsigned char)*pch][1]; + *pt = HexList[*pch][1]; pt ++; pch ++; OutBuf->BufUsed += 2; } *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) +{ + StrBufHexEscAppend(OutBuf, In, (const unsigned char*) PlainIn, -1); +} + /** * @ingroup StrBuf_DeEnCoder * @brief Append a string, escaping characters which have meaning in HTML. @@ -2093,6 +2212,7 @@ long StrECMAEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn) const char *aptr, *eiptr; char *bptr, *eptr; long len; + int IsUtf8Sequence; if (((Source == NULL) && (PlainIn == NULL)) || (Target == NULL) ) return -1; @@ -2112,31 +2232,83 @@ long StrECMAEscAppend(StrBuf *Target, const StrBuf *Source, const char *PlainIn) return -1; bptr = Target->buf + Target->BufUsed; - eptr = Target->buf + Target->BufSize - 3; /* our biggest unit to put in... */ + eptr = Target->buf + Target->BufSize - 7; /* our biggest unit to put in... */ while (aptr < eiptr){ if(bptr >= eptr) { IncreaseBuf(Target, 1, -1); - eptr = Target->buf + Target->BufSize - 3; + eptr = Target->buf + Target->BufSize - 7; /* our biggest unit to put in... */ bptr = Target->buf + Target->BufUsed; } - if (*aptr == '"') { + switch (*aptr) { + case '\n': + memcpy(bptr, HKEY("\\n")); + bptr += 2; + Target->BufUsed += 2; + break; + case '\r': + memcpy(bptr, HKEY("\\r")); + bptr += 2; + Target->BufUsed += 2; + break; + case '"': *bptr = '\\'; bptr ++; *bptr = '"'; bptr ++; Target->BufUsed += 2; - } else if (*aptr == '\\') { + break; + case '\\': + if ((*(aptr + 1) == 'u') && + isxdigit(*(aptr + 2)) && + isxdigit(*(aptr + 3)) && + isxdigit(*(aptr + 4)) && + isxdigit(*(aptr + 5))) + { /* oh, a unicode escaper. let it pass through. */ + memcpy(bptr, aptr, 6); + aptr += 5; + bptr +=6; + Target->BufUsed += 6; + } + else + { + *bptr = '\\'; + bptr ++; + *bptr = '\\'; + bptr ++; + Target->BufUsed += 2; + } + break; + case '\b': *bptr = '\\'; bptr ++; + *bptr = 'b'; + bptr ++; + Target->BufUsed += 2; + break; + case '\f': *bptr = '\\'; bptr ++; + *bptr = 'f'; + bptr ++; Target->BufUsed += 2; - } - else{ - *bptr = *aptr; - bptr++; - Target->BufUsed ++; + break; + case '\t': + *bptr = '\\'; + bptr ++; + *bptr = 't'; + bptr ++; + Target->BufUsed += 2; + break; + default: + IsUtf8Sequence = Ctdl_GetUtf8SequenceLength(aptr, eiptr); + while (IsUtf8Sequence > 0){ + *bptr = *aptr; + Target->BufUsed ++; + if (--IsUtf8Sequence) + aptr++; + bptr++; + } } aptr ++; } @@ -2190,83 +2362,127 @@ long StrHtmlEcmaEscAppend(StrBuf *Target, const StrBuf *Source, const char *Plai eptr = Target->buf + Target->BufSize - 11; /* our biggest unit to put in... */ bptr = Target->buf + Target->BufUsed; } - if (*aptr == '<') { - memcpy(bptr, "<", 4); + switch (*aptr) { + case '<': + memcpy(bptr, HKEY("<")); bptr += 4; Target->BufUsed += 4; - } - else if (*aptr == '>') { - memcpy(bptr, ">", 4); + break; + case '>': + memcpy(bptr, HKEY(">")); bptr += 4; Target->BufUsed += 4; - } - else if (*aptr == '&') { - memcpy(bptr, "&", 5); + break; + case '&': + memcpy(bptr, HKEY("&")); bptr += 5; Target->BufUsed += 5; - } - else if (*aptr == LB) { + break; + case LB: *bptr = '<'; bptr ++; Target->BufUsed ++; - } - else if (*aptr == RB) { + break; + case RB: *bptr = '>'; bptr ++; Target->BufUsed ++; - } - else if ((*aptr == 32) && (nbsp == 1)) { - memcpy(bptr, " ", 6); - bptr += 6; - Target->BufUsed += 6; - } - else if ((*aptr == '\n') && (nolinebreaks == 1)) { - *bptr='\0'; /* nothing */ - } - else if ((*aptr == '\n') && (nolinebreaks == 2)) { - memcpy(bptr, "<br/>", 11); - bptr += 11; - Target->BufUsed += 11; - } - - else if ((*aptr == '\r') && (nolinebreaks != 0)) { - *bptr='\0'; /* nothing */ - } - - else if ((*aptr == '"') || (*aptr == QU)) { + break; + case '\n': + switch (nolinebreaks) { + case 1: + *bptr='\0'; /* nothing */ + break; + case 2: + memcpy(bptr, HKEY("<br/>")); + bptr += 11; + Target->BufUsed += 11; + break; + default: + memcpy(bptr, HKEY("\\n")); + bptr += 2; + Target->BufUsed += 2; + } + break; + case '\r': + switch (nolinebreaks) { + case 1: + case 2: + *bptr='\0'; /* nothing */ + break; + default: + memcpy(bptr, HKEY("\\r")); + bptr += 2; + Target->BufUsed += 2; + break; + } + break; + case '"': + case QU: *bptr = '\\'; bptr ++; *bptr = '"'; bptr ++; Target->BufUsed += 2; - } else if (*aptr == '\\') { + break; + case '\\': + if ((*(aptr + 1) == 'u') && + isxdigit(*(aptr + 2)) && + isxdigit(*(aptr + 3)) && + isxdigit(*(aptr + 4)) && + isxdigit(*(aptr + 5))) + { /* oh, a unicode escaper. let it pass through. */ + memcpy(bptr, aptr, 6); + aptr += 5; + bptr +=6; + Target->BufUsed += 6; + } + else + { + *bptr = '\\'; + bptr ++; + *bptr = '\\'; + bptr ++; + Target->BufUsed += 2; + } + break; + case '\b': *bptr = '\\'; bptr ++; + *bptr = 'b'; + bptr ++; + Target->BufUsed += 2; + break; + case '\f': *bptr = '\\'; bptr ++; + *bptr = 'f'; + bptr ++; Target->BufUsed += 2; - } - else { - if (((unsigned char)*aptr) >= 0x20) - { - IsUtf8Sequence = Ctdl_GetUtf8SequenceLength(aptr, eiptr); - + break; + case '\t': + *bptr = '\\'; + bptr ++; + *bptr = 't'; + bptr ++; + Target->BufUsed += 2; + break; + case 32: + if (nbsp == 1) { + memcpy(bptr, HKEY(" ")); + bptr += 6; + Target->BufUsed += 6; + break; + } + default: + IsUtf8Sequence = Ctdl_GetUtf8SequenceLength(aptr, eiptr); + while (IsUtf8Sequence > 0){ *bptr = *aptr; Target->BufUsed ++; - while (IsUtf8Sequence > 1){ - if(bptr + IsUtf8Sequence >= eptr) { - IncreaseBuf(Target, 1, -1); - eptr = Target->buf + Target->BufSize - 11; /* our biggest unit to put in... */ - bptr = Target->buf + Target->BufUsed - 1; - } - bptr++; aptr++; - IsUtf8Sequence --; - *bptr = *aptr; - Target->BufUsed ++; - } + if (--IsUtf8Sequence) + aptr++; bptr++; } - } aptr ++; } @@ -2531,12 +2747,23 @@ int StrBufRFC2047encode(StrBuf **target, const StrBuf *source) if ((*target)->BufUsed + 4 >= (*target)->BufSize) IncreaseBuf(*target, 1, 0); ch = (unsigned char) source->buf[i]; - if ((ch < 32) || (ch > 126) || (ch == 61)) { + if ((ch < 32) || + (ch > 126) || + (ch == 61) || + (ch == '=') || + (ch == '?') || + (ch == '_') || + (ch == '[') || + (ch == ']') ) + { sprintf(&(*target)->buf[(*target)->BufUsed], "=%02X", ch); (*target)->BufUsed += 3; } else { - (*target)->buf[(*target)->BufUsed] = ch; + if (ch == ' ') + (*target)->buf[(*target)->BufUsed] = '_'; + else + (*target)->buf[(*target)->BufUsed] = ch; (*target)->BufUsed++; } } @@ -2590,15 +2817,12 @@ StrBuf *StrBufSanitizeEmailRecipientVector(const StrBuf *Recp, 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); @@ -2609,8 +2833,6 @@ StrBuf *StrBufSanitizeEmailRecipientVector(const StrBuf *Recp, while ((pch != NULL) && (pch < pche)) { - int ColonOk = 0; - while (isspace(*pch)) pch++; UserStart = UserEnd = EmailStart = EmailEnd = NULL; @@ -2640,7 +2862,6 @@ StrBuf *StrBufSanitizeEmailRecipientVector(const StrBuf *Recp, if (EmailEnd == NULL) EmailEnd = pche; pch = EmailEnd + 1; - ColonOk = 1; } else { int gt = 0; @@ -2748,7 +2969,7 @@ void StrBufReplaceChars(StrBuf *buf, char search, char replace) /** * @ingroup StrBuf - * @brief removes all \r s from the string, or replaces them with \n if its not a combination of both. + * @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) @@ -3180,19 +3401,24 @@ void StrBuf_RFC822_2_Utf8(StrBuf *Target, * @ingroup StrBuf * @brief evaluate the length of an utf8 special character sequence * @param Char the character to examine - * @returns width of utf8 chars in bytes + * @returns width of utf8 chars in bytes; if the sequence is broken 0 is returned; 1 if its simply ASCII. */ static inline int Ctdl_GetUtf8SequenceLength(const char *CharS, const char *CharE) { - int n = 1; - char test = (1<<7); - - while ((n < 8) && ((test & *CharS) != 0)) { - test = test << 1; + int n = 0; + unsigned char test = (1<<7); + + if ((*CharS & 0xC0) != 0xC0) + return 1; + + while ((n < 8) && + ((test & ((unsigned char)*CharS)) != 0)) + { + test = test >> 1; n ++; } if ((n > 6) || ((CharE - CharS) < n)) - n = 1; + n = 0; return n; } @@ -3205,7 +3431,7 @@ static inline int Ctdl_GetUtf8SequenceLength(const char *CharS, const char *Char static inline int Ctdl_IsUtf8SequenceStart(const char Char) { /** 11??.???? indicates an UTF8 Sequence. */ - return ((Char & 0xC0) != 0); + return ((Char & 0xC0) == 0xC0); } /** @@ -3566,7 +3792,18 @@ eReadState StrBufChunkSipLine(StrBuf *LineBuf, IOBuffer *FB) optr --; if ((*(ptr - 1) != '\r') && (*(ptr - 1) != '\n')) { LineBuf->BufUsed = optr - LineBuf->buf; - *optr = '\0'; + *optr = '\0'; + if ((FB->ReadWritePointer != NULL) && + (FB->ReadWritePointer != FB->Buf->buf)) + { + /* Ok, the client application read all the data + it was interested in so far. Since there is more to read, + we now shrink the buffer, and move the rest over. + */ + StrBufCutLeft(FB->Buf, + FB->ReadWritePointer - FB->Buf->buf); + FB->ReadWritePointer = FB->Buf->buf; + } return eMustReadMore; } } @@ -3606,6 +3843,203 @@ eReadState StrBufCheckBuffer(IOBuffer *FB) return eReadSuccess; } +long IOBufferStrLength(IOBuffer *FB) +{ + if (FB->ReadWritePointer == NULL) + return StrLength(FB->Buf); + + return StrLength(FB->Buf) - (FB->ReadWritePointer - FB->Buf->buf); +} + +void FDIOBufferInit(FDIOBuffer *FDB, IOBuffer *IO, int FD, long TotalSendSize) +{ + memset(FDB, 0, sizeof(FDIOBuffer)); + FDB->ChunkSize = + FDB->TotalSendSize = TotalSendSize; + FDB->IOB = IO; +#ifndef LINUX_SENDFILE + FDB->ChunkBuffer = NewStrBufPlain(NULL, TotalSendSize + 1); +#else + pipe(FDB->SplicePipe); +#endif + FDB->OtherFD = FD; +} + +void FDIOBufferDelete(FDIOBuffer *FDB) +{ +#ifndef LINUX_SENDFILE + FreeStrBuf(&FDB->ChunkBuffer); +#else + close(FDB->SplicePipe[0]); + close(FDB->SplicePipe[1]); + +#endif + close(FDB->OtherFD); + memset(FDB, 0, sizeof(FDIOBuffer)); +} + +int FileSendChunked(FDIOBuffer *FDB, const char **Err) +{ + char *pRead; + long nRead = 0; + +#ifdef LINUX_SENDFILE + ssize_t sent; + sent = sendfile(FDB->IOB->fd, FDB->OtherFD, &FDB->TotalSentAlready, FDB->ChunkSendRemain); + if (sent == -1) + { + *Err = strerror(errno); + return sent; + } + FDB->ChunkSendRemain -= sent; + FDB->TotalSentAlready += sent; + return FDB->ChunkSendRemain; +#else + pRead = FDB->ChunkBuffer->buf; + while ((FDB->ChunkBuffer->BufUsed < FDB->TotalSendSize) && (nRead >= 0)) + { + nRead = read(FDB->OtherFD, pRead, FDB->TotalSendSize - FDB->ChunkBuffer->BufUsed); + if (nRead > 0) { + FDB->ChunkBuffer->BufUsed += nRead; + FDB->ChunkBuffer->buf[FDB->ChunkBuffer->BufUsed] = '\0'; + } + else if (nRead == 0) {} + else return nRead; + + } + + nRead = write(FDB->IOB->fd, FDB->ChunkBuffer->buf + FDB->TotalSentAlready, FDB->ChunkSendRemain); + + if (nRead >= 0) { + FDB->TotalSentAlready += nRead; + FDB->ChunkSendRemain -= nRead; + return FDB->ChunkSendRemain; + } + else { + return nRead; + } +#endif +} + +int FileRecvChunked(FDIOBuffer *FDB, const char **Err) +{ + ssize_t sent, pipesize; + +#ifdef LINUX_SENDFILE + + pipesize = splice(FDB->IOB->fd, NULL, + FDB->SplicePipe[1], NULL, + FDB->ChunkSendRemain, + SPLICE_F_MORE | SPLICE_F_MOVE|SPLICE_F_NONBLOCK); + if (pipesize == -1) + { + *Err = strerror(errno); + return pipesize; + } + + sent = splice(FDB->SplicePipe[0], NULL, + FDB->OtherFD, &FDB->TotalSentAlready, + pipesize, SPLICE_F_MORE | SPLICE_F_MOVE); + if (sent == -1) + { + *Err = strerror(errno); + return sent; + } + FDB->ChunkSendRemain -= sent; + return sent; +#else + + sent = read(FDB->IOB->fd, FDB->ChunkBuffer->buf, FDB->ChunkSendRemain); + if (sent > 0) { + int nWritten = 0; + int rc; + + FDB->ChunkBuffer->BufUsed = sent; + + while (nWritten < FDB->ChunkBuffer->BufUsed) { + rc = write(FDB->OtherFD, FDB->ChunkBuffer->buf + nWritten, FDB->ChunkBuffer->BufUsed - nWritten); + if (rc < 0) { + *Err = strerror(errno); + return rc; + } + nWritten += rc; + + } + FDB->ChunkBuffer->BufUsed = 0; + FDB->TotalSentAlready += sent; + FDB->ChunkSendRemain -= sent; + return FDB->ChunkSendRemain; + } + else if (sent < 0) { + *Err = strerror(errno); + return sent; + } + +#endif + return 0; +} + +eReadState WriteIOBAlreadyRead(FDIOBuffer *FDB, const char **Error) +{ + int IsNonBlock; + int fdflags; + long rlen; + long should_write; + int nSuccessLess = 0; + struct timeval tv; + fd_set rfds; + + fdflags = fcntl(FDB->OtherFD, F_GETFL); + IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK; + + while ((FDB->IOB->ReadWritePointer - FDB->IOB->Buf->buf < FDB->IOB->Buf->BufUsed) && + (FDB->ChunkSendRemain > 0)) + { + if (IsNonBlock){ + tv.tv_sec = 1; /* selectresolution; */ + tv.tv_usec = 0; + + FD_ZERO(&rfds); + FD_SET(FDB->OtherFD, &rfds); + if (select(FDB->OtherFD + 1, NULL, &rfds, NULL, &tv) == -1) { + *Error = strerror(errno); + return eReadFail; + } + } + if (IsNonBlock && ! FD_ISSET(FDB->OtherFD, &rfds)) { + nSuccessLess ++; + continue; + } + + should_write = FDB->IOB->Buf->BufUsed - + (FDB->IOB->ReadWritePointer - FDB->IOB->Buf->buf); + if (should_write > FDB->ChunkSendRemain) + should_write = FDB->ChunkSendRemain; + + rlen = write(FDB->OtherFD, + FDB->IOB->ReadWritePointer, + should_write); + if (rlen < 1) { + *Error = strerror(errno); + + return eReadFail; + } + FDB->TotalSentAlready += rlen; + FDB->IOB->ReadWritePointer += rlen; + FDB->ChunkSendRemain -= rlen; + } + if (FDB->IOB->ReadWritePointer >= FDB->IOB->Buf->buf + FDB->IOB->Buf->BufUsed) + { + FlushStrBuf(FDB->IOB->Buf); + FDB->IOB->ReadWritePointer = NULL; + } + + if (FDB->ChunkSendRemain == 0) + return eReadSuccess; + else + return eMustReadMore; +} + /******************************************************************************* * File I/O; Prefer buffered read since its faster! * *******************************************************************************/ @@ -3959,7 +4393,7 @@ static const char *ErrRBLF_BLOBPreConditionFailed="StrBufReadBLOB: Wrong argumen int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **Error) { int fdflags; - int len, rlen, slen; + int rlen; int nSuccessLess; int nRead = 0; char *ptr; @@ -3979,8 +4413,6 @@ int StrBufReadBLOB(StrBuf *Buf, int *fd, int append, long nBytes, const char **E ptr = Buf->buf + Buf->BufUsed; - slen = len = Buf->BufUsed; - fdflags = fcntl(*fd, F_GETFL); IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK; nSuccessLess = 0; @@ -4049,17 +4481,15 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, int check, const char **Error) { - const char *pche; const char *pos; int fdflags; int len = 0; - int rlen, slen; + int rlen; int nRead = 0; int nAlreadyRead = 0; int IsNonBlock; char *ptr; fd_set rfds; - const char *pch; struct timeval tv; int nSuccessLess = 0; int MaxTries; @@ -4088,9 +4518,6 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, (pos != NULL) && (pos < IOBuf->buf + IOBuf->BufUsed)) { - pche = IOBuf->buf + IOBuf->BufUsed; - pch = pos; - if (rlen < nBytes) { memcpy(Blob->buf + Blob->BufUsed, pos, rlen); Blob->BufUsed += rlen; @@ -4118,7 +4545,7 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, IncreaseBuf(IOBuf, 0, nBytes - nRead); ptr = IOBuf->buf; - slen = len = Blob->BufUsed; + len = Blob->BufUsed; fdflags = fcntl(*fd, F_GETFL); IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK; @@ -4209,9 +4636,9 @@ int StrBufReadBLOBBuffered(StrBuf *Blob, * @param Buf BLOB with lines of text... * @param Ptr moved arround to keep the next-line across several iterations * has to be &NULL on start; will be &NotNULL on end of buffer - * @returns size of copied buffer + * @returns size of remaining buffer */ -int StrBufSipLine(StrBuf *LineBuf, StrBuf *Buf, const char **Ptr) +int StrBufSipLine(StrBuf *LineBuf, const StrBuf *Buf, const char **Ptr) { const char *aptr, *ptr, *eptr; char *optr, *xptr; @@ -4289,9 +4716,10 @@ void StrBufStripSlashes(StrBuf *Dir, int RemoveTrailingSlash) b++; a++; } } - if ((RemoveTrailingSlash) && (*(b - 1) != '/')){ - *b = '/'; - b++; + if ((RemoveTrailingSlash) && + (b > Dir->buf) && + (*(b - 1) == '/')){ + b--; } *b = '\0'; Dir->BufUsed = b - Dir->buf;