From: Wilfried Goesgens Date: Mon, 7 Oct 2013 21:16:12 +0000 (+0200) Subject: Implement range requests with attachments; we may need to inspect the first chunk... X-Git-Tag: v9.01~219 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=d88fd4e9952bd2858ea12497173dcda6ecfbdf09 Implement range requests with attachments; we may need to inspect the first chunk of the file anyways if we need to detect the mimetype. --- diff --git a/webcit/messages.c b/webcit/messages.c index 3444d6f9f..3eaef6817 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -1803,6 +1803,7 @@ void postpart(StrBuf *partnum, StrBuf *filename, int force_download) */ void mimepart(int force_download) { + int detect_mime = 0; long msgnum; long ErrorDetail; StrBuf *att; @@ -1824,26 +1825,29 @@ void mimepart(int force_download) StrBufExtract_token(ContentType, Buf, 3, '|'); CheckGZipCompressionAllowed (SKEY(ContentType)); if (force_download) + { FlushStrBuf(ContentType); - - - serv_read_binary(WCC->WBuf, bytes, Buf); - serv_puts("CLOS"); - StrBuf_ServGetln(Buf); - CT = ChrPtr(ContentType); - - if (!force_download) { - if (!strcasecmp(ChrPtr(ContentType), "application/octet-stream")) { + detect_mime = 0; + } + else + { + if (!strcasecmp(ChrPtr(ContentType), "application/octet-stream")) + { StrBufExtract_token(Buf, WCC->Hdr->HR.ReqLine, 2, '/'); CT = GuessMimeByFilename(SKEY(Buf)); - CheckGZipCompressionAllowed (CT, strlen(CT)); + StrBufPlain(ContentType, CT, -1); } - if (!strcasecmp(ChrPtr(ContentType), "application/octet-stream")) { - CT = GuessMimeType(SKEY(WCC->WBuf)); - CheckGZipCompressionAllowed (CT, strlen(CT)); + if (!strcasecmp(ChrPtr(ContentType), "application/octet-stream")) + { + detect_mime = 1; } } - http_transmit_thing(CT, 0); + serv_read_binary_to_http(ContentType, bytes, 0, detect_mime); + + serv_read_binary(WCC->WBuf, bytes, Buf); + serv_puts("CLOS"); + StrBuf_ServGetln(Buf); + CT = ChrPtr(ContentType); } else { StrBufCutLeft(Buf, 4); switch (ErrorDetail) { @@ -1863,7 +1867,12 @@ void mimepart(int force_download) hprintf("HTTP/1.1 500 %s\n", ChrPtr(Buf)); break; } - output_headers(0, 0, 0, 0, 0, 0); + + hprintf("Pragma: no-cache\r\n" + "Cache-Control: no-store\r\n" + "Expires: -1\r\n" + ); + hprintf("Content-Type: text/plain\r\n"); begin_burst(); wc_printf(_("An error occurred while retrieving this part: %s\n"), diff --git a/webcit/tcp_sockets.c b/webcit/tcp_sockets.c index 963007f87..04c648a29 100644 --- a/webcit/tcp_sockets.c +++ b/webcit/tcp_sockets.c @@ -495,22 +495,69 @@ int client_write(StrBuf *ThisBuf) return 0; } + +int +read_serv_chunk( + + StrBuf *Buf, + size_t total_len, + size_t *bytes_read + ) +{ + int rc; + int ServerRc; + wcsession *WCC = WC; + + serv_printf("READ "SIZE_T_FMT"|"SIZE_T_FMT, *bytes_read, total_len-(*bytes_read)); + if ( (rc = StrBuf_ServGetln(Buf) > 0) && + (ServerRc = GetServerStatus(Buf, NULL), ServerRc == 6) ) + { + size_t this_block = 0; + + if (rc < 0) + return rc; + + StrBufCutLeft(Buf, 4); + this_block = StrTol(Buf); + rc = StrBuf_ServGetBLOBBuffered(WCC->WBuf, this_block); + if (rc < 0) { + syslog(LOG_INFO, "Server connection broken during download\n"); + wc_backtrace(LOG_INFO); + if (WCC->serv_sock > 0) close(WCC->serv_sock); + WCC->serv_sock = (-1); + WCC->connected = 0; + WCC->logged_in = 0; + return rc; + } + *bytes_read += rc; + } + return 6; +} + +static inline int send_http(StrBuf *Buf) +{ +#ifdef HAVE_OPENSSL + if (is_https) + return client_write_ssl(Buf); + else +#endif + return client_write(Buf); +} /* * Read binary data from server into memory using a series of server READ commands. * returns the read content as StrBuf */ void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, int detect_mime) { + int ServerRc = 6; wcsession *WCC = WC; size_t bytes_read = 0; - size_t this_block = 0; - int rc = 6; - int ServerRc = 6; int first = 1; int chunked = 0; StrBuf *BufHeader; StrBuf *Buf; + Buf = NewStrBuf(); if (WCC->Hdr->HaveRange) { @@ -529,43 +576,67 @@ void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, { BufHeader=NewStrBuf(); } - Buf = NewStrBuf(); - http_transmit_headers(ChrPtr(MimeType), is_static, chunked); -#ifdef HAVE_OPENSSL - if (is_https) - client_write_ssl(WCC->HBuf); - else -#endif - client_write(WCC->HBuf); + if ((detect_mime != 0) && (bytes_read != 0)) + { + /* need to read first chunk to detect mime, though the client doesn't care */ + size_t bytes_read = 0; + const char *CT; + + ServerRc = read_serv_chunk( + Buf, + total_len, + &bytes_read); + + if (ServerRc != 6) + { + FreeStrBuf(&Buf); + return; + } + CT = GuessMimeType(SKEY(WCC->WBuf)); + FlushStrBuf(WCC->WBuf); + StrBufPlain(MimeType, CT, -1); + detect_mime = 0; + FreeStrBuf(&Buf); + } + + if (!detect_mime) + { + http_transmit_headers(ChrPtr(MimeType), is_static, chunked); + + if (send_http(WCC->HBuf) < 0) + { + FreeStrBuf(&Buf); + return; + } + } while ((bytes_read < total_len) && (ServerRc == 6)) { if (WCC->serv_sock==-1) { FlushStrBuf(WCC->WBuf); + FreeStrBuf(&Buf); return; } - serv_printf("READ "SIZE_T_FMT"|"SIZE_T_FMT, bytes_read, total_len-bytes_read); - if ( (rc = StrBuf_ServGetln(Buf) > 0) && - (ServerRc = GetServerStatus(Buf, NULL), ServerRc == 6) ) + ServerRc = read_serv_chunk( + Buf, + total_len, + &bytes_read); + if (ServerRc != 6) + break; + + if (detect_mime) { - if (rc < 0) - return; - StrBufCutLeft(Buf, 4); - this_block = StrTol(Buf); - rc = StrBuf_ServGetBLOBBuffered(WCC->WBuf, this_block); - if (rc < 0) { - syslog(LOG_INFO, "Server connection broken during download\n"); - wc_backtrace(LOG_INFO); - if (WCC->serv_sock > 0) close(WCC->serv_sock); - WCC->serv_sock = (-1); - WCC->connected = 0; - WCC->logged_in = 0; - return; - } - bytes_read += rc; + const char *CT; + detect_mime = 0; + + CT = GuessMimeType(SKEY(WCC->WBuf)); + StrBufPlain(MimeType, CT, -1); + http_transmit_headers(ChrPtr(MimeType), is_static, chunked); + if (send_http(WCC->HBuf) < 0) + break; } if (chunked) @@ -573,40 +644,26 @@ void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, StrBufPrintf(BufHeader, "%s%x\r\n", (first)?"":"\r\n", StrLength (WCC->WBuf)); -#ifdef HAVE_OPENSSL - if (is_https) - rc = client_write_ssl(BufHeader); - else -#endif - rc = client_write(BufHeader); - if (rc < 0) + if (send_http(BufHeader) < 0) break; } -#ifdef HAVE_OPENSSL - if (is_https) - rc = client_write_ssl(WCC->WBuf); - else -#endif - rc = client_write(WCC->WBuf); - - if (rc < 0) + if (send_http(WCC->WBuf) < 0) break; - first = 0; + FlushStrBuf(WCC->WBuf); } if (chunked) { - StrBufPrintf(BufHeader, "\r\n0\r\n\r\n"); -#ifdef HAVE_OPENSSL - if (is_https) - rc = client_write_ssl(BufHeader); - else -#endif - rc = client_write(BufHeader); + StrBufPlain(BufHeader, HKEY("\r\n0\r\n\r\n")); + if (send_http(BufHeader) < 0) + { + FreeStrBuf(&Buf); + return; + } } - + FreeStrBuf(&Buf); } int ClientGetLine(ParsedHttpHdrs *Hdr, StrBuf *Target)