X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=libcitadel%2Flib%2Fstringbuf.c;h=31e99b52f06c15a477990a726314595cdda34956;hb=0daf8cf6c657b725c2d53776ba766d632456a891;hp=7dc07af46e18a57541628d1b9a9f522cf0f94ef0;hpb=d406f030612c8793672a4172ae5d6d64a47dd5df;p=citadel.git diff --git a/libcitadel/lib/stringbuf.c b/libcitadel/lib/stringbuf.c index 7dc07af46..31e99b52f 100644 --- a/libcitadel/lib/stringbuf.c +++ b/libcitadel/lib/stringbuf.c @@ -29,8 +29,8 @@ #include #define SHOW_ME_VAPPEND_PRINTF #include + #ifndef LINUX_SENDFILE -#include #include #endif #include "libcitadel.h" @@ -1824,6 +1824,66 @@ void StrBufUrlescAppend(StrBuf *OutBuf, const StrBuf *In, const char *PlainIn) *pt = '\0'; } +/** + * @ingroup StrBuf_DeEnCoder + * @brief Escape a string for feeding out as a the username/password part of an URL while appending it to a Buffer + * @param OutBuf the output buffer + * @param In Buffer to encode + * @param PlainIn way in from plain old c strings + */ +void StrBufUrlescUPAppend(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 - 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 @@ -3791,8 +3851,6 @@ long IOBufferStrLength(IOBuffer *FB) return StrLength(FB->Buf) - (FB->ReadWritePointer - FB->Buf->buf); } - - void FDIOBufferInit(FDIOBuffer *FDB, IOBuffer *IO, int FD, long TotalSendSize) { memset(FDB, 0, sizeof(FDIOBuffer)); @@ -3800,16 +3858,31 @@ void FDIOBufferInit(FDIOBuffer *FDB, IOBuffer *IO, int FD, long TotalSendSize) FDB->TotalSendSize = TotalSendSize; FDB->IOB = IO; #ifndef LINUX_SENDFILE - FDB->ChunkBuffer = NewStrBuf(); + FDB->ChunkBuffer = NewStrBufPlain(NULL, TotalSendSize + 1); #else pipe(FDB->SplicePipe); #endif FDB->OtherFD = FD; } -int FileSendChunked(FDIOBuffer *FDB, const char **Err) +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); @@ -3819,18 +3892,40 @@ int FileSendChunked(FDIOBuffer *FDB, const char **Err) 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 - return 0; } int FileRecvChunked(FDIOBuffer *FDB, const char **Err) { + ssize_t sent, pipesize; #ifdef LINUX_SENDFILE - ssize_t sent, pipesize; - long foo = 0; pipesize = splice(FDB->IOB->fd, NULL, FDB->SplicePipe[1], NULL, @@ -3853,6 +3948,33 @@ int FileRecvChunked(FDIOBuffer *FDB, const char **Err) 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; } @@ -4594,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;