Fossil SCM
Allow server to emit up to 4 empty lines in the header before concluding the header is finished. RFC9112 "in the interests of robustness". From libfossil.
Commit
973e3e972027c5a9c59890e4cb3b1288aa61654eb64c2ee4cfa8be2a788b121a
Parent
399a624524b6c9c…
1 file changed
+13
-1
+13
-1
| --- src/http.c | ||
| +++ src/http.c | ||
| @@ -487,10 +487,11 @@ | ||
| 487 | 487 | Blob hdr; /* The HTTP request header */ |
| 488 | 488 | int closeConnection; /* True to close the connection when done */ |
| 489 | 489 | int iLength; /* Expected length of the reply payload */ |
| 490 | 490 | int rc = 0; /* Result code */ |
| 491 | 491 | int iHttpVersion; /* Which version of HTTP protocol server uses */ |
| 492 | + int nBlank = 0; /* Empty lines to skip after an interim reply */ | |
| 492 | 493 | char *zLine; /* A single line of the reply header */ |
| 493 | 494 | int i; /* Loop counter */ |
| 494 | 495 | int isError = 0; /* True if the reply is an error message */ |
| 495 | 496 | int isCompressed = 1; /* True if the reply is compressed */ |
| 496 | 497 | int isChunked = 0; /* True if Transfer-Encoding: chunked */ |
| @@ -597,11 +598,21 @@ | ||
| 597 | 598 | ** Read and interpret the server reply |
| 598 | 599 | */ |
| 599 | 600 | closeConnection = 1; |
| 600 | 601 | iLength = -1; |
| 601 | 602 | iHttpVersion = -1; |
| 602 | - while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){ | |
| 603 | + while( (zLine = transport_receive_line(&g.url))!=0 ){ | |
| 604 | + if( zLine[0]==0 ){ | |
| 605 | + if( nBlank>0 ){ | |
| 606 | + /* A server may send an empty line after an interim reply, | |
| 607 | + ** before the status line of the final reply. */ | |
| 608 | + nBlank--; | |
| 609 | + continue; | |
| 610 | + } | |
| 611 | + break; | |
| 612 | + } | |
| 613 | + nBlank = 0; | |
| 603 | 614 | if( mHttpFlags & HTTP_VERBOSE ){ |
| 604 | 615 | fossil_print("Read: [%s]\n", zLine); |
| 605 | 616 | } |
| 606 | 617 | if( zLine[0]==' ' || zLine[0]=='\t' ){ |
| 607 | 618 | /* A line starting with a space or tab continues the previous |
| @@ -618,10 +629,11 @@ | ||
| 618 | 629 | ** "100 Continue". Skip the remaining header lines of the reply. |
| 619 | 630 | ** A 1xx reply has no body.) */ |
| 620 | 631 | while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){} |
| 621 | 632 | iHttpVersion = -1; /* Ensures correct error msg if connection drops */ |
| 622 | 633 | if( zLine==0 ) goto write_err; |
| 634 | + nBlank = 4; | |
| 623 | 635 | continue; |
| 624 | 636 | } |
| 625 | 637 | if( rc==401 ){ |
| 626 | 638 | if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){ |
| 627 | 639 | if( g.zHttpAuth ){ |
| 628 | 640 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -487,10 +487,11 @@ | |
| 487 | Blob hdr; /* The HTTP request header */ |
| 488 | int closeConnection; /* True to close the connection when done */ |
| 489 | int iLength; /* Expected length of the reply payload */ |
| 490 | int rc = 0; /* Result code */ |
| 491 | int iHttpVersion; /* Which version of HTTP protocol server uses */ |
| 492 | char *zLine; /* A single line of the reply header */ |
| 493 | int i; /* Loop counter */ |
| 494 | int isError = 0; /* True if the reply is an error message */ |
| 495 | int isCompressed = 1; /* True if the reply is compressed */ |
| 496 | int isChunked = 0; /* True if Transfer-Encoding: chunked */ |
| @@ -597,11 +598,21 @@ | |
| 597 | ** Read and interpret the server reply |
| 598 | */ |
| 599 | closeConnection = 1; |
| 600 | iLength = -1; |
| 601 | iHttpVersion = -1; |
| 602 | while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){ |
| 603 | if( mHttpFlags & HTTP_VERBOSE ){ |
| 604 | fossil_print("Read: [%s]\n", zLine); |
| 605 | } |
| 606 | if( zLine[0]==' ' || zLine[0]=='\t' ){ |
| 607 | /* A line starting with a space or tab continues the previous |
| @@ -618,10 +629,11 @@ | |
| 618 | ** "100 Continue". Skip the remaining header lines of the reply. |
| 619 | ** A 1xx reply has no body.) */ |
| 620 | while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){} |
| 621 | iHttpVersion = -1; /* Ensures correct error msg if connection drops */ |
| 622 | if( zLine==0 ) goto write_err; |
| 623 | continue; |
| 624 | } |
| 625 | if( rc==401 ){ |
| 626 | if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){ |
| 627 | if( g.zHttpAuth ){ |
| 628 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -487,10 +487,11 @@ | |
| 487 | Blob hdr; /* The HTTP request header */ |
| 488 | int closeConnection; /* True to close the connection when done */ |
| 489 | int iLength; /* Expected length of the reply payload */ |
| 490 | int rc = 0; /* Result code */ |
| 491 | int iHttpVersion; /* Which version of HTTP protocol server uses */ |
| 492 | int nBlank = 0; /* Empty lines to skip after an interim reply */ |
| 493 | char *zLine; /* A single line of the reply header */ |
| 494 | int i; /* Loop counter */ |
| 495 | int isError = 0; /* True if the reply is an error message */ |
| 496 | int isCompressed = 1; /* True if the reply is compressed */ |
| 497 | int isChunked = 0; /* True if Transfer-Encoding: chunked */ |
| @@ -597,11 +598,21 @@ | |
| 598 | ** Read and interpret the server reply |
| 599 | */ |
| 600 | closeConnection = 1; |
| 601 | iLength = -1; |
| 602 | iHttpVersion = -1; |
| 603 | while( (zLine = transport_receive_line(&g.url))!=0 ){ |
| 604 | if( zLine[0]==0 ){ |
| 605 | if( nBlank>0 ){ |
| 606 | /* A server may send an empty line after an interim reply, |
| 607 | ** before the status line of the final reply. */ |
| 608 | nBlank--; |
| 609 | continue; |
| 610 | } |
| 611 | break; |
| 612 | } |
| 613 | nBlank = 0; |
| 614 | if( mHttpFlags & HTTP_VERBOSE ){ |
| 615 | fossil_print("Read: [%s]\n", zLine); |
| 616 | } |
| 617 | if( zLine[0]==' ' || zLine[0]=='\t' ){ |
| 618 | /* A line starting with a space or tab continues the previous |
| @@ -618,10 +629,11 @@ | |
| 629 | ** "100 Continue". Skip the remaining header lines of the reply. |
| 630 | ** A 1xx reply has no body.) */ |
| 631 | while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){} |
| 632 | iHttpVersion = -1; /* Ensures correct error msg if connection drops */ |
| 633 | if( zLine==0 ) goto write_err; |
| 634 | nBlank = 4; |
| 635 | continue; |
| 636 | } |
| 637 | if( rc==401 ){ |
| 638 | if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){ |
| 639 | if( g.zHttpAuth ){ |
| 640 |