Fossil SCM

Emit only \n, not \r\n, even in places where protocols technically require a full \r\n. Provide a compile-time option -DSEND_CR=1 that includes the CRs when necessary.

drh 2024-10-12 12:03 trunk
Commit 0dcce257b04e2bfb8f85bd5ecda8cc9064c077a253d5f48703f06675e2664b16
+1 -1
--- src/ajax.c
+++ src/ajax.c
@@ -338,11 +338,11 @@
338338
case AJAX_RENDER_PLAIN_TEXT: zRenderMode = "text"; break;
339339
case AJAX_RENDER_GUESS:
340340
assert(!"cannot happen");
341341
}
342342
if(zRenderMode!=0){
343
- cgi_printf_header("x-ajax-render-mode: %s\r\n", zRenderMode);
343
+ cgi_printf_header("x-ajax-render-mode: %s" CRLF, zRenderMode);
344344
}
345345
}
346346
347347
#if INTERFACE
348348
/*
349349
--- src/ajax.c
+++ src/ajax.c
@@ -338,11 +338,11 @@
338 case AJAX_RENDER_PLAIN_TEXT: zRenderMode = "text"; break;
339 case AJAX_RENDER_GUESS:
340 assert(!"cannot happen");
341 }
342 if(zRenderMode!=0){
343 cgi_printf_header("x-ajax-render-mode: %s\r\n", zRenderMode);
344 }
345 }
346
347 #if INTERFACE
348 /*
349
--- src/ajax.c
+++ src/ajax.c
@@ -338,11 +338,11 @@
338 case AJAX_RENDER_PLAIN_TEXT: zRenderMode = "text"; break;
339 case AJAX_RENDER_GUESS:
340 assert(!"cannot happen");
341 }
342 if(zRenderMode!=0){
343 cgi_printf_header("x-ajax-render-mode: %s" CRLF, zRenderMode);
344 }
345 }
346
347 #if INTERFACE
348 /*
349
+40 -36
--- src/alerts.c
+++ src/alerts.c
@@ -437,11 +437,11 @@
437437
char zBuf[100];
438438
n = blob_size(pMsg);
439439
for(i=0; i<n; i+=54){
440440
k = translateBase64(blob_buffer(pMsg)+i, i+54<n ? 54 : n-i, zBuf);
441441
blob_append(pOut, zBuf, k);
442
- blob_append(pOut, "\r\n", 2);
442
+ blob_append(pOut, CRLF, CRLF_SZ);
443443
}
444444
}
445445
#endif
446446
447447
/*
@@ -457,19 +457,19 @@
457457
|| (c==' ' && zIn[0]!='\r' && zIn[0]!='\n')
458458
){
459459
blob_append_char(pOut, c);
460460
iCol++;
461461
if( iCol>=70 ){
462
- blob_append(pOut, "=\r\n", 3);
462
+ blob_append(pOut, "=" CRLF, CRLF_SZ+1);
463463
iCol = 0;
464464
}
465465
}else if( c=='\r' && zIn[0]=='\n' ){
466466
zIn++;
467
- blob_append(pOut, "\r\n", 2);
467
+ blob_append(pOut, CRLF, CRLF_SZ);
468468
iCol = 0;
469469
}else if( c=='\n' ){
470
- blob_append(pOut, "\r\n", 2);
470
+ blob_append(pOut, CRLF, CRLF_SZ);
471471
iCol = 0;
472472
}else{
473473
char x[3];
474474
x[0] = '=';
475475
x[1] = "0123456789ABCDEF"[(c>>4)&0xf];
@@ -960,37 +960,37 @@
960960
}
961961
blob_append(pOut, blob_buffer(pHdr), blob_size(pHdr));
962962
if( p->zFrom==0 || p->zFrom[0]==0 ){
963963
return; /* email-self is not set. Error will be reported separately */
964964
}else if( zFromName ){
965
- blob_appendf(pOut, "From: %s <%s@%s>\r\n",
965
+ blob_appendf(pOut, "From: %s <%s@%s>" CRLF,
966966
zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom));
967
- blob_appendf(pOut, "Sender: <%s>\r\n", p->zFrom);
967
+ blob_appendf(pOut, "Sender: <%s>" CRLF, p->zFrom);
968968
}else{
969
- blob_appendf(pOut, "From: <%s>\r\n", p->zFrom);
969
+ blob_appendf(pOut, "From: <%s>" CRLF, p->zFrom);
970970
}
971
- blob_appendf(pOut, "Date: %z\r\n", cgi_rfc822_datestamp(time(0)));
971
+ blob_appendf(pOut, "Date: %z" CRLF, cgi_rfc822_datestamp(time(0)));
972972
if( p->zListId && p->zListId[0] ){
973
- blob_appendf(pOut, "List-Id: %s\r\n", p->zListId);
973
+ blob_appendf(pOut, "List-Id: %s" CRLF, p->zListId);
974974
}
975
- if( strstr(blob_str(pHdr), "\r\nMessage-Id:")==0 ){
975
+ if( strstr(blob_str(pHdr), CRLF "Message-Id:")==0 ){
976976
/* Message-id format: "<$(date)x$(random)@$(from-host)>" where $(date) is
977977
** the current unix-time in hex, $(random) is a 64-bit random number,
978978
** and $(from) is the domain part of the email-self setting. */
979979
sqlite3_randomness(sizeof(r1), &r1);
980980
r2 = time(0);
981
- blob_appendf(pOut, "Message-Id: <%llxx%016llx@%s>\r\n",
981
+ blob_appendf(pOut, "Message-Id: <%llxx%016llx@%s>" CRLF,
982982
r2, r1, alert_hostname(p->zFrom));
983983
}
984984
blob_add_final_newline(pBody);
985
- blob_appendf(pOut, "MIME-Version: 1.0\r\n");
986
- blob_appendf(pOut, "Content-Type: text/plain; charset=\"UTF-8\"\r\n");
985
+ blob_appendf(pOut, "MIME-Version: 1.0" CRLF);
986
+ blob_appendf(pOut, "Content-Type: text/plain; charset=\"UTF-8\"" CRLF);
987987
#if 0
988
- blob_appendf(pOut, "Content-Transfer-Encoding: base64\r\n\r\n");
988
+ blob_appendf(pOut, "Content-Transfer-Encoding: base64" CRLF CRLF);
989989
append_base64(pOut, pBody);
990990
#else
991
- blob_appendf(pOut, "Content-Transfer-Encoding: quoted-printable\r\n\r\n");
991
+ blob_appendf(pOut, "Content-Transfer-Encoding: quoted-printable" CRLF CRLF);
992992
append_quoted(pOut, pBody);
993993
#endif
994994
if( p->pStmt ){
995995
int i, rc;
996996
sqlite3_bind_text(p->pStmt, 1, blob_str(&all), -1, SQLITE_TRANSIENT);
@@ -1026,11 +1026,11 @@
10261026
char **azTo = 0;
10271027
int nTo = 0;
10281028
int i;
10291029
email_header_to(pHdr, &nTo, &azTo);
10301030
for(i=0; i<nTo; i++){
1031
- fossil_print("X-To-Test-%d: [%s]\r\n", i, azTo[i]);
1031
+ fossil_print("X-To-Test-%d: [%s]" CRLF, i, azTo[i]);
10321032
}
10331033
email_header_to_free(nTo, azTo);
10341034
blob_add_final_newline(&all);
10351035
fossil_print("%s", blob_str(&all));
10361036
}
@@ -1343,13 +1343,13 @@
13431343
blob_appendf(&hdr,"To: ");
13441344
for(i=3; i<g.argc; i++){
13451345
if( i>3 ) blob_append(&hdr, ", ", 2);
13461346
blob_appendf(&hdr, "<%s>", g.argv[i]);
13471347
}
1348
- blob_append(&hdr,"\r\n",2);
1348
+ blob_append(&hdr, CRLF, CRLF_SZ);
13491349
if( zSubject==0 ) zSubject = "fossil alerts test-message";
1350
- blob_appendf(&hdr, "Subject: %s\r\n", zSubject);
1350
+ blob_appendf(&hdr, "Subject: %s" CRLF, zSubject);
13511351
if( zSource ){
13521352
blob_read_from_file(&body, zSource, ExtFILE);
13531353
}else{
13541354
prompt_for_user_comment(&body, &prompt);
13551355
}
@@ -2314,12 +2314,12 @@
23142314
** been submitted. Send the appropriate email. */
23152315
Blob hdr, body;
23162316
AlertSender *pSender = alert_sender_new(0,0);
23172317
blob_init(&hdr,0,0);
23182318
blob_init(&body,0,0);
2319
- blob_appendf(&hdr, "To: <%s>\r\n", zEAddr);
2320
- blob_appendf(&hdr, "Subject: Unsubscribe Instructions\r\n");
2319
+ blob_appendf(&hdr, "To: <%s>" CRLF, zEAddr);
2320
+ blob_appendf(&hdr, "Subject: Unsubscribe Instructions" CRLF);
23212321
blob_appendf(&body, zUnsubMsg/*works-like:"%s%s%s%s%s%s"*/,
23222322
g.zBaseURL, g.zBaseURL, zCode, g.zBaseURL, g.zBaseURL, zCode);
23232323
alert_send(pSender, &hdr, &body, 0);
23242324
style_header("Unsubscribe Instructions Sent");
23252325
if( pSender->zErr ){
@@ -2739,19 +2739,19 @@
27392739
p->pNext = 0;
27402740
blob_init(&p->hdr, 0, 0);
27412741
zUuid = db_column_text(&q, 1);
27422742
zTitle = db_column_text(&q, 3);
27432743
if( p->needMod ){
2744
- blob_appendf(&p->hdr, "Subject: %s Pending Moderation: %s\r\n",
2744
+ blob_appendf(&p->hdr, "Subject: %s Pending Moderation: %s" CRLF,
27452745
zSub, zTitle);
27462746
}else{
2747
- blob_appendf(&p->hdr, "Subject: %s %s\r\n", zSub, zTitle);
2748
- blob_appendf(&p->hdr, "Message-Id: <%.32s@%s>\r\n",
2747
+ blob_appendf(&p->hdr, "Subject: %s %s" CRLF, zSub, zTitle);
2748
+ blob_appendf(&p->hdr, "Message-Id: <%.32s@%s>" CRLF,
27492749
zUuid, alert_hostname(zFrom));
27502750
zIrt = db_column_text(&q, 4);
27512751
if( zIrt && zIrt[0] ){
2752
- blob_appendf(&p->hdr, "In-Reply-To: <%.32s@%s>\r\n",
2752
+ blob_appendf(&p->hdr, "In-Reply-To: <%.32s@%s>" CRLF,
27532753
zIrt, alert_hostname(zFrom));
27542754
}
27552755
}
27562756
blob_init(&p->txt, 0, 0);
27572757
if( p->needMod ){
@@ -2915,12 +2915,12 @@
29152915
const char *zEAddr, /* Subscriber email address. Send to this. */
29162916
const char *zSub, /* Subscription codes */
29172917
const char *zRepoName, /* Name of the sending Fossil repostory */
29182918
const char *zUrl /* URL for the sending Fossil repostory */
29192919
){
2920
- blob_appendf(pHdr,"To: <%s>\r\n", zEAddr);
2921
- blob_appendf(pHdr,"Subject: %s Subscription to %s expires soon\r\n",
2920
+ blob_appendf(pHdr,"To: <%s>" CRLF, zEAddr);
2921
+ blob_appendf(pHdr,"Subject: %s Subscription to %s expires soon" CRLF,
29222922
zRepoName, zUrl);
29232923
blob_appendf(pBody,
29242924
"\nTo renew your subscription, click the following link:\n"
29252925
"\n %s/renew/%s\n\n",
29262926
zUrl, zCode
@@ -3167,17 +3167,17 @@
31673167
}
31683168
if( blob_size(&p->hdr)>0 ){
31693169
/* This alert should be sent as a separate email */
31703170
Blob fhdr, fbody;
31713171
blob_init(&fhdr, 0, 0);
3172
- blob_appendf(&fhdr, "To: <%s>\r\n", zEmail);
3172
+ blob_appendf(&fhdr, "To: <%s>" CRLF, zEmail);
31733173
blob_append(&fhdr, blob_buffer(&p->hdr), blob_size(&p->hdr));
31743174
blob_init(&fbody, blob_buffer(&p->txt), blob_size(&p->txt));
3175
- blob_appendf(&fhdr, "List-Unsubscribe: <%s/oneclickunsub/%s>\r\n",
3175
+ blob_appendf(&fhdr, "List-Unsubscribe: <%s/oneclickunsub/%s>" CRLF,
31763176
zUrl, zCode);
31773177
blob_appendf(&fhdr,
3178
- "List-Unsubscribe-Post: List-Unsubscribe=One-Click\r\n");
3178
+ "List-Unsubscribe-Post: List-Unsubscribe=One-Click" CRLF);
31793179
blob_appendf(&fbody, "\n-- \nUnsubscribe: %s/unsubscribe/%s\n",
31803180
zUrl, zCode);
31813181
/* blob_appendf(&fbody, "Subscription settings: %s/alerts/%s\n",
31823182
** zUrl, zCode); */
31833183
alert_send(pSender,&fhdr,&fbody,p->zFromName);
@@ -3186,12 +3186,12 @@
31863186
blob_reset(&fbody);
31873187
}else{
31883188
/* Events other than forum posts are gathered together into
31893189
** a single email message */
31903190
if( nHit==0 ){
3191
- blob_appendf(&hdr,"To: <%s>\r\n", zEmail);
3192
- blob_appendf(&hdr,"Subject: %s activity alert\r\n", zRepoName);
3191
+ blob_appendf(&hdr,"To: <%s>" CRLF, zEmail);
3192
+ blob_appendf(&hdr,"Subject: %s activity alert" CRLF, zRepoName);
31933193
blob_appendf(&body,
31943194
"This is an automated email sent by the Fossil repository "
31953195
"at %s to report changes.\n",
31963196
zUrl
31973197
);
@@ -3200,13 +3200,13 @@
32003200
blob_append(&body, "\n", 1);
32013201
blob_append(&body, blob_buffer(&p->txt), blob_size(&p->txt));
32023202
}
32033203
}
32043204
if( nHit==0 ) continue;
3205
- blob_appendf(&hdr, "List-Unsubscribe: <%s/oneclickunsub/%s>\r\n",
3205
+ blob_appendf(&hdr, "List-Unsubscribe: <%s/oneclickunsub/%s>" CRLF,
32063206
zUrl, zCode);
3207
- blob_appendf(&hdr, "List-Unsubscribe-Post: List-Unsubscribe=One-Click\r\n");
3207
+ blob_appendf(&hdr, "List-Unsubscribe-Post: List-Unsubscribe=One-Click"CRLF);
32083208
blob_appendf(&body,"\n-- \nSubscription info: %s/alerts/%s\n",
32093209
zUrl, zCode);
32103210
alert_send(pSender,&hdr,&body,0);
32113211
nSent++;
32123212
blob_truncate(&hdr, 0);
@@ -3332,11 +3332,11 @@
33323332
&& captcha_is_correct(0)
33333333
){
33343334
Blob hdr, body;
33353335
AlertSender *pSender = alert_sender_new(0,0);
33363336
blob_init(&hdr, 0, 0);
3337
- blob_appendf(&hdr, "To: <%s>\r\nSubject: %s administrator message\r\n",
3337
+ blob_appendf(&hdr, "To: <%s>" CRLF "Subject: %s administrator message" CRLF,
33383338
zAdminEmail, db_get("email-subname","Fossil Repo"));
33393339
blob_init(&body, 0, 0);
33403340
blob_appendf(&body, "Message from [%s]\n", PT("from")/*safe-for-%s*/);
33413341
blob_appendf(&body, "Subject: [%s]\n\n", PT("subject")/*safe-for-%s*/);
33423342
blob_appendf(&body, "%s", PT("msg")/*safe-for-%s*/);
@@ -3422,11 +3422,13 @@
34223422
blob_init(&body, 0, 0);
34233423
blob_init(&hdr, 0, 0);
34243424
blob_appendf(&body, "%s", PT("msg")/*safe-for-%s*/);
34253425
pSender = alert_sender_new(bTest2 ? "blob" : 0, 0);
34263426
if( zTo[0] ){
3427
- blob_appendf(&hdr, "To: <%s>\r\nSubject: %s %s\r\n", zTo, zSub, zSubject);
3427
+ blob_appendf(&hdr, "To: <%s>" CRLF
3428
+ "Subject: %s %s" CRLF,
3429
+ zTo, zSub, zSubject);
34283430
alert_send(pSender, &hdr, &body, 0);
34293431
}
34303432
if( bAll || bAA || bMods ){
34313433
Stmt q;
34323434
int nUsed = blob_size(&body);
@@ -3448,11 +3450,13 @@
34483450
}
34493451
while( db_step(&q)==SQLITE_ROW ){
34503452
const char *zCode = db_column_text(&q, 1);
34513453
zTo = db_column_text(&q, 0);
34523454
blob_truncate(&hdr, 0);
3453
- blob_appendf(&hdr, "To: <%s>\r\nSubject: %s %s\r\n", zTo, zSub, zSubject);
3455
+ blob_appendf(&hdr, "To: <%s>" CRLF
3456
+ "Subject: %s %s" CRLF,
3457
+ zTo, zSub, zSubject);
34543458
if( zURL ){
34553459
blob_truncate(&body, nUsed);
34563460
blob_appendf(&body,"\n-- \nSubscription info: %s/alerts/%s\n",
34573461
zURL, zCode);
34583462
}
34593463
--- src/alerts.c
+++ src/alerts.c
@@ -437,11 +437,11 @@
437 char zBuf[100];
438 n = blob_size(pMsg);
439 for(i=0; i<n; i+=54){
440 k = translateBase64(blob_buffer(pMsg)+i, i+54<n ? 54 : n-i, zBuf);
441 blob_append(pOut, zBuf, k);
442 blob_append(pOut, "\r\n", 2);
443 }
444 }
445 #endif
446
447 /*
@@ -457,19 +457,19 @@
457 || (c==' ' && zIn[0]!='\r' && zIn[0]!='\n')
458 ){
459 blob_append_char(pOut, c);
460 iCol++;
461 if( iCol>=70 ){
462 blob_append(pOut, "=\r\n", 3);
463 iCol = 0;
464 }
465 }else if( c=='\r' && zIn[0]=='\n' ){
466 zIn++;
467 blob_append(pOut, "\r\n", 2);
468 iCol = 0;
469 }else if( c=='\n' ){
470 blob_append(pOut, "\r\n", 2);
471 iCol = 0;
472 }else{
473 char x[3];
474 x[0] = '=';
475 x[1] = "0123456789ABCDEF"[(c>>4)&0xf];
@@ -960,37 +960,37 @@
960 }
961 blob_append(pOut, blob_buffer(pHdr), blob_size(pHdr));
962 if( p->zFrom==0 || p->zFrom[0]==0 ){
963 return; /* email-self is not set. Error will be reported separately */
964 }else if( zFromName ){
965 blob_appendf(pOut, "From: %s <%s@%s>\r\n",
966 zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom));
967 blob_appendf(pOut, "Sender: <%s>\r\n", p->zFrom);
968 }else{
969 blob_appendf(pOut, "From: <%s>\r\n", p->zFrom);
970 }
971 blob_appendf(pOut, "Date: %z\r\n", cgi_rfc822_datestamp(time(0)));
972 if( p->zListId && p->zListId[0] ){
973 blob_appendf(pOut, "List-Id: %s\r\n", p->zListId);
974 }
975 if( strstr(blob_str(pHdr), "\r\nMessage-Id:")==0 ){
976 /* Message-id format: "<$(date)x$(random)@$(from-host)>" where $(date) is
977 ** the current unix-time in hex, $(random) is a 64-bit random number,
978 ** and $(from) is the domain part of the email-self setting. */
979 sqlite3_randomness(sizeof(r1), &r1);
980 r2 = time(0);
981 blob_appendf(pOut, "Message-Id: <%llxx%016llx@%s>\r\n",
982 r2, r1, alert_hostname(p->zFrom));
983 }
984 blob_add_final_newline(pBody);
985 blob_appendf(pOut, "MIME-Version: 1.0\r\n");
986 blob_appendf(pOut, "Content-Type: text/plain; charset=\"UTF-8\"\r\n");
987 #if 0
988 blob_appendf(pOut, "Content-Transfer-Encoding: base64\r\n\r\n");
989 append_base64(pOut, pBody);
990 #else
991 blob_appendf(pOut, "Content-Transfer-Encoding: quoted-printable\r\n\r\n");
992 append_quoted(pOut, pBody);
993 #endif
994 if( p->pStmt ){
995 int i, rc;
996 sqlite3_bind_text(p->pStmt, 1, blob_str(&all), -1, SQLITE_TRANSIENT);
@@ -1026,11 +1026,11 @@
1026 char **azTo = 0;
1027 int nTo = 0;
1028 int i;
1029 email_header_to(pHdr, &nTo, &azTo);
1030 for(i=0; i<nTo; i++){
1031 fossil_print("X-To-Test-%d: [%s]\r\n", i, azTo[i]);
1032 }
1033 email_header_to_free(nTo, azTo);
1034 blob_add_final_newline(&all);
1035 fossil_print("%s", blob_str(&all));
1036 }
@@ -1343,13 +1343,13 @@
1343 blob_appendf(&hdr,"To: ");
1344 for(i=3; i<g.argc; i++){
1345 if( i>3 ) blob_append(&hdr, ", ", 2);
1346 blob_appendf(&hdr, "<%s>", g.argv[i]);
1347 }
1348 blob_append(&hdr,"\r\n",2);
1349 if( zSubject==0 ) zSubject = "fossil alerts test-message";
1350 blob_appendf(&hdr, "Subject: %s\r\n", zSubject);
1351 if( zSource ){
1352 blob_read_from_file(&body, zSource, ExtFILE);
1353 }else{
1354 prompt_for_user_comment(&body, &prompt);
1355 }
@@ -2314,12 +2314,12 @@
2314 ** been submitted. Send the appropriate email. */
2315 Blob hdr, body;
2316 AlertSender *pSender = alert_sender_new(0,0);
2317 blob_init(&hdr,0,0);
2318 blob_init(&body,0,0);
2319 blob_appendf(&hdr, "To: <%s>\r\n", zEAddr);
2320 blob_appendf(&hdr, "Subject: Unsubscribe Instructions\r\n");
2321 blob_appendf(&body, zUnsubMsg/*works-like:"%s%s%s%s%s%s"*/,
2322 g.zBaseURL, g.zBaseURL, zCode, g.zBaseURL, g.zBaseURL, zCode);
2323 alert_send(pSender, &hdr, &body, 0);
2324 style_header("Unsubscribe Instructions Sent");
2325 if( pSender->zErr ){
@@ -2739,19 +2739,19 @@
2739 p->pNext = 0;
2740 blob_init(&p->hdr, 0, 0);
2741 zUuid = db_column_text(&q, 1);
2742 zTitle = db_column_text(&q, 3);
2743 if( p->needMod ){
2744 blob_appendf(&p->hdr, "Subject: %s Pending Moderation: %s\r\n",
2745 zSub, zTitle);
2746 }else{
2747 blob_appendf(&p->hdr, "Subject: %s %s\r\n", zSub, zTitle);
2748 blob_appendf(&p->hdr, "Message-Id: <%.32s@%s>\r\n",
2749 zUuid, alert_hostname(zFrom));
2750 zIrt = db_column_text(&q, 4);
2751 if( zIrt && zIrt[0] ){
2752 blob_appendf(&p->hdr, "In-Reply-To: <%.32s@%s>\r\n",
2753 zIrt, alert_hostname(zFrom));
2754 }
2755 }
2756 blob_init(&p->txt, 0, 0);
2757 if( p->needMod ){
@@ -2915,12 +2915,12 @@
2915 const char *zEAddr, /* Subscriber email address. Send to this. */
2916 const char *zSub, /* Subscription codes */
2917 const char *zRepoName, /* Name of the sending Fossil repostory */
2918 const char *zUrl /* URL for the sending Fossil repostory */
2919 ){
2920 blob_appendf(pHdr,"To: <%s>\r\n", zEAddr);
2921 blob_appendf(pHdr,"Subject: %s Subscription to %s expires soon\r\n",
2922 zRepoName, zUrl);
2923 blob_appendf(pBody,
2924 "\nTo renew your subscription, click the following link:\n"
2925 "\n %s/renew/%s\n\n",
2926 zUrl, zCode
@@ -3167,17 +3167,17 @@
3167 }
3168 if( blob_size(&p->hdr)>0 ){
3169 /* This alert should be sent as a separate email */
3170 Blob fhdr, fbody;
3171 blob_init(&fhdr, 0, 0);
3172 blob_appendf(&fhdr, "To: <%s>\r\n", zEmail);
3173 blob_append(&fhdr, blob_buffer(&p->hdr), blob_size(&p->hdr));
3174 blob_init(&fbody, blob_buffer(&p->txt), blob_size(&p->txt));
3175 blob_appendf(&fhdr, "List-Unsubscribe: <%s/oneclickunsub/%s>\r\n",
3176 zUrl, zCode);
3177 blob_appendf(&fhdr,
3178 "List-Unsubscribe-Post: List-Unsubscribe=One-Click\r\n");
3179 blob_appendf(&fbody, "\n-- \nUnsubscribe: %s/unsubscribe/%s\n",
3180 zUrl, zCode);
3181 /* blob_appendf(&fbody, "Subscription settings: %s/alerts/%s\n",
3182 ** zUrl, zCode); */
3183 alert_send(pSender,&fhdr,&fbody,p->zFromName);
@@ -3186,12 +3186,12 @@
3186 blob_reset(&fbody);
3187 }else{
3188 /* Events other than forum posts are gathered together into
3189 ** a single email message */
3190 if( nHit==0 ){
3191 blob_appendf(&hdr,"To: <%s>\r\n", zEmail);
3192 blob_appendf(&hdr,"Subject: %s activity alert\r\n", zRepoName);
3193 blob_appendf(&body,
3194 "This is an automated email sent by the Fossil repository "
3195 "at %s to report changes.\n",
3196 zUrl
3197 );
@@ -3200,13 +3200,13 @@
3200 blob_append(&body, "\n", 1);
3201 blob_append(&body, blob_buffer(&p->txt), blob_size(&p->txt));
3202 }
3203 }
3204 if( nHit==0 ) continue;
3205 blob_appendf(&hdr, "List-Unsubscribe: <%s/oneclickunsub/%s>\r\n",
3206 zUrl, zCode);
3207 blob_appendf(&hdr, "List-Unsubscribe-Post: List-Unsubscribe=One-Click\r\n");
3208 blob_appendf(&body,"\n-- \nSubscription info: %s/alerts/%s\n",
3209 zUrl, zCode);
3210 alert_send(pSender,&hdr,&body,0);
3211 nSent++;
3212 blob_truncate(&hdr, 0);
@@ -3332,11 +3332,11 @@
3332 && captcha_is_correct(0)
3333 ){
3334 Blob hdr, body;
3335 AlertSender *pSender = alert_sender_new(0,0);
3336 blob_init(&hdr, 0, 0);
3337 blob_appendf(&hdr, "To: <%s>\r\nSubject: %s administrator message\r\n",
3338 zAdminEmail, db_get("email-subname","Fossil Repo"));
3339 blob_init(&body, 0, 0);
3340 blob_appendf(&body, "Message from [%s]\n", PT("from")/*safe-for-%s*/);
3341 blob_appendf(&body, "Subject: [%s]\n\n", PT("subject")/*safe-for-%s*/);
3342 blob_appendf(&body, "%s", PT("msg")/*safe-for-%s*/);
@@ -3422,11 +3422,13 @@
3422 blob_init(&body, 0, 0);
3423 blob_init(&hdr, 0, 0);
3424 blob_appendf(&body, "%s", PT("msg")/*safe-for-%s*/);
3425 pSender = alert_sender_new(bTest2 ? "blob" : 0, 0);
3426 if( zTo[0] ){
3427 blob_appendf(&hdr, "To: <%s>\r\nSubject: %s %s\r\n", zTo, zSub, zSubject);
 
 
3428 alert_send(pSender, &hdr, &body, 0);
3429 }
3430 if( bAll || bAA || bMods ){
3431 Stmt q;
3432 int nUsed = blob_size(&body);
@@ -3448,11 +3450,13 @@
3448 }
3449 while( db_step(&q)==SQLITE_ROW ){
3450 const char *zCode = db_column_text(&q, 1);
3451 zTo = db_column_text(&q, 0);
3452 blob_truncate(&hdr, 0);
3453 blob_appendf(&hdr, "To: <%s>\r\nSubject: %s %s\r\n", zTo, zSub, zSubject);
 
 
3454 if( zURL ){
3455 blob_truncate(&body, nUsed);
3456 blob_appendf(&body,"\n-- \nSubscription info: %s/alerts/%s\n",
3457 zURL, zCode);
3458 }
3459
--- src/alerts.c
+++ src/alerts.c
@@ -437,11 +437,11 @@
437 char zBuf[100];
438 n = blob_size(pMsg);
439 for(i=0; i<n; i+=54){
440 k = translateBase64(blob_buffer(pMsg)+i, i+54<n ? 54 : n-i, zBuf);
441 blob_append(pOut, zBuf, k);
442 blob_append(pOut, CRLF, CRLF_SZ);
443 }
444 }
445 #endif
446
447 /*
@@ -457,19 +457,19 @@
457 || (c==' ' && zIn[0]!='\r' && zIn[0]!='\n')
458 ){
459 blob_append_char(pOut, c);
460 iCol++;
461 if( iCol>=70 ){
462 blob_append(pOut, "=" CRLF, CRLF_SZ+1);
463 iCol = 0;
464 }
465 }else if( c=='\r' && zIn[0]=='\n' ){
466 zIn++;
467 blob_append(pOut, CRLF, CRLF_SZ);
468 iCol = 0;
469 }else if( c=='\n' ){
470 blob_append(pOut, CRLF, CRLF_SZ);
471 iCol = 0;
472 }else{
473 char x[3];
474 x[0] = '=';
475 x[1] = "0123456789ABCDEF"[(c>>4)&0xf];
@@ -960,37 +960,37 @@
960 }
961 blob_append(pOut, blob_buffer(pHdr), blob_size(pHdr));
962 if( p->zFrom==0 || p->zFrom[0]==0 ){
963 return; /* email-self is not set. Error will be reported separately */
964 }else if( zFromName ){
965 blob_appendf(pOut, "From: %s <%s@%s>" CRLF,
966 zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom));
967 blob_appendf(pOut, "Sender: <%s>" CRLF, p->zFrom);
968 }else{
969 blob_appendf(pOut, "From: <%s>" CRLF, p->zFrom);
970 }
971 blob_appendf(pOut, "Date: %z" CRLF, cgi_rfc822_datestamp(time(0)));
972 if( p->zListId && p->zListId[0] ){
973 blob_appendf(pOut, "List-Id: %s" CRLF, p->zListId);
974 }
975 if( strstr(blob_str(pHdr), CRLF "Message-Id:")==0 ){
976 /* Message-id format: "<$(date)x$(random)@$(from-host)>" where $(date) is
977 ** the current unix-time in hex, $(random) is a 64-bit random number,
978 ** and $(from) is the domain part of the email-self setting. */
979 sqlite3_randomness(sizeof(r1), &r1);
980 r2 = time(0);
981 blob_appendf(pOut, "Message-Id: <%llxx%016llx@%s>" CRLF,
982 r2, r1, alert_hostname(p->zFrom));
983 }
984 blob_add_final_newline(pBody);
985 blob_appendf(pOut, "MIME-Version: 1.0" CRLF);
986 blob_appendf(pOut, "Content-Type: text/plain; charset=\"UTF-8\"" CRLF);
987 #if 0
988 blob_appendf(pOut, "Content-Transfer-Encoding: base64" CRLF CRLF);
989 append_base64(pOut, pBody);
990 #else
991 blob_appendf(pOut, "Content-Transfer-Encoding: quoted-printable" CRLF CRLF);
992 append_quoted(pOut, pBody);
993 #endif
994 if( p->pStmt ){
995 int i, rc;
996 sqlite3_bind_text(p->pStmt, 1, blob_str(&all), -1, SQLITE_TRANSIENT);
@@ -1026,11 +1026,11 @@
1026 char **azTo = 0;
1027 int nTo = 0;
1028 int i;
1029 email_header_to(pHdr, &nTo, &azTo);
1030 for(i=0; i<nTo; i++){
1031 fossil_print("X-To-Test-%d: [%s]" CRLF, i, azTo[i]);
1032 }
1033 email_header_to_free(nTo, azTo);
1034 blob_add_final_newline(&all);
1035 fossil_print("%s", blob_str(&all));
1036 }
@@ -1343,13 +1343,13 @@
1343 blob_appendf(&hdr,"To: ");
1344 for(i=3; i<g.argc; i++){
1345 if( i>3 ) blob_append(&hdr, ", ", 2);
1346 blob_appendf(&hdr, "<%s>", g.argv[i]);
1347 }
1348 blob_append(&hdr, CRLF, CRLF_SZ);
1349 if( zSubject==0 ) zSubject = "fossil alerts test-message";
1350 blob_appendf(&hdr, "Subject: %s" CRLF, zSubject);
1351 if( zSource ){
1352 blob_read_from_file(&body, zSource, ExtFILE);
1353 }else{
1354 prompt_for_user_comment(&body, &prompt);
1355 }
@@ -2314,12 +2314,12 @@
2314 ** been submitted. Send the appropriate email. */
2315 Blob hdr, body;
2316 AlertSender *pSender = alert_sender_new(0,0);
2317 blob_init(&hdr,0,0);
2318 blob_init(&body,0,0);
2319 blob_appendf(&hdr, "To: <%s>" CRLF, zEAddr);
2320 blob_appendf(&hdr, "Subject: Unsubscribe Instructions" CRLF);
2321 blob_appendf(&body, zUnsubMsg/*works-like:"%s%s%s%s%s%s"*/,
2322 g.zBaseURL, g.zBaseURL, zCode, g.zBaseURL, g.zBaseURL, zCode);
2323 alert_send(pSender, &hdr, &body, 0);
2324 style_header("Unsubscribe Instructions Sent");
2325 if( pSender->zErr ){
@@ -2739,19 +2739,19 @@
2739 p->pNext = 0;
2740 blob_init(&p->hdr, 0, 0);
2741 zUuid = db_column_text(&q, 1);
2742 zTitle = db_column_text(&q, 3);
2743 if( p->needMod ){
2744 blob_appendf(&p->hdr, "Subject: %s Pending Moderation: %s" CRLF,
2745 zSub, zTitle);
2746 }else{
2747 blob_appendf(&p->hdr, "Subject: %s %s" CRLF, zSub, zTitle);
2748 blob_appendf(&p->hdr, "Message-Id: <%.32s@%s>" CRLF,
2749 zUuid, alert_hostname(zFrom));
2750 zIrt = db_column_text(&q, 4);
2751 if( zIrt && zIrt[0] ){
2752 blob_appendf(&p->hdr, "In-Reply-To: <%.32s@%s>" CRLF,
2753 zIrt, alert_hostname(zFrom));
2754 }
2755 }
2756 blob_init(&p->txt, 0, 0);
2757 if( p->needMod ){
@@ -2915,12 +2915,12 @@
2915 const char *zEAddr, /* Subscriber email address. Send to this. */
2916 const char *zSub, /* Subscription codes */
2917 const char *zRepoName, /* Name of the sending Fossil repostory */
2918 const char *zUrl /* URL for the sending Fossil repostory */
2919 ){
2920 blob_appendf(pHdr,"To: <%s>" CRLF, zEAddr);
2921 blob_appendf(pHdr,"Subject: %s Subscription to %s expires soon" CRLF,
2922 zRepoName, zUrl);
2923 blob_appendf(pBody,
2924 "\nTo renew your subscription, click the following link:\n"
2925 "\n %s/renew/%s\n\n",
2926 zUrl, zCode
@@ -3167,17 +3167,17 @@
3167 }
3168 if( blob_size(&p->hdr)>0 ){
3169 /* This alert should be sent as a separate email */
3170 Blob fhdr, fbody;
3171 blob_init(&fhdr, 0, 0);
3172 blob_appendf(&fhdr, "To: <%s>" CRLF, zEmail);
3173 blob_append(&fhdr, blob_buffer(&p->hdr), blob_size(&p->hdr));
3174 blob_init(&fbody, blob_buffer(&p->txt), blob_size(&p->txt));
3175 blob_appendf(&fhdr, "List-Unsubscribe: <%s/oneclickunsub/%s>" CRLF,
3176 zUrl, zCode);
3177 blob_appendf(&fhdr,
3178 "List-Unsubscribe-Post: List-Unsubscribe=One-Click" CRLF);
3179 blob_appendf(&fbody, "\n-- \nUnsubscribe: %s/unsubscribe/%s\n",
3180 zUrl, zCode);
3181 /* blob_appendf(&fbody, "Subscription settings: %s/alerts/%s\n",
3182 ** zUrl, zCode); */
3183 alert_send(pSender,&fhdr,&fbody,p->zFromName);
@@ -3186,12 +3186,12 @@
3186 blob_reset(&fbody);
3187 }else{
3188 /* Events other than forum posts are gathered together into
3189 ** a single email message */
3190 if( nHit==0 ){
3191 blob_appendf(&hdr,"To: <%s>" CRLF, zEmail);
3192 blob_appendf(&hdr,"Subject: %s activity alert" CRLF, zRepoName);
3193 blob_appendf(&body,
3194 "This is an automated email sent by the Fossil repository "
3195 "at %s to report changes.\n",
3196 zUrl
3197 );
@@ -3200,13 +3200,13 @@
3200 blob_append(&body, "\n", 1);
3201 blob_append(&body, blob_buffer(&p->txt), blob_size(&p->txt));
3202 }
3203 }
3204 if( nHit==0 ) continue;
3205 blob_appendf(&hdr, "List-Unsubscribe: <%s/oneclickunsub/%s>" CRLF,
3206 zUrl, zCode);
3207 blob_appendf(&hdr, "List-Unsubscribe-Post: List-Unsubscribe=One-Click"CRLF);
3208 blob_appendf(&body,"\n-- \nSubscription info: %s/alerts/%s\n",
3209 zUrl, zCode);
3210 alert_send(pSender,&hdr,&body,0);
3211 nSent++;
3212 blob_truncate(&hdr, 0);
@@ -3332,11 +3332,11 @@
3332 && captcha_is_correct(0)
3333 ){
3334 Blob hdr, body;
3335 AlertSender *pSender = alert_sender_new(0,0);
3336 blob_init(&hdr, 0, 0);
3337 blob_appendf(&hdr, "To: <%s>" CRLF "Subject: %s administrator message" CRLF,
3338 zAdminEmail, db_get("email-subname","Fossil Repo"));
3339 blob_init(&body, 0, 0);
3340 blob_appendf(&body, "Message from [%s]\n", PT("from")/*safe-for-%s*/);
3341 blob_appendf(&body, "Subject: [%s]\n\n", PT("subject")/*safe-for-%s*/);
3342 blob_appendf(&body, "%s", PT("msg")/*safe-for-%s*/);
@@ -3422,11 +3422,13 @@
3422 blob_init(&body, 0, 0);
3423 blob_init(&hdr, 0, 0);
3424 blob_appendf(&body, "%s", PT("msg")/*safe-for-%s*/);
3425 pSender = alert_sender_new(bTest2 ? "blob" : 0, 0);
3426 if( zTo[0] ){
3427 blob_appendf(&hdr, "To: <%s>" CRLF
3428 "Subject: %s %s" CRLF,
3429 zTo, zSub, zSubject);
3430 alert_send(pSender, &hdr, &body, 0);
3431 }
3432 if( bAll || bAA || bMods ){
3433 Stmt q;
3434 int nUsed = blob_size(&body);
@@ -3448,11 +3450,13 @@
3450 }
3451 while( db_step(&q)==SQLITE_ROW ){
3452 const char *zCode = db_column_text(&q, 1);
3453 zTo = db_column_text(&q, 0);
3454 blob_truncate(&hdr, 0);
3455 blob_appendf(&hdr, "To: <%s>" CRLF
3456 "Subject: %s %s" CRLF,
3457 zTo, zSub, zSubject);
3458 if( zURL ){
3459 blob_truncate(&body, nUsed);
3460 blob_appendf(&body,"\n-- \nSubscription info: %s/alerts/%s\n",
3461 zURL, zCode);
3462 }
3463
+2 -2
--- src/captcha.c
+++ src/captcha.c
@@ -802,11 +802,11 @@
802802
@ </form>
803803
if( !bTest ){
804804
if( P("fossil-goto")==0 ){
805805
cgi_set_cookie("fossil-goto", cgi_reconstruct_original_url(), 0, 600);
806806
}
807
- cgi_append_header("X-Robot: 1\r\n");
807
+ cgi_append_header("X-Robot: 1" CRLF);
808808
style_finish_page();
809809
}
810810
return 1;
811811
}
812812
@@ -826,11 +826,11 @@
826826
if( bTest==0 ){
827827
if( !login_cookie_wellformed() ){
828828
/* ^^^^--- Don't overwrite a valid login on another repo! */
829829
login_set_anon_cookie(0, 0);
830830
}
831
- cgi_append_header("X-Robot: 0\r\n");
831
+ cgi_append_header("X-Robot: 0" CRLF);
832832
}
833833
login_redirect_to_g();
834834
}else{
835835
g.isHuman = 0;
836836
(void)exclude_spiders(bTest);
837837
--- src/captcha.c
+++ src/captcha.c
@@ -802,11 +802,11 @@
802 @ </form>
803 if( !bTest ){
804 if( P("fossil-goto")==0 ){
805 cgi_set_cookie("fossil-goto", cgi_reconstruct_original_url(), 0, 600);
806 }
807 cgi_append_header("X-Robot: 1\r\n");
808 style_finish_page();
809 }
810 return 1;
811 }
812
@@ -826,11 +826,11 @@
826 if( bTest==0 ){
827 if( !login_cookie_wellformed() ){
828 /* ^^^^--- Don't overwrite a valid login on another repo! */
829 login_set_anon_cookie(0, 0);
830 }
831 cgi_append_header("X-Robot: 0\r\n");
832 }
833 login_redirect_to_g();
834 }else{
835 g.isHuman = 0;
836 (void)exclude_spiders(bTest);
837
--- src/captcha.c
+++ src/captcha.c
@@ -802,11 +802,11 @@
802 @ </form>
803 if( !bTest ){
804 if( P("fossil-goto")==0 ){
805 cgi_set_cookie("fossil-goto", cgi_reconstruct_original_url(), 0, 600);
806 }
807 cgi_append_header("X-Robot: 1" CRLF);
808 style_finish_page();
809 }
810 return 1;
811 }
812
@@ -826,11 +826,11 @@
826 if( bTest==0 ){
827 if( !login_cookie_wellformed() ){
828 /* ^^^^--- Don't overwrite a valid login on another repo! */
829 login_set_anon_cookie(0, 0);
830 }
831 cgi_append_header("X-Robot: 0" CRLF);
832 }
833 login_redirect_to_g();
834 }else{
835 g.isHuman = 0;
836 (void)exclude_spiders(bTest);
837
+24 -24
--- src/cgi.c
+++ src/cgi.c
@@ -316,15 +316,15 @@
316316
if( g.zBaseURL!=0 && fossil_strncmp(g.zBaseURL, "https:", 6)==0 ){
317317
zSecure = " secure;";
318318
}
319319
if( lifetime!=0 ){
320320
blob_appendf(&extraHeader,
321
- "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; %s\r\n",
321
+ "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; %s" CRLF,
322322
zName, lifetime>0 ? zValue : "null", zPath, lifetime, zSecure);
323323
}else{
324324
blob_appendf(&extraHeader,
325
- "Set-Cookie: %s=%t; Path=%s; HttpOnly; %s\r\n",
325
+ "Set-Cookie: %s=%t; Path=%s; HttpOnly; %s" CRLF,
326326
zName, zValue, zPath, zSecure);
327327
}
328328
}
329329
330330
@@ -489,45 +489,45 @@
489489
&& fossil_strcmp(P("REQUEST_METHOD"),"GET")==0
490490
){
491491
iReplyStatus = 206;
492492
zReplyStatus = "Partial Content";
493493
}
494
- blob_appendf(&hdr, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
495
- blob_appendf(&hdr, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
496
- blob_appendf(&hdr, "Connection: close\r\n");
497
- blob_appendf(&hdr, "X-UA-Compatible: IE=edge\r\n");
494
+ blob_appendf(&hdr, "HTTP/1.0 %d %s" CRLF, iReplyStatus, zReplyStatus);
495
+ blob_appendf(&hdr, "Date: %s" CRLF, cgi_rfc822_datestamp(time(0)));
496
+ blob_appendf(&hdr, "Connection: close" CRLF);
497
+ blob_appendf(&hdr, "X-UA-Compatible: IE=edge" CRLF);
498498
}else{
499499
assert( rangeEnd==0 );
500
- blob_appendf(&hdr, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
500
+ blob_appendf(&hdr, "Status: %d %s" CRLF, iReplyStatus, zReplyStatus);
501501
}
502502
if( etag_tag()[0]!=0
503503
&& iReplyStatus==200
504504
&& strcmp(zContentType,"text/html")!=0
505505
){
506506
/* Do not cache HTML replies as those will have been generated and
507507
** will likely, therefore, contains a nonce and we want that nonce to
508508
** be different every time. */
509
- blob_appendf(&hdr, "ETag: %s\r\n", etag_tag());
510
- blob_appendf(&hdr, "Cache-Control: max-age=%d\r\n", etag_maxage());
509
+ blob_appendf(&hdr, "ETag: %s" CRLF, etag_tag());
510
+ blob_appendf(&hdr, "Cache-Control: max-age=%d" CRLF, etag_maxage());
511511
if( etag_mtime()>0 ){
512
- blob_appendf(&hdr, "Last-Modified: %s\r\n",
512
+ blob_appendf(&hdr, "Last-Modified: %s" CRLF,
513513
cgi_rfc822_datestamp(etag_mtime()));
514514
}
515515
}else if( g.isConst ){
516516
/* isConst means that the reply is guaranteed to be invariant, even
517517
** after configuration changes and/or Fossil binary recompiles. */
518
- blob_appendf(&hdr, "Cache-Control: max-age=315360000, immutable\r\n");
518
+ blob_appendf(&hdr, "Cache-Control: max-age=315360000, immutable" CRLF);
519519
}else{
520
- blob_appendf(&hdr, "Cache-control: no-cache\r\n");
520
+ blob_appendf(&hdr, "Cache-control: no-cache" CRLF);
521521
}
522522
523523
if( blob_size(&extraHeader)>0 ){
524524
blob_appendf(&hdr, "%s", blob_buffer(&extraHeader));
525525
}
526526
527527
/* Add headers to turn on useful security options in browsers. */
528
- blob_appendf(&hdr, "X-Frame-Options: SAMEORIGIN\r\n");
528
+ blob_appendf(&hdr, "X-Frame-Options: SAMEORIGIN" CRLF);
529529
/* The previous stops fossil pages appearing in frames or iframes, preventing
530530
** click-jacking attacks on supporting browsers.
531531
**
532532
** Other good headers would be
533533
** Strict-Transport-Security: max-age=62208000
@@ -541,11 +541,11 @@
541541
** These headers are probably best added by the web server hosting fossil as
542542
** a CGI script.
543543
*/
544544
545545
if( iReplyStatus!=304 ) {
546
- blob_appendf(&hdr, "Content-Type: %s%s\r\n", zContentType,
546
+ blob_appendf(&hdr, "Content-Type: %s%s" CRLF, zContentType,
547547
content_type_charset(zContentType));
548548
if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
549549
cgi_combine_header_and_body();
550550
blob_compress(&cgiContent[0], &cgiContent[0]);
551551
}
@@ -557,24 +557,24 @@
557557
int size = blob_size(&cgiContent[i]);
558558
if( size>0 ) gzip_step(blob_buffer(&cgiContent[i]), size);
559559
blob_reset(&cgiContent[i]);
560560
}
561561
gzip_finish(&cgiContent[0]);
562
- blob_appendf(&hdr, "Content-Encoding: gzip\r\n");
563
- blob_appendf(&hdr, "Vary: Accept-Encoding\r\n");
562
+ blob_appendf(&hdr, "Content-Encoding: gzip" CRLF);
563
+ blob_appendf(&hdr, "Vary: Accept-Encoding" CRLF);
564564
}
565565
total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
566566
if( iReplyStatus==206 ){
567
- blob_appendf(&hdr, "Content-Range: bytes %d-%d/%d\r\n",
567
+ blob_appendf(&hdr, "Content-Range: bytes %d-%d/%d" CRLF,
568568
rangeStart, rangeEnd-1, total_size);
569569
total_size = rangeEnd - rangeStart;
570570
}
571
- blob_appendf(&hdr, "Content-Length: %d\r\n", total_size);
571
+ blob_appendf(&hdr, "Content-Length: %d" CRLF, total_size);
572572
}else{
573573
total_size = 0;
574574
}
575
- blob_appendf(&hdr, "\r\n");
575
+ blob_appendf(&hdr, CRLF);
576576
cgi_fwrite(blob_buffer(&hdr), blob_size(&hdr));
577577
blob_reset(&hdr);
578578
if( total_size>0
579579
&& iReplyStatus!=304
580580
&& fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
@@ -620,18 +620,18 @@
620620
){
621621
char *zLocation;
622622
CGIDEBUG(("redirect to %s\n", zURL));
623623
if( fossil_strncmp(zURL,"http:",5)==0
624624
|| fossil_strncmp(zURL,"https:",6)==0 ){
625
- zLocation = mprintf("Location: %s\r\n", zURL);
625
+ zLocation = mprintf("Location: %s" CRLF, zURL);
626626
}else if( *zURL=='/' ){
627627
int n1 = (int)strlen(g.zBaseURL);
628628
int n2 = (int)strlen(g.zTop);
629629
if( g.zBaseURL[n1-1]=='/' ) zURL++;
630
- zLocation = mprintf("Location: %.*s%s\r\n", n1-n2, g.zBaseURL, zURL);
630
+ zLocation = mprintf("Location: %.*s%s" CRLF, n1-n2, g.zBaseURL, zURL);
631631
}else{
632
- zLocation = mprintf("Location: %s/%s\r\n", g.zBaseURL, zURL);
632
+ zLocation = mprintf("Location: %s/%s" CRLF, g.zBaseURL, zURL);
633633
}
634634
cgi_append_header(zLocation);
635635
cgi_reset_content();
636636
cgi_printf("<html>\n<p>Redirect to %h</p>\n</html>\n", zLocation);
637637
cgi_set_status(iStat, zStat);
@@ -658,11 +658,11 @@
658658
void cgi_content_disposition_filename(const char *zFilename){
659659
char *z;
660660
int i, n;
661661
662662
/* 0123456789 123456789 123456789 123456789 123456*/
663
- z = mprintf("Content-Disposition: attachment; filename=\"%s\";\r\n",
663
+ z = mprintf("Content-Disposition: attachment; filename=\"%s\";" CRLF,
664664
file_tail(zFilename));
665665
n = (int)strlen(z);
666666
for(i=43; i<n-4; i++){
667667
char c = z[i];
668668
if( fossil_isalnum(c) ) continue;
@@ -1014,11 +1014,11 @@
10141014
*pLen -= i;
10151015
return z;
10161016
}
10171017
10181018
/*
1019
-** The input *pz points to content that is terminated by a "\r\n"
1019
+** The input *pz points to content that is terminated by a \n or \r\n
10201020
** followed by the boundary marker zBoundary. An extra "--" may or
10211021
** may not be appended to the boundary marker. There are *pLen characters
10221022
** in *pz.
10231023
**
10241024
** This routine adds a "\000" to the end of the content (overwriting
10251025
--- src/cgi.c
+++ src/cgi.c
@@ -316,15 +316,15 @@
316 if( g.zBaseURL!=0 && fossil_strncmp(g.zBaseURL, "https:", 6)==0 ){
317 zSecure = " secure;";
318 }
319 if( lifetime!=0 ){
320 blob_appendf(&extraHeader,
321 "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; %s\r\n",
322 zName, lifetime>0 ? zValue : "null", zPath, lifetime, zSecure);
323 }else{
324 blob_appendf(&extraHeader,
325 "Set-Cookie: %s=%t; Path=%s; HttpOnly; %s\r\n",
326 zName, zValue, zPath, zSecure);
327 }
328 }
329
330
@@ -489,45 +489,45 @@
489 && fossil_strcmp(P("REQUEST_METHOD"),"GET")==0
490 ){
491 iReplyStatus = 206;
492 zReplyStatus = "Partial Content";
493 }
494 blob_appendf(&hdr, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
495 blob_appendf(&hdr, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
496 blob_appendf(&hdr, "Connection: close\r\n");
497 blob_appendf(&hdr, "X-UA-Compatible: IE=edge\r\n");
498 }else{
499 assert( rangeEnd==0 );
500 blob_appendf(&hdr, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
501 }
502 if( etag_tag()[0]!=0
503 && iReplyStatus==200
504 && strcmp(zContentType,"text/html")!=0
505 ){
506 /* Do not cache HTML replies as those will have been generated and
507 ** will likely, therefore, contains a nonce and we want that nonce to
508 ** be different every time. */
509 blob_appendf(&hdr, "ETag: %s\r\n", etag_tag());
510 blob_appendf(&hdr, "Cache-Control: max-age=%d\r\n", etag_maxage());
511 if( etag_mtime()>0 ){
512 blob_appendf(&hdr, "Last-Modified: %s\r\n",
513 cgi_rfc822_datestamp(etag_mtime()));
514 }
515 }else if( g.isConst ){
516 /* isConst means that the reply is guaranteed to be invariant, even
517 ** after configuration changes and/or Fossil binary recompiles. */
518 blob_appendf(&hdr, "Cache-Control: max-age=315360000, immutable\r\n");
519 }else{
520 blob_appendf(&hdr, "Cache-control: no-cache\r\n");
521 }
522
523 if( blob_size(&extraHeader)>0 ){
524 blob_appendf(&hdr, "%s", blob_buffer(&extraHeader));
525 }
526
527 /* Add headers to turn on useful security options in browsers. */
528 blob_appendf(&hdr, "X-Frame-Options: SAMEORIGIN\r\n");
529 /* The previous stops fossil pages appearing in frames or iframes, preventing
530 ** click-jacking attacks on supporting browsers.
531 **
532 ** Other good headers would be
533 ** Strict-Transport-Security: max-age=62208000
@@ -541,11 +541,11 @@
541 ** These headers are probably best added by the web server hosting fossil as
542 ** a CGI script.
543 */
544
545 if( iReplyStatus!=304 ) {
546 blob_appendf(&hdr, "Content-Type: %s%s\r\n", zContentType,
547 content_type_charset(zContentType));
548 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
549 cgi_combine_header_and_body();
550 blob_compress(&cgiContent[0], &cgiContent[0]);
551 }
@@ -557,24 +557,24 @@
557 int size = blob_size(&cgiContent[i]);
558 if( size>0 ) gzip_step(blob_buffer(&cgiContent[i]), size);
559 blob_reset(&cgiContent[i]);
560 }
561 gzip_finish(&cgiContent[0]);
562 blob_appendf(&hdr, "Content-Encoding: gzip\r\n");
563 blob_appendf(&hdr, "Vary: Accept-Encoding\r\n");
564 }
565 total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
566 if( iReplyStatus==206 ){
567 blob_appendf(&hdr, "Content-Range: bytes %d-%d/%d\r\n",
568 rangeStart, rangeEnd-1, total_size);
569 total_size = rangeEnd - rangeStart;
570 }
571 blob_appendf(&hdr, "Content-Length: %d\r\n", total_size);
572 }else{
573 total_size = 0;
574 }
575 blob_appendf(&hdr, "\r\n");
576 cgi_fwrite(blob_buffer(&hdr), blob_size(&hdr));
577 blob_reset(&hdr);
578 if( total_size>0
579 && iReplyStatus!=304
580 && fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
@@ -620,18 +620,18 @@
620 ){
621 char *zLocation;
622 CGIDEBUG(("redirect to %s\n", zURL));
623 if( fossil_strncmp(zURL,"http:",5)==0
624 || fossil_strncmp(zURL,"https:",6)==0 ){
625 zLocation = mprintf("Location: %s\r\n", zURL);
626 }else if( *zURL=='/' ){
627 int n1 = (int)strlen(g.zBaseURL);
628 int n2 = (int)strlen(g.zTop);
629 if( g.zBaseURL[n1-1]=='/' ) zURL++;
630 zLocation = mprintf("Location: %.*s%s\r\n", n1-n2, g.zBaseURL, zURL);
631 }else{
632 zLocation = mprintf("Location: %s/%s\r\n", g.zBaseURL, zURL);
633 }
634 cgi_append_header(zLocation);
635 cgi_reset_content();
636 cgi_printf("<html>\n<p>Redirect to %h</p>\n</html>\n", zLocation);
637 cgi_set_status(iStat, zStat);
@@ -658,11 +658,11 @@
658 void cgi_content_disposition_filename(const char *zFilename){
659 char *z;
660 int i, n;
661
662 /* 0123456789 123456789 123456789 123456789 123456*/
663 z = mprintf("Content-Disposition: attachment; filename=\"%s\";\r\n",
664 file_tail(zFilename));
665 n = (int)strlen(z);
666 for(i=43; i<n-4; i++){
667 char c = z[i];
668 if( fossil_isalnum(c) ) continue;
@@ -1014,11 +1014,11 @@
1014 *pLen -= i;
1015 return z;
1016 }
1017
1018 /*
1019 ** The input *pz points to content that is terminated by a "\r\n"
1020 ** followed by the boundary marker zBoundary. An extra "--" may or
1021 ** may not be appended to the boundary marker. There are *pLen characters
1022 ** in *pz.
1023 **
1024 ** This routine adds a "\000" to the end of the content (overwriting
1025
--- src/cgi.c
+++ src/cgi.c
@@ -316,15 +316,15 @@
316 if( g.zBaseURL!=0 && fossil_strncmp(g.zBaseURL, "https:", 6)==0 ){
317 zSecure = " secure;";
318 }
319 if( lifetime!=0 ){
320 blob_appendf(&extraHeader,
321 "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly; %s" CRLF,
322 zName, lifetime>0 ? zValue : "null", zPath, lifetime, zSecure);
323 }else{
324 blob_appendf(&extraHeader,
325 "Set-Cookie: %s=%t; Path=%s; HttpOnly; %s" CRLF,
326 zName, zValue, zPath, zSecure);
327 }
328 }
329
330
@@ -489,45 +489,45 @@
489 && fossil_strcmp(P("REQUEST_METHOD"),"GET")==0
490 ){
491 iReplyStatus = 206;
492 zReplyStatus = "Partial Content";
493 }
494 blob_appendf(&hdr, "HTTP/1.0 %d %s" CRLF, iReplyStatus, zReplyStatus);
495 blob_appendf(&hdr, "Date: %s" CRLF, cgi_rfc822_datestamp(time(0)));
496 blob_appendf(&hdr, "Connection: close" CRLF);
497 blob_appendf(&hdr, "X-UA-Compatible: IE=edge" CRLF);
498 }else{
499 assert( rangeEnd==0 );
500 blob_appendf(&hdr, "Status: %d %s" CRLF, iReplyStatus, zReplyStatus);
501 }
502 if( etag_tag()[0]!=0
503 && iReplyStatus==200
504 && strcmp(zContentType,"text/html")!=0
505 ){
506 /* Do not cache HTML replies as those will have been generated and
507 ** will likely, therefore, contains a nonce and we want that nonce to
508 ** be different every time. */
509 blob_appendf(&hdr, "ETag: %s" CRLF, etag_tag());
510 blob_appendf(&hdr, "Cache-Control: max-age=%d" CRLF, etag_maxage());
511 if( etag_mtime()>0 ){
512 blob_appendf(&hdr, "Last-Modified: %s" CRLF,
513 cgi_rfc822_datestamp(etag_mtime()));
514 }
515 }else if( g.isConst ){
516 /* isConst means that the reply is guaranteed to be invariant, even
517 ** after configuration changes and/or Fossil binary recompiles. */
518 blob_appendf(&hdr, "Cache-Control: max-age=315360000, immutable" CRLF);
519 }else{
520 blob_appendf(&hdr, "Cache-control: no-cache" CRLF);
521 }
522
523 if( blob_size(&extraHeader)>0 ){
524 blob_appendf(&hdr, "%s", blob_buffer(&extraHeader));
525 }
526
527 /* Add headers to turn on useful security options in browsers. */
528 blob_appendf(&hdr, "X-Frame-Options: SAMEORIGIN" CRLF);
529 /* The previous stops fossil pages appearing in frames or iframes, preventing
530 ** click-jacking attacks on supporting browsers.
531 **
532 ** Other good headers would be
533 ** Strict-Transport-Security: max-age=62208000
@@ -541,11 +541,11 @@
541 ** These headers are probably best added by the web server hosting fossil as
542 ** a CGI script.
543 */
544
545 if( iReplyStatus!=304 ) {
546 blob_appendf(&hdr, "Content-Type: %s%s" CRLF, zContentType,
547 content_type_charset(zContentType));
548 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
549 cgi_combine_header_and_body();
550 blob_compress(&cgiContent[0], &cgiContent[0]);
551 }
@@ -557,24 +557,24 @@
557 int size = blob_size(&cgiContent[i]);
558 if( size>0 ) gzip_step(blob_buffer(&cgiContent[i]), size);
559 blob_reset(&cgiContent[i]);
560 }
561 gzip_finish(&cgiContent[0]);
562 blob_appendf(&hdr, "Content-Encoding: gzip" CRLF);
563 blob_appendf(&hdr, "Vary: Accept-Encoding" CRLF);
564 }
565 total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
566 if( iReplyStatus==206 ){
567 blob_appendf(&hdr, "Content-Range: bytes %d-%d/%d" CRLF,
568 rangeStart, rangeEnd-1, total_size);
569 total_size = rangeEnd - rangeStart;
570 }
571 blob_appendf(&hdr, "Content-Length: %d" CRLF, total_size);
572 }else{
573 total_size = 0;
574 }
575 blob_appendf(&hdr, CRLF);
576 cgi_fwrite(blob_buffer(&hdr), blob_size(&hdr));
577 blob_reset(&hdr);
578 if( total_size>0
579 && iReplyStatus!=304
580 && fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
@@ -620,18 +620,18 @@
620 ){
621 char *zLocation;
622 CGIDEBUG(("redirect to %s\n", zURL));
623 if( fossil_strncmp(zURL,"http:",5)==0
624 || fossil_strncmp(zURL,"https:",6)==0 ){
625 zLocation = mprintf("Location: %s" CRLF, zURL);
626 }else if( *zURL=='/' ){
627 int n1 = (int)strlen(g.zBaseURL);
628 int n2 = (int)strlen(g.zTop);
629 if( g.zBaseURL[n1-1]=='/' ) zURL++;
630 zLocation = mprintf("Location: %.*s%s" CRLF, n1-n2, g.zBaseURL, zURL);
631 }else{
632 zLocation = mprintf("Location: %s/%s" CRLF, g.zBaseURL, zURL);
633 }
634 cgi_append_header(zLocation);
635 cgi_reset_content();
636 cgi_printf("<html>\n<p>Redirect to %h</p>\n</html>\n", zLocation);
637 cgi_set_status(iStat, zStat);
@@ -658,11 +658,11 @@
658 void cgi_content_disposition_filename(const char *zFilename){
659 char *z;
660 int i, n;
661
662 /* 0123456789 123456789 123456789 123456789 123456*/
663 z = mprintf("Content-Disposition: attachment; filename=\"%s\";" CRLF,
664 file_tail(zFilename));
665 n = (int)strlen(z);
666 for(i=43; i<n-4; i++){
667 char c = z[i];
668 if( fossil_isalnum(c) ) continue;
@@ -1014,11 +1014,11 @@
1014 *pLen -= i;
1015 return z;
1016 }
1017
1018 /*
1019 ** The input *pz points to content that is terminated by a \n or \r\n
1020 ** followed by the boundary marker zBoundary. An extra "--" may or
1021 ** may not be appended to the boundary marker. There are *pLen characters
1022 ** in *pz.
1023 **
1024 ** This routine adds a "\000" to the end of the content (overwriting
1025
+22 -13
--- src/chat.c
+++ src/chat.c
@@ -1302,26 +1302,34 @@
13021302
"--------%016llu%016llu%016llu", r[0], r[1], r[2]);
13031303
blob_appendf(&up, "%s", zBoundary);
13041304
zLMTime = db_text(0,
13051305
"SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S','now','localtime')");
13061306
if( zLMTime ){
1307
- blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"lmtime\"\r\n"
1308
- "\r\n%z\r\n%s", zLMTime, zBoundary);
1307
+ blob_appendf(&up,
1308
+ CRLF "Content-Disposition: form-data; name=\"lmtime\"" CRLF
1309
+ CRLF "%z" CRLF "%s",
1310
+ zLMTime, zBoundary);
13091311
}
13101312
if( g.url.user && g.url.user[0] ){
1311
- blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"resid\"\r\n"
1312
- "\r\n%z\r\n%s", obscure(g.url.user), zBoundary);
1313
+ blob_appendf(&up,
1314
+ CRLF "Content-Disposition: form-data; name=\"resid\"" CRLF
1315
+ CRLF "%z" CRLF "%s",
1316
+ obscure(g.url.user), zBoundary);
13131317
}
13141318
zPw = g.url.passwd;
13151319
if( zPw==0 && isDefaultUrl ) zPw = unobscure(db_get("last-sync-pw", 0));
13161320
if( zPw && zPw[0] ){
1317
- blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"token\"\r\n"
1318
- "\r\n%z\r\n%s", obscure(zPw), zBoundary);
1321
+ blob_appendf(&up,
1322
+ CRLF "Content-Disposition: form-data; name=\"token\"" CRLF
1323
+ CRLF "%z" CRLF "%s",
1324
+ obscure(zPw), zBoundary);
13191325
}
13201326
if( zMsg && zMsg[0] ){
1321
- blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"msg\"\r\n"
1322
- "\r\n%s\r\n%s", zMsg, zBoundary);
1327
+ blob_appendf(&up,
1328
+ CRLF "Content-Disposition: form-data; name=\"msg\"" CRLF
1329
+ CRLF "%s" CRLF "%s",
1330
+ zMsg, zBoundary);
13231331
}
13241332
if( zFilename && blob_read_from_file(&fcontent, zFilename, ExtFILE)>0 ){
13251333
char *zFN = mprintf("%s", file_tail(zAs ? zAs : zFilename));
13261334
int i;
13271335
const char *zMime = mimetype_from_name(zFN);
@@ -1330,17 +1338,18 @@
13301338
if( fossil_isalnum(c) ) continue;
13311339
if( c=='.' ) continue;
13321340
if( c=='-' ) continue;
13331341
zFN[i] = '_';
13341342
}
1335
- blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"file\";"
1336
- " filename=\"%s\"\r\n", zFN);
1337
- blob_appendf(&up,"Content-Type: %s\r\n\r\n", zMime);
1343
+ blob_appendf(&up,
1344
+ CRLF "Content-Disposition: form-data; name=\"file\";"
1345
+ " filename=\"%s\"" CRLF, zFN);
1346
+ blob_appendf(&up,"Content-Type: %s" CRLF CRLF, zMime);
13381347
blob_append(&up, fcontent.aData, fcontent.nUsed);
1339
- blob_appendf(&up,"\r\n%s", zBoundary);
1348
+ blob_appendf(&up,CRLF "%s", zBoundary);
13401349
}
1341
- blob_append(&up,"--\r\n", 4);
1350
+ blob_append(&up,"--" CRLF, CRLF_SZ+2);
13421351
http_exchange(&up, &down, mFlags, 4, "multipart/form-data");
13431352
blob_reset(&up);
13441353
if( sqlite3_strglob("{\"isError\": true,*", blob_str(&down))==0 ){
13451354
if( strstr(blob_str(&down), "not logged in")!=0 ){
13461355
fossil_print("ERROR: username and/or password is incorrect\n");
13471356
--- src/chat.c
+++ src/chat.c
@@ -1302,26 +1302,34 @@
1302 "--------%016llu%016llu%016llu", r[0], r[1], r[2]);
1303 blob_appendf(&up, "%s", zBoundary);
1304 zLMTime = db_text(0,
1305 "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S','now','localtime')");
1306 if( zLMTime ){
1307 blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"lmtime\"\r\n"
1308 "\r\n%z\r\n%s", zLMTime, zBoundary);
 
 
1309 }
1310 if( g.url.user && g.url.user[0] ){
1311 blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"resid\"\r\n"
1312 "\r\n%z\r\n%s", obscure(g.url.user), zBoundary);
 
 
1313 }
1314 zPw = g.url.passwd;
1315 if( zPw==0 && isDefaultUrl ) zPw = unobscure(db_get("last-sync-pw", 0));
1316 if( zPw && zPw[0] ){
1317 blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"token\"\r\n"
1318 "\r\n%z\r\n%s", obscure(zPw), zBoundary);
 
 
1319 }
1320 if( zMsg && zMsg[0] ){
1321 blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"msg\"\r\n"
1322 "\r\n%s\r\n%s", zMsg, zBoundary);
 
 
1323 }
1324 if( zFilename && blob_read_from_file(&fcontent, zFilename, ExtFILE)>0 ){
1325 char *zFN = mprintf("%s", file_tail(zAs ? zAs : zFilename));
1326 int i;
1327 const char *zMime = mimetype_from_name(zFN);
@@ -1330,17 +1338,18 @@
1330 if( fossil_isalnum(c) ) continue;
1331 if( c=='.' ) continue;
1332 if( c=='-' ) continue;
1333 zFN[i] = '_';
1334 }
1335 blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"file\";"
1336 " filename=\"%s\"\r\n", zFN);
1337 blob_appendf(&up,"Content-Type: %s\r\n\r\n", zMime);
 
1338 blob_append(&up, fcontent.aData, fcontent.nUsed);
1339 blob_appendf(&up,"\r\n%s", zBoundary);
1340 }
1341 blob_append(&up,"--\r\n", 4);
1342 http_exchange(&up, &down, mFlags, 4, "multipart/form-data");
1343 blob_reset(&up);
1344 if( sqlite3_strglob("{\"isError\": true,*", blob_str(&down))==0 ){
1345 if( strstr(blob_str(&down), "not logged in")!=0 ){
1346 fossil_print("ERROR: username and/or password is incorrect\n");
1347
--- src/chat.c
+++ src/chat.c
@@ -1302,26 +1302,34 @@
1302 "--------%016llu%016llu%016llu", r[0], r[1], r[2]);
1303 blob_appendf(&up, "%s", zBoundary);
1304 zLMTime = db_text(0,
1305 "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S','now','localtime')");
1306 if( zLMTime ){
1307 blob_appendf(&up,
1308 CRLF "Content-Disposition: form-data; name=\"lmtime\"" CRLF
1309 CRLF "%z" CRLF "%s",
1310 zLMTime, zBoundary);
1311 }
1312 if( g.url.user && g.url.user[0] ){
1313 blob_appendf(&up,
1314 CRLF "Content-Disposition: form-data; name=\"resid\"" CRLF
1315 CRLF "%z" CRLF "%s",
1316 obscure(g.url.user), zBoundary);
1317 }
1318 zPw = g.url.passwd;
1319 if( zPw==0 && isDefaultUrl ) zPw = unobscure(db_get("last-sync-pw", 0));
1320 if( zPw && zPw[0] ){
1321 blob_appendf(&up,
1322 CRLF "Content-Disposition: form-data; name=\"token\"" CRLF
1323 CRLF "%z" CRLF "%s",
1324 obscure(zPw), zBoundary);
1325 }
1326 if( zMsg && zMsg[0] ){
1327 blob_appendf(&up,
1328 CRLF "Content-Disposition: form-data; name=\"msg\"" CRLF
1329 CRLF "%s" CRLF "%s",
1330 zMsg, zBoundary);
1331 }
1332 if( zFilename && blob_read_from_file(&fcontent, zFilename, ExtFILE)>0 ){
1333 char *zFN = mprintf("%s", file_tail(zAs ? zAs : zFilename));
1334 int i;
1335 const char *zMime = mimetype_from_name(zFN);
@@ -1330,17 +1338,18 @@
1338 if( fossil_isalnum(c) ) continue;
1339 if( c=='.' ) continue;
1340 if( c=='-' ) continue;
1341 zFN[i] = '_';
1342 }
1343 blob_appendf(&up,
1344 CRLF "Content-Disposition: form-data; name=\"file\";"
1345 " filename=\"%s\"" CRLF, zFN);
1346 blob_appendf(&up,"Content-Type: %s" CRLF CRLF, zMime);
1347 blob_append(&up, fcontent.aData, fcontent.nUsed);
1348 blob_appendf(&up,CRLF "%s", zBoundary);
1349 }
1350 blob_append(&up,"--" CRLF, CRLF_SZ+2);
1351 http_exchange(&up, &down, mFlags, 4, "multipart/form-data");
1352 blob_reset(&up);
1353 if( sqlite3_strglob("{\"isError\": true,*", blob_str(&down))==0 ){
1354 if( strstr(blob_str(&down), "not logged in")!=0 ){
1355 fossil_print("ERROR: username and/or password is incorrect\n");
1356
+19
--- src/config.h
+++ src/config.h
@@ -266,10 +266,29 @@
266266
** Number of elements in an array
267267
*/
268268
#define count(X) (int)(sizeof(X)/sizeof(X[0]))
269269
#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
270270
271
+/*
272
+** Fossil normally only sends a \n, not a full \r\n, for line endings
273
+** even on protocols that specifically require \r\n (HTTP, SMTP, etc.)
274
+** This is in rebellion to the silliness that is \r\n. Everybody
275
+** understands a bare \n. Fossil deliberately violates the spec in an
276
+** attempt to promote change.
277
+**
278
+** If you prefer to follow the protocol exactly, compile with -DSEND_CR=1
279
+*/
280
+#if defined(SEND_CR) && SEND_CR+0>=1
281
+/* This case for strict compliance */
282
+# define CRLF "\r\n"
283
+# define CRLF_SZ 2
284
+#else
285
+/* Default: Send only \n */
286
+# define CRLF "\n"
287
+# define CRLF_SZ 1
288
+#endif
289
+
271290
/*
272291
** The pledge() interface is currently only available on OpenBSD 5.9
273292
** and later. Make calls to fossil_pledge() no-ops on all platforms
274293
** that omit the HAVE_PLEDGE configuration parameter.
275294
*/
276295
--- src/config.h
+++ src/config.h
@@ -266,10 +266,29 @@
266 ** Number of elements in an array
267 */
268 #define count(X) (int)(sizeof(X)/sizeof(X[0]))
269 #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
270
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271 /*
272 ** The pledge() interface is currently only available on OpenBSD 5.9
273 ** and later. Make calls to fossil_pledge() no-ops on all platforms
274 ** that omit the HAVE_PLEDGE configuration parameter.
275 */
276
--- src/config.h
+++ src/config.h
@@ -266,10 +266,29 @@
266 ** Number of elements in an array
267 */
268 #define count(X) (int)(sizeof(X)/sizeof(X[0]))
269 #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
270
271 /*
272 ** Fossil normally only sends a \n, not a full \r\n, for line endings
273 ** even on protocols that specifically require \r\n (HTTP, SMTP, etc.)
274 ** This is in rebellion to the silliness that is \r\n. Everybody
275 ** understands a bare \n. Fossil deliberately violates the spec in an
276 ** attempt to promote change.
277 **
278 ** If you prefer to follow the protocol exactly, compile with -DSEND_CR=1
279 */
280 #if defined(SEND_CR) && SEND_CR+0>=1
281 /* This case for strict compliance */
282 # define CRLF "\r\n"
283 # define CRLF_SZ 2
284 #else
285 /* Default: Send only \n */
286 # define CRLF "\n"
287 # define CRLF_SZ 1
288 #endif
289
290 /*
291 ** The pledge() interface is currently only available on OpenBSD 5.9
292 ** and later. Make calls to fossil_pledge() no-ops on all platforms
293 ** that omit the HAVE_PLEDGE configuration parameter.
294 */
295
+1 -1
--- src/extcgi.c
+++ src/extcgi.c
@@ -335,11 +335,11 @@
335335
for(i=13; fossil_isspace(zLine[i]); i++){}
336336
for(j=i; zLine[j] && zLine[j]!=';'; j++){}
337337
zMime = mprintf("%.*s", j-i, &zLine[i]);
338338
}else{
339339
cgi_append_header(zLine);
340
- cgi_append_header("\r\n");
340
+ cgi_append_header(CRLF);
341341
}
342342
}
343343
}
344344
blob_read_from_channel(&reply, fromChild, nContent);
345345
zFailReason = 0; /* Indicate success */
346346
--- src/extcgi.c
+++ src/extcgi.c
@@ -335,11 +335,11 @@
335 for(i=13; fossil_isspace(zLine[i]); i++){}
336 for(j=i; zLine[j] && zLine[j]!=';'; j++){}
337 zMime = mprintf("%.*s", j-i, &zLine[i]);
338 }else{
339 cgi_append_header(zLine);
340 cgi_append_header("\r\n");
341 }
342 }
343 }
344 blob_read_from_channel(&reply, fromChild, nContent);
345 zFailReason = 0; /* Indicate success */
346
--- src/extcgi.c
+++ src/extcgi.c
@@ -335,11 +335,11 @@
335 for(i=13; fossil_isspace(zLine[i]); i++){}
336 for(j=i; zLine[j] && zLine[j]!=';'; j++){}
337 zMime = mprintf("%.*s", j-i, &zLine[i]);
338 }else{
339 cgi_append_header(zLine);
340 cgi_append_header(CRLF);
341 }
342 }
343 }
344 blob_read_from_channel(&reply, fromChild, nContent);
345 zFailReason = 0; /* Indicate success */
346
+2 -2
--- src/fileedit.c
+++ src/fileedit.c
@@ -1065,17 +1065,17 @@
10651065
** updated to account for that. */
10661066
int fperm = 0;
10671067
char * zFuuid = fileedit_file_uuid(zFilename, vid, &fperm);
10681068
const char * zPerm = mfile_permint_mstring(fperm);
10691069
assert(zFuuid);
1070
- cgi_printf_header("x-fileedit-file-perm:%s\r\n", zPerm);
1070
+ cgi_printf_header("x-fileedit-file-perm:%s" CRLF, zPerm);
10711071
fossil_free(zFuuid);
10721072
}
10731073
{ /* Send branch name via response header for UI usability reasons */
10741074
char * zBranch = branch_of_rid(vid);
10751075
if(zBranch!=0 && zBranch[0]!=0){
1076
- cgi_printf_header("x-fileedit-checkin-branch: %s\r\n", zBranch);
1076
+ cgi_printf_header("x-fileedit-checkin-branch: %s" CRLF, zBranch);
10771077
}
10781078
fossil_free(zBranch);
10791079
}
10801080
cgi_set_content_type(zMime);
10811081
cgi_set_content(&content);
10821082
--- src/fileedit.c
+++ src/fileedit.c
@@ -1065,17 +1065,17 @@
1065 ** updated to account for that. */
1066 int fperm = 0;
1067 char * zFuuid = fileedit_file_uuid(zFilename, vid, &fperm);
1068 const char * zPerm = mfile_permint_mstring(fperm);
1069 assert(zFuuid);
1070 cgi_printf_header("x-fileedit-file-perm:%s\r\n", zPerm);
1071 fossil_free(zFuuid);
1072 }
1073 { /* Send branch name via response header for UI usability reasons */
1074 char * zBranch = branch_of_rid(vid);
1075 if(zBranch!=0 && zBranch[0]!=0){
1076 cgi_printf_header("x-fileedit-checkin-branch: %s\r\n", zBranch);
1077 }
1078 fossil_free(zBranch);
1079 }
1080 cgi_set_content_type(zMime);
1081 cgi_set_content(&content);
1082
--- src/fileedit.c
+++ src/fileedit.c
@@ -1065,17 +1065,17 @@
1065 ** updated to account for that. */
1066 int fperm = 0;
1067 char * zFuuid = fileedit_file_uuid(zFilename, vid, &fperm);
1068 const char * zPerm = mfile_permint_mstring(fperm);
1069 assert(zFuuid);
1070 cgi_printf_header("x-fileedit-file-perm:%s" CRLF, zPerm);
1071 fossil_free(zFuuid);
1072 }
1073 { /* Send branch name via response header for UI usability reasons */
1074 char * zBranch = branch_of_rid(vid);
1075 if(zBranch!=0 && zBranch[0]!=0){
1076 cgi_printf_header("x-fileedit-checkin-branch: %s" CRLF, zBranch);
1077 }
1078 fossil_free(zBranch);
1079 }
1080 cgi_set_content_type(zMime);
1081 cgi_set_content(&content);
1082
+11 -11
--- src/http.c
+++ src/http.c
@@ -137,36 +137,36 @@
137137
const char *zAltMimetype /* Alternative mimetype */
138138
){
139139
int nPayload = pPayload ? blob_size(pPayload) : 0;
140140
141141
blob_zero(pHdr);
142
- blob_appendf(pHdr, "%s %s%s HTTP/1.0\r\n",
142
+ blob_appendf(pHdr, "%s %s%s HTTP/1.0" CRLF,
143143
nPayload>0 ? "POST" : "GET", g.url.path,
144144
g.url.path[0]==0 ? "/" : "");
145145
if( g.url.proxyAuth ){
146
- blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
146
+ blob_appendf(pHdr, "Proxy-Authorization: %s" CRLF, g.url.proxyAuth);
147147
}
148148
if( g.zHttpAuth && g.zHttpAuth[0] ){
149149
const char *zCredentials = g.zHttpAuth;
150150
char *zEncoded = encode64(zCredentials, -1);
151
- blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
151
+ blob_appendf(pHdr, "Authorization: Basic %s" CRLF, zEncoded);
152152
fossil_free(zEncoded);
153153
}
154
- blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
155
- blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
156
- if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
154
+ blob_appendf(pHdr, "Host: %s" CRLF, g.url.hostname);
155
+ blob_appendf(pHdr, "User-Agent: %s" CRLF, get_user_agent());
156
+ if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH" CRLF);
157157
if( nPayload ){
158158
if( zAltMimetype ){
159
- blob_appendf(pHdr, "Content-Type: %s\r\n", zAltMimetype);
159
+ blob_appendf(pHdr, "Content-Type: %s" CRLF, zAltMimetype);
160160
}else if( g.fHttpTrace ){
161
- blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
161
+ blob_appendf(pHdr, "Content-Type: application/x-fossil-debug" CRLF);
162162
}else{
163
- blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
163
+ blob_appendf(pHdr, "Content-Type: application/x-fossil" CRLF);
164164
}
165
- blob_appendf(pHdr, "Content-Length: %d\r\n", blob_size(pPayload));
165
+ blob_appendf(pHdr, "Content-Length: %d" CRLF, blob_size(pPayload));
166166
}
167
- blob_append(pHdr, "\r\n", 2);
167
+ blob_append(pHdr, CRLF, CRLF_SZ);
168168
}
169169
170170
/*
171171
** Use Fossil credentials for HTTP Basic Authorization prompt
172172
*/
173173
--- src/http.c
+++ src/http.c
@@ -137,36 +137,36 @@
137 const char *zAltMimetype /* Alternative mimetype */
138 ){
139 int nPayload = pPayload ? blob_size(pPayload) : 0;
140
141 blob_zero(pHdr);
142 blob_appendf(pHdr, "%s %s%s HTTP/1.0\r\n",
143 nPayload>0 ? "POST" : "GET", g.url.path,
144 g.url.path[0]==0 ? "/" : "");
145 if( g.url.proxyAuth ){
146 blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
147 }
148 if( g.zHttpAuth && g.zHttpAuth[0] ){
149 const char *zCredentials = g.zHttpAuth;
150 char *zEncoded = encode64(zCredentials, -1);
151 blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
152 fossil_free(zEncoded);
153 }
154 blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
155 blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
156 if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
157 if( nPayload ){
158 if( zAltMimetype ){
159 blob_appendf(pHdr, "Content-Type: %s\r\n", zAltMimetype);
160 }else if( g.fHttpTrace ){
161 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
162 }else{
163 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
164 }
165 blob_appendf(pHdr, "Content-Length: %d\r\n", blob_size(pPayload));
166 }
167 blob_append(pHdr, "\r\n", 2);
168 }
169
170 /*
171 ** Use Fossil credentials for HTTP Basic Authorization prompt
172 */
173
--- src/http.c
+++ src/http.c
@@ -137,36 +137,36 @@
137 const char *zAltMimetype /* Alternative mimetype */
138 ){
139 int nPayload = pPayload ? blob_size(pPayload) : 0;
140
141 blob_zero(pHdr);
142 blob_appendf(pHdr, "%s %s%s HTTP/1.0" CRLF,
143 nPayload>0 ? "POST" : "GET", g.url.path,
144 g.url.path[0]==0 ? "/" : "");
145 if( g.url.proxyAuth ){
146 blob_appendf(pHdr, "Proxy-Authorization: %s" CRLF, g.url.proxyAuth);
147 }
148 if( g.zHttpAuth && g.zHttpAuth[0] ){
149 const char *zCredentials = g.zHttpAuth;
150 char *zEncoded = encode64(zCredentials, -1);
151 blob_appendf(pHdr, "Authorization: Basic %s" CRLF, zEncoded);
152 fossil_free(zEncoded);
153 }
154 blob_appendf(pHdr, "Host: %s" CRLF, g.url.hostname);
155 blob_appendf(pHdr, "User-Agent: %s" CRLF, get_user_agent());
156 if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH" CRLF);
157 if( nPayload ){
158 if( zAltMimetype ){
159 blob_appendf(pHdr, "Content-Type: %s" CRLF, zAltMimetype);
160 }else if( g.fHttpTrace ){
161 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug" CRLF);
162 }else{
163 blob_appendf(pHdr, "Content-Type: application/x-fossil" CRLF);
164 }
165 blob_appendf(pHdr, "Content-Length: %d" CRLF, blob_size(pPayload));
166 }
167 blob_append(pHdr, CRLF, CRLF_SZ);
168 }
169
170 /*
171 ** Use Fossil credentials for HTTP Basic Authorization prompt
172 */
173
+10 -12
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -379,20 +379,20 @@
379379
int rc, httpVerMin;
380380
char *bbuf;
381381
Blob snd, reply;
382382
int done=0,end=0;
383383
blob_zero(&snd);
384
- blob_appendf(&snd, "CONNECT %s:%d HTTP/1.1\r\n", pUrlData->hostname,
384
+ blob_appendf(&snd, "CONNECT %s:%d HTTP/1.1" CRLF, pUrlData->hostname,
385385
pUrlData->proxyOrigPort);
386
- blob_appendf(&snd, "Host: %s:%d\r\n",
386
+ blob_appendf(&snd, "Host: %s:%d" CRLF,
387387
pUrlData->hostname, pUrlData->proxyOrigPort);
388388
if( pUrlData->proxyAuth ){
389
- blob_appendf(&snd, "Proxy-Authorization: %s\r\n", pUrlData->proxyAuth);
389
+ blob_appendf(&snd, "Proxy-Authorization: %s" CRLF, pUrlData->proxyAuth);
390390
}
391
- blob_append(&snd, "Proxy-Connection: keep-alive\r\n", -1);
392
- blob_appendf(&snd, "User-Agent: %s\r\n", get_user_agent());
393
- blob_append(&snd, "\r\n", 2);
391
+ blob_append(&snd, "Proxy-Connection: keep-alive" CRLF, -1);
392
+ blob_appendf(&snd, "User-Agent: %s" CRLF, get_user_agent());
393
+ blob_append(&snd, CRLF, CRLF_SZ);
394394
BIO_write(bio, blob_buffer(&snd), blob_size(&snd));
395395
blob_reset(&snd);
396396
397397
/* Wait for end of reply */
398398
blob_zero(&reply);
@@ -403,16 +403,14 @@
403403
blob_append(&reply, buf, len);
404404
405405
bbuf = blob_buffer(&reply);
406406
len = blob_size(&reply);
407407
while(end < len) {
408
- if(bbuf[end] == '\r') {
409
- if(len - end < 4) {
410
- /* need more data */
411
- break;
412
- }
413
- if(memcmp(&bbuf[end], "\r\n\r\n", 4) == 0) {
408
+ if( bbuf[end]=='\n' ) {
409
+ if( (end+1<len && bbuf[end+1]=='\n')
410
+ || (end+2<len && bbuf[end+1]=='\r' && bbuf[end+1]=='\n')
411
+ ){
414412
done = 1;
415413
break;
416414
}
417415
}
418416
end++;
419417
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -379,20 +379,20 @@
379 int rc, httpVerMin;
380 char *bbuf;
381 Blob snd, reply;
382 int done=0,end=0;
383 blob_zero(&snd);
384 blob_appendf(&snd, "CONNECT %s:%d HTTP/1.1\r\n", pUrlData->hostname,
385 pUrlData->proxyOrigPort);
386 blob_appendf(&snd, "Host: %s:%d\r\n",
387 pUrlData->hostname, pUrlData->proxyOrigPort);
388 if( pUrlData->proxyAuth ){
389 blob_appendf(&snd, "Proxy-Authorization: %s\r\n", pUrlData->proxyAuth);
390 }
391 blob_append(&snd, "Proxy-Connection: keep-alive\r\n", -1);
392 blob_appendf(&snd, "User-Agent: %s\r\n", get_user_agent());
393 blob_append(&snd, "\r\n", 2);
394 BIO_write(bio, blob_buffer(&snd), blob_size(&snd));
395 blob_reset(&snd);
396
397 /* Wait for end of reply */
398 blob_zero(&reply);
@@ -403,16 +403,14 @@
403 blob_append(&reply, buf, len);
404
405 bbuf = blob_buffer(&reply);
406 len = blob_size(&reply);
407 while(end < len) {
408 if(bbuf[end] == '\r') {
409 if(len - end < 4) {
410 /* need more data */
411 break;
412 }
413 if(memcmp(&bbuf[end], "\r\n\r\n", 4) == 0) {
414 done = 1;
415 break;
416 }
417 }
418 end++;
419
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -379,20 +379,20 @@
379 int rc, httpVerMin;
380 char *bbuf;
381 Blob snd, reply;
382 int done=0,end=0;
383 blob_zero(&snd);
384 blob_appendf(&snd, "CONNECT %s:%d HTTP/1.1" CRLF, pUrlData->hostname,
385 pUrlData->proxyOrigPort);
386 blob_appendf(&snd, "Host: %s:%d" CRLF,
387 pUrlData->hostname, pUrlData->proxyOrigPort);
388 if( pUrlData->proxyAuth ){
389 blob_appendf(&snd, "Proxy-Authorization: %s" CRLF, pUrlData->proxyAuth);
390 }
391 blob_append(&snd, "Proxy-Connection: keep-alive" CRLF, -1);
392 blob_appendf(&snd, "User-Agent: %s" CRLF, get_user_agent());
393 blob_append(&snd, CRLF, CRLF_SZ);
394 BIO_write(bio, blob_buffer(&snd), blob_size(&snd));
395 blob_reset(&snd);
396
397 /* Wait for end of reply */
398 blob_zero(&reply);
@@ -403,16 +403,14 @@
403 blob_append(&reply, buf, len);
404
405 bbuf = blob_buffer(&reply);
406 len = blob_size(&reply);
407 while(end < len) {
408 if( bbuf[end]=='\n' ) {
409 if( (end+1<len && bbuf[end+1]=='\n')
410 || (end+2<len && bbuf[end+1]=='\r' && bbuf[end+1]=='\n')
411 ){
 
 
412 done = 1;
413 break;
414 }
415 }
416 end++;
417
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -271,11 +271,11 @@
271271
if(zContent && *zContent){
272272
Blob out = empty_blob;
273273
const int isErr =
274274
pikchr_process(zContent, pikFlags, 0, &out);
275275
if(isErr){
276
- cgi_printf_header("x-pikchrshow-is-error: %d\r\n", isErr);
276
+ cgi_printf_header("x-pikchrshow-is-error: %d" CRLF, isErr);
277277
}
278278
CX("%b", &out);
279279
blob_reset(&out);
280280
}else{
281281
CX("<pre>No content! Nothing to render</pre>");
282282
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -271,11 +271,11 @@
271 if(zContent && *zContent){
272 Blob out = empty_blob;
273 const int isErr =
274 pikchr_process(zContent, pikFlags, 0, &out);
275 if(isErr){
276 cgi_printf_header("x-pikchrshow-is-error: %d\r\n", isErr);
277 }
278 CX("%b", &out);
279 blob_reset(&out);
280 }else{
281 CX("<pre>No content! Nothing to render</pre>");
282
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -271,11 +271,11 @@
271 if(zContent && *zContent){
272 Blob out = empty_blob;
273 const int isErr =
274 pikchr_process(zContent, pikFlags, 0, &out);
275 if(isErr){
276 cgi_printf_header("x-pikchrshow-is-error: %d" CRLF, isErr);
277 }
278 CX("%b", &out);
279 blob_reset(&out);
280 }else{
281 CX("<pre>No content! Nothing to render</pre>");
282
+8 -8
--- src/smtp.c
+++ src/smtp.c
@@ -375,11 +375,11 @@
375375
int smtp_client_quit(SmtpSession *p){
376376
Blob in = BLOB_INITIALIZER;
377377
int iCode = 0;
378378
int bMore = 0;
379379
char *zArg = 0;
380
- smtp_send_line(p, "QUIT\r\n");
380
+ smtp_send_line(p, "QUIT" CRLF);
381381
do{
382382
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
383383
}while( bMore );
384384
p->atEof = 1;
385385
socket_close();
@@ -402,11 +402,11 @@
402402
}while( bMore );
403403
if( iCode!=220 ){
404404
smtp_client_quit(p);
405405
return 1;
406406
}
407
- smtp_send_line(p, "EHLO %s\r\n", p->zFrom);
407
+ smtp_send_line(p, "EHLO %s" CRLF, p->zFrom);
408408
do{
409409
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
410410
}while( bMore );
411411
if( iCode!=250 ){
412412
smtp_client_quit(p);
@@ -456,11 +456,11 @@
456456
smtp_session_free(p);
457457
}
458458
459459
/*
460460
** Send the content of an email message followed by a single
461
-** "." line. All lines must be \r\n terminated. Any isolated
461
+** "." line. All lines must be \r\n terminated. (NOT!) Any isolated
462462
** \n line terminators in the input must be converted. Also,
463463
** a line beginning with "." must have the dot doubled per
464464
** https://tools.ietf.org/html/rfc5321#section-4.5.2
465465
*/
466466
static void smtp_send_email_body(
@@ -482,13 +482,13 @@
482482
blob_append(&out, "..", 2); /* RFC 5321 § 4.5.2 */
483483
blob_append(&out, z+1, n-1);
484484
}else{
485485
blob_append(&out, z, n);
486486
}
487
- blob_append(&out, "\r\n", 2);
487
+ blob_append(&out, CRLF, CRLF_SZ);
488488
}
489
- blob_append(&out, ".\r\n", 3);
489
+ blob_append(&out, "." CRLF, CRLF_SZ+1);
490490
xSend(pArg, blob_buffer(&out), blob_size(&out));
491491
blob_reset(&out);
492492
blob_reset(&line);
493493
}
494494
@@ -541,23 +541,23 @@
541541
int iCode = 0;
542542
int bMore = 0;
543543
char *zArg = 0;
544544
Blob in;
545545
blob_init(&in, 0, 0);
546
- smtp_send_line(p, "MAIL FROM:<%s>\r\n", zFrom);
546
+ smtp_send_line(p, "MAIL FROM:<%s>" CRLF, zFrom);
547547
do{
548548
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
549549
}while( bMore );
550550
if( iCode!=250 ) return 1;
551551
for(i=0; i<nTo; i++){
552
- smtp_send_line(p, "RCPT TO:<%s>\r\n", azTo[i]);
552
+ smtp_send_line(p, "RCPT TO:<%s>" CRLF, azTo[i]);
553553
do{
554554
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
555555
}while( bMore );
556556
if( iCode!=250 ) return 1;
557557
}
558
- smtp_send_line(p, "DATA\r\n");
558
+ smtp_send_line(p, "DATA" CRLF);
559559
do{
560560
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
561561
}while( bMore );
562562
if( iCode!=354 ) return 1;
563563
smtp_send_email_body(zMsg, socket_send, 0);
564564
--- src/smtp.c
+++ src/smtp.c
@@ -375,11 +375,11 @@
375 int smtp_client_quit(SmtpSession *p){
376 Blob in = BLOB_INITIALIZER;
377 int iCode = 0;
378 int bMore = 0;
379 char *zArg = 0;
380 smtp_send_line(p, "QUIT\r\n");
381 do{
382 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
383 }while( bMore );
384 p->atEof = 1;
385 socket_close();
@@ -402,11 +402,11 @@
402 }while( bMore );
403 if( iCode!=220 ){
404 smtp_client_quit(p);
405 return 1;
406 }
407 smtp_send_line(p, "EHLO %s\r\n", p->zFrom);
408 do{
409 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
410 }while( bMore );
411 if( iCode!=250 ){
412 smtp_client_quit(p);
@@ -456,11 +456,11 @@
456 smtp_session_free(p);
457 }
458
459 /*
460 ** Send the content of an email message followed by a single
461 ** "." line. All lines must be \r\n terminated. Any isolated
462 ** \n line terminators in the input must be converted. Also,
463 ** a line beginning with "." must have the dot doubled per
464 ** https://tools.ietf.org/html/rfc5321#section-4.5.2
465 */
466 static void smtp_send_email_body(
@@ -482,13 +482,13 @@
482 blob_append(&out, "..", 2); /* RFC 5321 § 4.5.2 */
483 blob_append(&out, z+1, n-1);
484 }else{
485 blob_append(&out, z, n);
486 }
487 blob_append(&out, "\r\n", 2);
488 }
489 blob_append(&out, ".\r\n", 3);
490 xSend(pArg, blob_buffer(&out), blob_size(&out));
491 blob_reset(&out);
492 blob_reset(&line);
493 }
494
@@ -541,23 +541,23 @@
541 int iCode = 0;
542 int bMore = 0;
543 char *zArg = 0;
544 Blob in;
545 blob_init(&in, 0, 0);
546 smtp_send_line(p, "MAIL FROM:<%s>\r\n", zFrom);
547 do{
548 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
549 }while( bMore );
550 if( iCode!=250 ) return 1;
551 for(i=0; i<nTo; i++){
552 smtp_send_line(p, "RCPT TO:<%s>\r\n", azTo[i]);
553 do{
554 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
555 }while( bMore );
556 if( iCode!=250 ) return 1;
557 }
558 smtp_send_line(p, "DATA\r\n");
559 do{
560 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
561 }while( bMore );
562 if( iCode!=354 ) return 1;
563 smtp_send_email_body(zMsg, socket_send, 0);
564
--- src/smtp.c
+++ src/smtp.c
@@ -375,11 +375,11 @@
375 int smtp_client_quit(SmtpSession *p){
376 Blob in = BLOB_INITIALIZER;
377 int iCode = 0;
378 int bMore = 0;
379 char *zArg = 0;
380 smtp_send_line(p, "QUIT" CRLF);
381 do{
382 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
383 }while( bMore );
384 p->atEof = 1;
385 socket_close();
@@ -402,11 +402,11 @@
402 }while( bMore );
403 if( iCode!=220 ){
404 smtp_client_quit(p);
405 return 1;
406 }
407 smtp_send_line(p, "EHLO %s" CRLF, p->zFrom);
408 do{
409 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
410 }while( bMore );
411 if( iCode!=250 ){
412 smtp_client_quit(p);
@@ -456,11 +456,11 @@
456 smtp_session_free(p);
457 }
458
459 /*
460 ** Send the content of an email message followed by a single
461 ** "." line. All lines must be \r\n terminated. (NOT!) Any isolated
462 ** \n line terminators in the input must be converted. Also,
463 ** a line beginning with "." must have the dot doubled per
464 ** https://tools.ietf.org/html/rfc5321#section-4.5.2
465 */
466 static void smtp_send_email_body(
@@ -482,13 +482,13 @@
482 blob_append(&out, "..", 2); /* RFC 5321 § 4.5.2 */
483 blob_append(&out, z+1, n-1);
484 }else{
485 blob_append(&out, z, n);
486 }
487 blob_append(&out, CRLF, CRLF_SZ);
488 }
489 blob_append(&out, "." CRLF, CRLF_SZ+1);
490 xSend(pArg, blob_buffer(&out), blob_size(&out));
491 blob_reset(&out);
492 blob_reset(&line);
493 }
494
@@ -541,23 +541,23 @@
541 int iCode = 0;
542 int bMore = 0;
543 char *zArg = 0;
544 Blob in;
545 blob_init(&in, 0, 0);
546 smtp_send_line(p, "MAIL FROM:<%s>" CRLF, zFrom);
547 do{
548 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
549 }while( bMore );
550 if( iCode!=250 ) return 1;
551 for(i=0; i<nTo; i++){
552 smtp_send_line(p, "RCPT TO:<%s>" CRLF, azTo[i]);
553 do{
554 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
555 }while( bMore );
556 if( iCode!=250 ) return 1;
557 }
558 smtp_send_line(p, "DATA" CRLF);
559 do{
560 smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
561 }while( bMore );
562 if( iCode!=354 ) return 1;
563 smtp_send_email_body(zMsg, socket_send, 0);
564
+1 -1
--- src/style.c
+++ src/style.c
@@ -618,11 +618,11 @@
618618
zCsp = blob_str(&csp);
619619
/* No whitespace other than actual space characters allowed in the CSP
620620
** string. See https://fossil-scm.org/forum/forumpost/d29e3af43c */
621621
for(i=0; zCsp[i]; i++){ if( fossil_isspace(zCsp[i]) ) zCsp[i] = ' '; }
622622
if( toHeader ){
623
- cgi_printf_header("Content-Security-Policy: %s\r\n", zCsp);
623
+ cgi_printf_header("Content-Security-Policy: %s" CRLF, zCsp);
624624
}
625625
return zCsp;
626626
}
627627
628628
/*
629629
--- src/style.c
+++ src/style.c
@@ -618,11 +618,11 @@
618 zCsp = blob_str(&csp);
619 /* No whitespace other than actual space characters allowed in the CSP
620 ** string. See https://fossil-scm.org/forum/forumpost/d29e3af43c */
621 for(i=0; zCsp[i]; i++){ if( fossil_isspace(zCsp[i]) ) zCsp[i] = ' '; }
622 if( toHeader ){
623 cgi_printf_header("Content-Security-Policy: %s\r\n", zCsp);
624 }
625 return zCsp;
626 }
627
628 /*
629
--- src/style.c
+++ src/style.c
@@ -618,11 +618,11 @@
618 zCsp = blob_str(&csp);
619 /* No whitespace other than actual space characters allowed in the CSP
620 ** string. See https://fossil-scm.org/forum/forumpost/d29e3af43c */
621 for(i=0; zCsp[i]; i++){ if( fossil_isspace(zCsp[i]) ) zCsp[i] = ' '; }
622 if( toHeader ){
623 cgi_printf_header("Content-Security-Policy: %s" CRLF, zCsp);
624 }
625 return zCsp;
626 }
627
628 /*
629
+8 -8
--- src/th_main.c
+++ src/th_main.c
@@ -2183,29 +2183,29 @@
21832183
zSep = "";
21842184
}else{
21852185
zSep = "/";
21862186
}
21872187
blob_zero(&hdr);
2188
- blob_appendf(&hdr, "%s %s%s%s HTTP/1.0\r\n",
2188
+ blob_appendf(&hdr, "%s %s%s%s HTTP/1.0" CRLF,
21892189
zType, zSep, urlData.path, zParams ? zParams : "");
21902190
if( urlData.proxyAuth ){
2191
- blob_appendf(&hdr, "Proxy-Authorization: %s\r\n", urlData.proxyAuth);
2191
+ blob_appendf(&hdr, "Proxy-Authorization: %s" CRLF, urlData.proxyAuth);
21922192
}
21932193
if( urlData.passwd && urlData.user && urlData.passwd[0]=='#' ){
21942194
char *zCredentials = mprintf("%s:%s", urlData.user, &urlData.passwd[1]);
21952195
char *zEncoded = encode64(zCredentials, -1);
2196
- blob_appendf(&hdr, "Authorization: Basic %s\r\n", zEncoded);
2196
+ blob_appendf(&hdr, "Authorization: Basic %s" CRLF, zEncoded);
21972197
fossil_free(zEncoded);
21982198
fossil_free(zCredentials);
21992199
}
2200
- blob_appendf(&hdr, "Host: %s\r\n"
2201
- "User-Agent: %s\r\n", urlData.hostname, get_user_agent());
2200
+ blob_appendf(&hdr, "Host: %s" CRLF
2201
+ "User-Agent: %s" CRLF, urlData.hostname, get_user_agent());
22022202
if( zType[0]=='P' ){
2203
- blob_appendf(&hdr, "Content-Type: application/x-www-form-urlencoded\r\n"
2204
- "Content-Length: %d\r\n\r\n", blob_size(&payload));
2203
+ blob_appendf(&hdr, "Content-Type: application/x-www-form-urlencoded" CRLF
2204
+ "Content-Length: %d" CRLF CRLF, blob_size(&payload));
22052205
}else{
2206
- blob_appendf(&hdr, "\r\n");
2206
+ blob_appendf(&hdr, CRLF);
22072207
}
22082208
if( transport_open(&urlData) ){
22092209
Th_ErrorMessage(interp, transport_errmsg(&urlData), 0, 0);
22102210
blob_reset(&hdr);
22112211
blob_reset(&payload);
22122212
--- src/th_main.c
+++ src/th_main.c
@@ -2183,29 +2183,29 @@
2183 zSep = "";
2184 }else{
2185 zSep = "/";
2186 }
2187 blob_zero(&hdr);
2188 blob_appendf(&hdr, "%s %s%s%s HTTP/1.0\r\n",
2189 zType, zSep, urlData.path, zParams ? zParams : "");
2190 if( urlData.proxyAuth ){
2191 blob_appendf(&hdr, "Proxy-Authorization: %s\r\n", urlData.proxyAuth);
2192 }
2193 if( urlData.passwd && urlData.user && urlData.passwd[0]=='#' ){
2194 char *zCredentials = mprintf("%s:%s", urlData.user, &urlData.passwd[1]);
2195 char *zEncoded = encode64(zCredentials, -1);
2196 blob_appendf(&hdr, "Authorization: Basic %s\r\n", zEncoded);
2197 fossil_free(zEncoded);
2198 fossil_free(zCredentials);
2199 }
2200 blob_appendf(&hdr, "Host: %s\r\n"
2201 "User-Agent: %s\r\n", urlData.hostname, get_user_agent());
2202 if( zType[0]=='P' ){
2203 blob_appendf(&hdr, "Content-Type: application/x-www-form-urlencoded\r\n"
2204 "Content-Length: %d\r\n\r\n", blob_size(&payload));
2205 }else{
2206 blob_appendf(&hdr, "\r\n");
2207 }
2208 if( transport_open(&urlData) ){
2209 Th_ErrorMessage(interp, transport_errmsg(&urlData), 0, 0);
2210 blob_reset(&hdr);
2211 blob_reset(&payload);
2212
--- src/th_main.c
+++ src/th_main.c
@@ -2183,29 +2183,29 @@
2183 zSep = "";
2184 }else{
2185 zSep = "/";
2186 }
2187 blob_zero(&hdr);
2188 blob_appendf(&hdr, "%s %s%s%s HTTP/1.0" CRLF,
2189 zType, zSep, urlData.path, zParams ? zParams : "");
2190 if( urlData.proxyAuth ){
2191 blob_appendf(&hdr, "Proxy-Authorization: %s" CRLF, urlData.proxyAuth);
2192 }
2193 if( urlData.passwd && urlData.user && urlData.passwd[0]=='#' ){
2194 char *zCredentials = mprintf("%s:%s", urlData.user, &urlData.passwd[1]);
2195 char *zEncoded = encode64(zCredentials, -1);
2196 blob_appendf(&hdr, "Authorization: Basic %s" CRLF, zEncoded);
2197 fossil_free(zEncoded);
2198 fossil_free(zCredentials);
2199 }
2200 blob_appendf(&hdr, "Host: %s" CRLF
2201 "User-Agent: %s" CRLF, urlData.hostname, get_user_agent());
2202 if( zType[0]=='P' ){
2203 blob_appendf(&hdr, "Content-Type: application/x-www-form-urlencoded" CRLF
2204 "Content-Length: %d" CRLF CRLF, blob_size(&payload));
2205 }else{
2206 blob_appendf(&hdr, CRLF);
2207 }
2208 if( transport_open(&urlData) ){
2209 Th_ErrorMessage(interp, transport_errmsg(&urlData), 0, 0);
2210 blob_reset(&hdr);
2211 blob_reset(&payload);
2212
+4 -4
--- src/winhttp.c
+++ src/winhttp.c
@@ -375,18 +375,18 @@
375375
wanted = 0;
376376
break;
377377
}
378378
amt += got;
379379
zBuf[amt] = 0;
380
- z = strstr(zBuf, "\r\n\r\n");
380
+ z = strstr(zBuf, "\n\n");
381381
if( z ){
382
- wanted = find_content_length(zBuf) + (&z[4]-zBuf) - amt;
382
+ wanted = find_content_length(zBuf) + (&z[2]-zBuf) - amt;
383383
break;
384384
}else{
385
- z = strstr(zBuf, "\n\n");
385
+ z = strstr(zBuf, "\n\r\n");
386386
if( z ){
387
- wanted = find_content_length(zBuf) + (&z[2]-zBuf) - amt;
387
+ wanted = find_content_length(zBuf) + (&z[3]-zBuf) - amt;
388388
break;
389389
}
390390
}
391391
}
392392
if( amt>=szHdr ) goto end_request;
393393
--- src/winhttp.c
+++ src/winhttp.c
@@ -375,18 +375,18 @@
375 wanted = 0;
376 break;
377 }
378 amt += got;
379 zBuf[amt] = 0;
380 z = strstr(zBuf, "\r\n\r\n");
381 if( z ){
382 wanted = find_content_length(zBuf) + (&z[4]-zBuf) - amt;
383 break;
384 }else{
385 z = strstr(zBuf, "\n\n");
386 if( z ){
387 wanted = find_content_length(zBuf) + (&z[2]-zBuf) - amt;
388 break;
389 }
390 }
391 }
392 if( amt>=szHdr ) goto end_request;
393
--- src/winhttp.c
+++ src/winhttp.c
@@ -375,18 +375,18 @@
375 wanted = 0;
376 break;
377 }
378 amt += got;
379 zBuf[amt] = 0;
380 z = strstr(zBuf, "\n\n");
381 if( z ){
382 wanted = find_content_length(zBuf) + (&z[2]-zBuf) - amt;
383 break;
384 }else{
385 z = strstr(zBuf, "\n\r\n");
386 if( z ){
387 wanted = find_content_length(zBuf) + (&z[3]-zBuf) - amt;
388 break;
389 }
390 }
391 }
392 if( amt>=szHdr ) goto end_request;
393
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -230,14 +230,19 @@
230230
231231
/*
232232
** Return true if the input is a string literal.
233233
*/
234234
static int is_string_lit(const char *z){
235
- int nu1, nu2;
236
- z = next_non_whitespace(z, &nu1, &nu2);
237
- if( strcmp(z, "NULL")==0 ) return 1;
238
- return z[0]=='"';
235
+ int len, eType;
236
+ while( 1 /* exit by return */ ){
237
+ z = next_non_whitespace(z, &len, &eType);
238
+ if( len==4 ){
239
+ if( strncmp(z, "NULL", 4)==0 ) return 1;
240
+ if( strncmp(z, "CRLF", 4)==0 ) return 1;
241
+ }
242
+ return z[0]=='"';
243
+ }
239244
}
240245
241246
/*
242247
** Return true if the input is an expression of string literals:
243248
**
244249
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -230,14 +230,19 @@
230
231 /*
232 ** Return true if the input is a string literal.
233 */
234 static int is_string_lit(const char *z){
235 int nu1, nu2;
236 z = next_non_whitespace(z, &nu1, &nu2);
237 if( strcmp(z, "NULL")==0 ) return 1;
238 return z[0]=='"';
 
 
 
 
 
239 }
240
241 /*
242 ** Return true if the input is an expression of string literals:
243 **
244
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -230,14 +230,19 @@
230
231 /*
232 ** Return true if the input is a string literal.
233 */
234 static int is_string_lit(const char *z){
235 int len, eType;
236 while( 1 /* exit by return */ ){
237 z = next_non_whitespace(z, &len, &eType);
238 if( len==4 ){
239 if( strncmp(z, "NULL", 4)==0 ) return 1;
240 if( strncmp(z, "CRLF", 4)==0 ) return 1;
241 }
242 return z[0]=='"';
243 }
244 }
245
246 /*
247 ** Return true if the input is an expression of string literals:
248 **
249

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button