Fossil SCM

Get sync working from both login card forms and add a temporary --login-card-header CLI flag to force it to emit the HTTP header form of the card in output requests. If all is well, this checkin should be able to push to the canonical repo, despite their differences.

stephan 2025-07-22 15:12 xfer-login-card
Commit 042560df547a44ae91d03cb0bd791f924eb3b277d748439d0be6d99cc407d282
4 files changed +2 -2 +46 -35 +10 -1 +15 -7
+2 -2
--- src/cgi.c
+++ src/cgi.c
@@ -2222,12 +2222,12 @@
22222222
if( sscanf(zVal,"bytes=%d-%d",&x1,&x2)==2 && x1>=0 && x1<=x2 ){
22232223
rangeStart = x1;
22242224
rangeEnd = x2+1;
22252225
}
22262226
}else if( fossil_strcmp(zFieldName, "x-fossil-xfer-login:")==0 ){
2227
- g.zLoginCard = fossil_strdup(zVal);
2228
- /*fprintf(stderr, "X-Fossil-Xfer-Login: %s\n", g.zLoginCard);*/
2227
+ g.syncInfo.zLoginCard = fossil_strdup(zVal);
2228
+ /*fprintf(stderr, "X-Fossil-Xfer-Login: %s\n", g.syncInfo.zLoginCard);*/
22292229
}
22302230
}
22312231
cgi_setenv("REQUEST_SCHEME",zScheme);
22322232
cgi_init();
22332233
cgi_trace(0);
22342234
--- src/cgi.c
+++ src/cgi.c
@@ -2222,12 +2222,12 @@
2222 if( sscanf(zVal,"bytes=%d-%d",&x1,&x2)==2 && x1>=0 && x1<=x2 ){
2223 rangeStart = x1;
2224 rangeEnd = x2+1;
2225 }
2226 }else if( fossil_strcmp(zFieldName, "x-fossil-xfer-login:")==0 ){
2227 g.zLoginCard = fossil_strdup(zVal);
2228 /*fprintf(stderr, "X-Fossil-Xfer-Login: %s\n", g.zLoginCard);*/
2229 }
2230 }
2231 cgi_setenv("REQUEST_SCHEME",zScheme);
2232 cgi_init();
2233 cgi_trace(0);
2234
--- src/cgi.c
+++ src/cgi.c
@@ -2222,12 +2222,12 @@
2222 if( sscanf(zVal,"bytes=%d-%d",&x1,&x2)==2 && x1>=0 && x1<=x2 ){
2223 rangeStart = x1;
2224 rangeEnd = x2+1;
2225 }
2226 }else if( fossil_strcmp(zFieldName, "x-fossil-xfer-login:")==0 ){
2227 g.syncInfo.zLoginCard = fossil_strdup(zVal);
2228 /*fprintf(stderr, "X-Fossil-Xfer-Login: %s\n", g.syncInfo.zLoginCard);*/
2229 }
2230 }
2231 cgi_setenv("REQUEST_SCHEME",zScheme);
2232 cgi_init();
2233 cgi_trace(0);
2234
+46 -35
--- src/http.c
+++ src/http.c
@@ -52,18 +52,21 @@
5252
** Construct the "login" card with the client credentials.
5353
**
5454
** login LOGIN NONCE SIGNATURE
5555
**
5656
** The LOGIN is the user id of the client. NONCE is the sha1 checksum
57
-** of all payload that follows the login card. Randomness for the NONCE
58
-** must be provided in the payload (in xfer.c). SIGNATURE is the sha1
59
-** checksum of the nonce followed by the user password.
57
+** of all payload that follows the login card. Randomness for the
58
+** NONCE must be provided in the payload (in xfer.c) (e.g. by
59
+** appending a timestamp or random bytes as a comment line to the
60
+** payload). SIGNATURE is the sha1 checksum of the nonce followed by
61
+** the fossil-hashed version of the user's password.
6062
**
61
-** Write the constructed login card into pLogin. pLogin is initialized
62
-** by this routine.
63
+** Write the constructed login card into pLogin. The result does not
64
+** have an EOL added to it because which type of EOL it needs has to
65
+** be determined later. pLogin is initialized by this routine.
6366
*/
64
-static void http_build_login_card(Blob *pPayload, Blob *pLogin){
67
+static void http_build_login_card(Blob * const pPayload, Blob * const pLogin){
6568
Blob nonce; /* The nonce */
6669
const char *zLogin; /* The user login name */
6770
const char *zPw; /* The user password */
6871
Blob pw; /* The nonce with user password appended */
6972
Blob sig; /* The signature field */
@@ -128,16 +131,17 @@
128131
}
129132
130133
/*
131134
** Construct an appropriate HTTP request header. Write the header
132135
** into pHdr. This routine initializes the pHdr blob. pPayload is
133
-** the complete payload (including the login card) already compressed.
136
+** the complete payload (including the login card if pLogin is NULL or
137
+** empty) already compressed.
134138
*/
135139
static void http_build_header(
136
- Blob *pLogin, /* Login card or NULL */
137140
Blob *pPayload, /* the payload that will be sent */
138141
Blob *pHdr, /* construct the header here */
142
+ Blob *pLogin, /* Login card header value or NULL */
139143
const char *zAltMimetype /* Alternative mimetype */
140144
){
141145
int nPayload = pPayload ? blob_size(pPayload) : 0;
142146
143147
blob_zero(pHdr);
@@ -154,11 +158,11 @@
154158
fossil_free(zEncoded);
155159
}
156160
blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
157161
blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
158162
if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
159
- if( pLogin ){
163
+ if( pLogin && blob_size(pLogin) ){
160164
blob_appendf(pHdr, "X-Fossil-Xfer-Login: %b\r\n", pLogin);
161165
}
162166
if( nPayload ){
163167
if( zAltMimetype ){
164168
blob_appendf(pHdr, "Content-Type: %s\r\n", zAltMimetype);
@@ -468,42 +472,49 @@
468472
blob_zero(&login);
469473
if( blob_size(pSend)==0 ){
470474
blob_zero(&payload);
471475
}else{
472476
if( mHttpFlags & HTTP_USE_LOGIN ) http_build_login_card(pSend, &login);
473
-#define TEST_LOGIN_HEADER 0 /* temporary dev/test/debug crutch */
474
-#if TEST_LOGIN_HEADER
475
- if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
476
- /*blob_append(&payload, blob_buffer(pSend), blob_size(pSend));*/
477
- blob_zero(&payload);
478
- blob_swap(pSend, &payload);
479
- }else{
480
- blob_compress(pSend, &payload);
481
- }
477
+#if 0
478
+ fprintf(stderr, "# g.syncInfo.bLoginCardHeader=%d login card=%s\n",
479
+ g.syncInfo.bLoginCardHeader,
480
+ blob_size(&login) ? blob_str(&login) : "<empty>");
481
+#endif
482
+ if( g.syncInfo.bLoginCardHeader ) {
483
+ /* Send the login card as an HTTP header. */
484
+ if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
485
+#if 1
486
+ /*blob_append(&payload, blob_buffer(pSend), blob_size(pSend));*/
487
+ blob_init(&payload, blob_buffer(pSend), blob_size(pSend));
482488
#else
483
- if( blob_size(&login) ){
484
- blob_append_char(&login, '\n');
485
- }
486
- if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
487
- payload = login;
488
- login = empty_blob/*transfer ownership*/;
489
- blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
489
+ /* This could save memory but looks like it would break in a
490
+ ** couple of cases in the loop below where pSend is referenced
491
+ ** for HTTP 401 and redirects. */
492
+ blob_zero(&payload);
493
+ blob_swap(pSend, &payload);
494
+#endif
495
+ }else{
496
+ blob_compress(pSend, &payload);
497
+ }
490498
}else{
491
- blob_compress2(&login, pSend, &payload);
492
- blob_reset(&login);
499
+ /* Prepend the login card (if set) to the payload */
500
+ if( blob_size(&login) ){
501
+ blob_append_char(&login, '\n');
502
+ }
503
+ if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
504
+ payload = login;
505
+ login = empty_blob/*transfer ownership*/;
506
+ blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
507
+ }else{
508
+ blob_compress2(&login, pSend, &payload);
509
+ blob_reset(&login);
510
+ }
493511
}
494
-#endif
495512
}
496513
497514
/* Construct the HTTP request header */
498
-#if !TEST_LOGIN_HEADER
499
- http_build_header(0, &payload, &hdr, zAltMimetype);
500
-#else
501
- http_build_header(blob_size(&login) ? &login : 0,
502
- &payload, &hdr, zAltMimetype);
503
- blob_reset(&login);
504
-#endif
515
+ http_build_header(&payload, &hdr, &login, zAltMimetype);
505516
506517
/* When tracing, write the transmitted HTTP message both to standard
507518
** output and into a file. The file can then be used to drive the
508519
** server-side like this:
509520
**
510521
--- src/http.c
+++ src/http.c
@@ -52,18 +52,21 @@
52 ** Construct the "login" card with the client credentials.
53 **
54 ** login LOGIN NONCE SIGNATURE
55 **
56 ** The LOGIN is the user id of the client. NONCE is the sha1 checksum
57 ** of all payload that follows the login card. Randomness for the NONCE
58 ** must be provided in the payload (in xfer.c). SIGNATURE is the sha1
59 ** checksum of the nonce followed by the user password.
 
 
60 **
61 ** Write the constructed login card into pLogin. pLogin is initialized
62 ** by this routine.
 
63 */
64 static void http_build_login_card(Blob *pPayload, Blob *pLogin){
65 Blob nonce; /* The nonce */
66 const char *zLogin; /* The user login name */
67 const char *zPw; /* The user password */
68 Blob pw; /* The nonce with user password appended */
69 Blob sig; /* The signature field */
@@ -128,16 +131,17 @@
128 }
129
130 /*
131 ** Construct an appropriate HTTP request header. Write the header
132 ** into pHdr. This routine initializes the pHdr blob. pPayload is
133 ** the complete payload (including the login card) already compressed.
 
134 */
135 static void http_build_header(
136 Blob *pLogin, /* Login card or NULL */
137 Blob *pPayload, /* the payload that will be sent */
138 Blob *pHdr, /* construct the header here */
 
139 const char *zAltMimetype /* Alternative mimetype */
140 ){
141 int nPayload = pPayload ? blob_size(pPayload) : 0;
142
143 blob_zero(pHdr);
@@ -154,11 +158,11 @@
154 fossil_free(zEncoded);
155 }
156 blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
157 blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
158 if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
159 if( pLogin ){
160 blob_appendf(pHdr, "X-Fossil-Xfer-Login: %b\r\n", pLogin);
161 }
162 if( nPayload ){
163 if( zAltMimetype ){
164 blob_appendf(pHdr, "Content-Type: %s\r\n", zAltMimetype);
@@ -468,42 +472,49 @@
468 blob_zero(&login);
469 if( blob_size(pSend)==0 ){
470 blob_zero(&payload);
471 }else{
472 if( mHttpFlags & HTTP_USE_LOGIN ) http_build_login_card(pSend, &login);
473 #define TEST_LOGIN_HEADER 0 /* temporary dev/test/debug crutch */
474 #if TEST_LOGIN_HEADER
475 if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
476 /*blob_append(&payload, blob_buffer(pSend), blob_size(pSend));*/
477 blob_zero(&payload);
478 blob_swap(pSend, &payload);
479 }else{
480 blob_compress(pSend, &payload);
481 }
 
 
482 #else
483 if( blob_size(&login) ){
484 blob_append_char(&login, '\n');
485 }
486 if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
487 payload = login;
488 login = empty_blob/*transfer ownership*/;
489 blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
 
 
490 }else{
491 blob_compress2(&login, pSend, &payload);
492 blob_reset(&login);
 
 
 
 
 
 
 
 
 
 
493 }
494 #endif
495 }
496
497 /* Construct the HTTP request header */
498 #if !TEST_LOGIN_HEADER
499 http_build_header(0, &payload, &hdr, zAltMimetype);
500 #else
501 http_build_header(blob_size(&login) ? &login : 0,
502 &payload, &hdr, zAltMimetype);
503 blob_reset(&login);
504 #endif
505
506 /* When tracing, write the transmitted HTTP message both to standard
507 ** output and into a file. The file can then be used to drive the
508 ** server-side like this:
509 **
510
--- src/http.c
+++ src/http.c
@@ -52,18 +52,21 @@
52 ** Construct the "login" card with the client credentials.
53 **
54 ** login LOGIN NONCE SIGNATURE
55 **
56 ** The LOGIN is the user id of the client. NONCE is the sha1 checksum
57 ** of all payload that follows the login card. Randomness for the
58 ** NONCE must be provided in the payload (in xfer.c) (e.g. by
59 ** appending a timestamp or random bytes as a comment line to the
60 ** payload). SIGNATURE is the sha1 checksum of the nonce followed by
61 ** the fossil-hashed version of the user's password.
62 **
63 ** Write the constructed login card into pLogin. The result does not
64 ** have an EOL added to it because which type of EOL it needs has to
65 ** be determined later. pLogin is initialized by this routine.
66 */
67 static void http_build_login_card(Blob * const pPayload, Blob * const pLogin){
68 Blob nonce; /* The nonce */
69 const char *zLogin; /* The user login name */
70 const char *zPw; /* The user password */
71 Blob pw; /* The nonce with user password appended */
72 Blob sig; /* The signature field */
@@ -128,16 +131,17 @@
131 }
132
133 /*
134 ** Construct an appropriate HTTP request header. Write the header
135 ** into pHdr. This routine initializes the pHdr blob. pPayload is
136 ** the complete payload (including the login card if pLogin is NULL or
137 ** empty) already compressed.
138 */
139 static void http_build_header(
 
140 Blob *pPayload, /* the payload that will be sent */
141 Blob *pHdr, /* construct the header here */
142 Blob *pLogin, /* Login card header value or NULL */
143 const char *zAltMimetype /* Alternative mimetype */
144 ){
145 int nPayload = pPayload ? blob_size(pPayload) : 0;
146
147 blob_zero(pHdr);
@@ -154,11 +158,11 @@
158 fossil_free(zEncoded);
159 }
160 blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
161 blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
162 if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
163 if( pLogin && blob_size(pLogin) ){
164 blob_appendf(pHdr, "X-Fossil-Xfer-Login: %b\r\n", pLogin);
165 }
166 if( nPayload ){
167 if( zAltMimetype ){
168 blob_appendf(pHdr, "Content-Type: %s\r\n", zAltMimetype);
@@ -468,42 +472,49 @@
472 blob_zero(&login);
473 if( blob_size(pSend)==0 ){
474 blob_zero(&payload);
475 }else{
476 if( mHttpFlags & HTTP_USE_LOGIN ) http_build_login_card(pSend, &login);
477 #if 0
478 fprintf(stderr, "# g.syncInfo.bLoginCardHeader=%d login card=%s\n",
479 g.syncInfo.bLoginCardHeader,
480 blob_size(&login) ? blob_str(&login) : "<empty>");
481 #endif
482 if( g.syncInfo.bLoginCardHeader ) {
483 /* Send the login card as an HTTP header. */
484 if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
485 #if 1
486 /*blob_append(&payload, blob_buffer(pSend), blob_size(pSend));*/
487 blob_init(&payload, blob_buffer(pSend), blob_size(pSend));
488 #else
489 /* This could save memory but looks like it would break in a
490 ** couple of cases in the loop below where pSend is referenced
491 ** for HTTP 401 and redirects. */
492 blob_zero(&payload);
493 blob_swap(pSend, &payload);
494 #endif
495 }else{
496 blob_compress(pSend, &payload);
497 }
498 }else{
499 /* Prepend the login card (if set) to the payload */
500 if( blob_size(&login) ){
501 blob_append_char(&login, '\n');
502 }
503 if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
504 payload = login;
505 login = empty_blob/*transfer ownership*/;
506 blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
507 }else{
508 blob_compress2(&login, pSend, &payload);
509 blob_reset(&login);
510 }
511 }
 
512 }
513
514 /* Construct the HTTP request header */
515 http_build_header(&payload, &hdr, &login, zAltMimetype);
 
 
 
 
 
 
516
517 /* When tracing, write the transmitted HTTP message both to standard
518 ** output and into a file. The file can then be used to drive the
519 ** server-side like this:
520 **
521
+10 -1
--- src/main.c
+++ src/main.c
@@ -230,11 +230,10 @@
230230
const char *zReqType; /* Type of request: "HTTP", "CGI", "SCGI" */
231231
#if USE_SEE
232232
const char *zPidKey; /* Saved value of the --usepidkey option. Only
233233
* applicable when using SEE on Windows or Linux. */
234234
#endif
235
- char *zLoginCard; /* X-Fossil-Xfer-Login request header value */
236235
int useLocalauth; /* No login required if from 127.0.0.1 */
237236
int noPswd; /* Logged in without password (on 127.0.0.1) */
238237
int userUid; /* Integer user id */
239238
int isHuman; /* True if access by a human, not a spider or bot */
240239
int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
@@ -289,10 +288,15 @@
289288
int allowSymlinks; /* Cached "allow-symlinks" option */
290289
int mainTimerId; /* Set to fossil_timer_start() */
291290
int nPendingRequest; /* # of HTTP requests in "fossil server" */
292291
int nRequest; /* Total # of HTTP request */
293292
int bAvoidDeltaManifests; /* Avoid using delta manifests if true */
293
+ struct {
294
+ char *zLoginCard; /* X-Fossil-Xfer-Login request header value */
295
+ int bLoginCardHeader; /* If true, emit login cards as HTTP headers
296
+ ** instead of as part of the payload */
297
+ } syncInfo;
294298
#ifdef FOSSIL_ENABLE_JSON
295299
struct FossilJsonBits {
296300
int isJsonMode; /* True if running in JSON mode, else
297301
false. This changes how errors are
298302
reported. In JSON mode we try to
@@ -759,10 +763,15 @@
759763
g.tcl.argc = g.argc;
760764
g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
761765
#endif
762766
g.mainTimerId = fossil_timer_start();
763767
capture_case_sensitive_option();
768
+ g.syncInfo.bLoginCardHeader =
769
+ /* This is only for facilitating development of the
770
+ ** xfer-login-card branch. It will be removed or re-imagined at
771
+ ** some point. */
772
+ !!find_option("login-card-header","lch", 0);
764773
g.zVfsName = find_option("vfs",0,1);
765774
if( g.zVfsName==0 ){
766775
g.zVfsName = fossil_getenv("FOSSIL_VFS");
767776
}
768777
if( g.zVfsName ){
769778
--- src/main.c
+++ src/main.c
@@ -230,11 +230,10 @@
230 const char *zReqType; /* Type of request: "HTTP", "CGI", "SCGI" */
231 #if USE_SEE
232 const char *zPidKey; /* Saved value of the --usepidkey option. Only
233 * applicable when using SEE on Windows or Linux. */
234 #endif
235 char *zLoginCard; /* X-Fossil-Xfer-Login request header value */
236 int useLocalauth; /* No login required if from 127.0.0.1 */
237 int noPswd; /* Logged in without password (on 127.0.0.1) */
238 int userUid; /* Integer user id */
239 int isHuman; /* True if access by a human, not a spider or bot */
240 int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
@@ -289,10 +288,15 @@
289 int allowSymlinks; /* Cached "allow-symlinks" option */
290 int mainTimerId; /* Set to fossil_timer_start() */
291 int nPendingRequest; /* # of HTTP requests in "fossil server" */
292 int nRequest; /* Total # of HTTP request */
293 int bAvoidDeltaManifests; /* Avoid using delta manifests if true */
 
 
 
 
 
294 #ifdef FOSSIL_ENABLE_JSON
295 struct FossilJsonBits {
296 int isJsonMode; /* True if running in JSON mode, else
297 false. This changes how errors are
298 reported. In JSON mode we try to
@@ -759,10 +763,15 @@
759 g.tcl.argc = g.argc;
760 g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
761 #endif
762 g.mainTimerId = fossil_timer_start();
763 capture_case_sensitive_option();
 
 
 
 
 
764 g.zVfsName = find_option("vfs",0,1);
765 if( g.zVfsName==0 ){
766 g.zVfsName = fossil_getenv("FOSSIL_VFS");
767 }
768 if( g.zVfsName ){
769
--- src/main.c
+++ src/main.c
@@ -230,11 +230,10 @@
230 const char *zReqType; /* Type of request: "HTTP", "CGI", "SCGI" */
231 #if USE_SEE
232 const char *zPidKey; /* Saved value of the --usepidkey option. Only
233 * applicable when using SEE on Windows or Linux. */
234 #endif
 
235 int useLocalauth; /* No login required if from 127.0.0.1 */
236 int noPswd; /* Logged in without password (on 127.0.0.1) */
237 int userUid; /* Integer user id */
238 int isHuman; /* True if access by a human, not a spider or bot */
239 int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
@@ -289,10 +288,15 @@
288 int allowSymlinks; /* Cached "allow-symlinks" option */
289 int mainTimerId; /* Set to fossil_timer_start() */
290 int nPendingRequest; /* # of HTTP requests in "fossil server" */
291 int nRequest; /* Total # of HTTP request */
292 int bAvoidDeltaManifests; /* Avoid using delta manifests if true */
293 struct {
294 char *zLoginCard; /* X-Fossil-Xfer-Login request header value */
295 int bLoginCardHeader; /* If true, emit login cards as HTTP headers
296 ** instead of as part of the payload */
297 } syncInfo;
298 #ifdef FOSSIL_ENABLE_JSON
299 struct FossilJsonBits {
300 int isJsonMode; /* True if running in JSON mode, else
301 false. This changes how errors are
302 reported. In JSON mode we try to
@@ -759,10 +763,15 @@
763 g.tcl.argc = g.argc;
764 g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
765 #endif
766 g.mainTimerId = fossil_timer_start();
767 capture_case_sensitive_option();
768 g.syncInfo.bLoginCardHeader =
769 /* This is only for facilitating development of the
770 ** xfer-login-card branch. It will be removed or re-imagined at
771 ** some point. */
772 !!find_option("login-card-header","lch", 0);
773 g.zVfsName = find_option("vfs",0,1);
774 if( g.zVfsName==0 ){
775 g.zVfsName = fossil_getenv("FOSSIL_VFS");
776 }
777 if( g.zVfsName ){
778
+15 -7
--- src/xfer.c
+++ src/xfer.c
@@ -1330,26 +1330,27 @@
13301330
zScript = xfer_push_code();
13311331
if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */
13321332
pzUuidList = &zUuidList;
13331333
pnUuidList = &nUuidList;
13341334
}
1335
- if( g.zLoginCard ){
1335
+ if( g.syncInfo.zLoginCard ){
13361336
/* Login card received via HTTP header X-Fossil-Xfer-Login */
13371337
blob_zero(&xfer.line);
1338
- blob_append(&xfer.line, g.zLoginCard, -1);
1338
+ blob_append(&xfer.line, g.syncInfo.zLoginCard, -1);
13391339
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken,
13401340
count(xfer.aToken));
13411341
#if 0
1342
- fprintf(stderr,"%s:%d: g.zLoginCard=[%s]\nnToken=%d tok[0]=%s line=%s\n",
1343
- __FILE__, __LINE__, g.zLoginCard,
1342
+ fprintf(stderr,"%s:%d: g.syncInfo.zLoginCard=[%s]\nnToken=%d tok[0]=%s line=%s\n",
1343
+ __FILE__, __LINE__, g.syncInfo.zLoginCard,
13441344
xfer.nToken, xfer.nToken ? blob_str(&xfer.aToken[0]) : "<NULL>",
13451345
blob_str(&xfer.line));
13461346
#endif
1347
- fossil_free( g.zLoginCard );
1348
- g.zLoginCard = 0;
1347
+ fossil_free( g.syncInfo.zLoginCard );
1348
+ g.syncInfo.zLoginCard = 0;
13491349
if( xfer.nToken==4
13501350
&& blob_eq(&xfer.aToken[0], "login") ){
1351
+ g.syncInfo.bLoginCardHeader = 1;
13511352
goto handle_login_card;
13521353
}
13531354
}
13541355
while( blob_line(xfer.pIn, &xfer.line) ){
13551356
if( blob_buffer(&xfer.line)[0]=='#' ) continue;
@@ -1604,11 +1605,11 @@
16041605
@ error multiple\slogin\cards
16051606
nErr++;
16061607
break;
16071608
}else{
16081609
#if 0
1609
- fprintf(stderr, "handle_login_card: aToken[2]=[%.*s]\n",
1610
+ fprintf(stderr, "# handle_login_card: aToken[2]=[%.*s]\n",
16101611
blob_size(&xfer.aToken[2]),
16111612
blob_str(&xfer.aToken[2]));
16121613
#endif
16131614
if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
16141615
|| check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
@@ -1616,10 +1617,15 @@
16161617
cgi_reset_content();
16171618
@ error login\sfailed
16181619
nErr++;
16191620
break;
16201621
}
1622
+#if 0
1623
+ fprintf(stderr, "# logged in as [%.*s]\n",
1624
+ blob_size(&xfer.aToken[1]),
1625
+ blob_str(&xfer.aToken[1]));
1626
+#endif
16211627
}
16221628
}else
16231629
16241630
/* reqconfig NAME
16251631
**
@@ -1745,10 +1751,12 @@
17451751
** is running. The DATE and TIME are a pure numeric ISO8601 time
17461752
** for the specific check-in of the client.
17471753
*/
17481754
if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){
17491755
xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
1756
+ g.syncInfo.bLoginCardHeader =
1757
+ xfer.remoteVersion>=RELEASE_VERSION_NUMBER;
17501758
if( xfer.nToken>=5 ){
17511759
xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
17521760
xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
17531761
@ pragma server-version %d(RELEASE_VERSION_NUMBER) \
17541762
@ %d(MANIFEST_NUMERIC_DATE) %d(MANIFEST_NUMERIC_TIME)
17551763
--- src/xfer.c
+++ src/xfer.c
@@ -1330,26 +1330,27 @@
1330 zScript = xfer_push_code();
1331 if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */
1332 pzUuidList = &zUuidList;
1333 pnUuidList = &nUuidList;
1334 }
1335 if( g.zLoginCard ){
1336 /* Login card received via HTTP header X-Fossil-Xfer-Login */
1337 blob_zero(&xfer.line);
1338 blob_append(&xfer.line, g.zLoginCard, -1);
1339 xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken,
1340 count(xfer.aToken));
1341 #if 0
1342 fprintf(stderr,"%s:%d: g.zLoginCard=[%s]\nnToken=%d tok[0]=%s line=%s\n",
1343 __FILE__, __LINE__, g.zLoginCard,
1344 xfer.nToken, xfer.nToken ? blob_str(&xfer.aToken[0]) : "<NULL>",
1345 blob_str(&xfer.line));
1346 #endif
1347 fossil_free( g.zLoginCard );
1348 g.zLoginCard = 0;
1349 if( xfer.nToken==4
1350 && blob_eq(&xfer.aToken[0], "login") ){
 
1351 goto handle_login_card;
1352 }
1353 }
1354 while( blob_line(xfer.pIn, &xfer.line) ){
1355 if( blob_buffer(&xfer.line)[0]=='#' ) continue;
@@ -1604,11 +1605,11 @@
1604 @ error multiple\slogin\cards
1605 nErr++;
1606 break;
1607 }else{
1608 #if 0
1609 fprintf(stderr, "handle_login_card: aToken[2]=[%.*s]\n",
1610 blob_size(&xfer.aToken[2]),
1611 blob_str(&xfer.aToken[2]));
1612 #endif
1613 if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
1614 || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
@@ -1616,10 +1617,15 @@
1616 cgi_reset_content();
1617 @ error login\sfailed
1618 nErr++;
1619 break;
1620 }
 
 
 
 
 
1621 }
1622 }else
1623
1624 /* reqconfig NAME
1625 **
@@ -1745,10 +1751,12 @@
1745 ** is running. The DATE and TIME are a pure numeric ISO8601 time
1746 ** for the specific check-in of the client.
1747 */
1748 if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){
1749 xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
 
 
1750 if( xfer.nToken>=5 ){
1751 xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
1752 xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
1753 @ pragma server-version %d(RELEASE_VERSION_NUMBER) \
1754 @ %d(MANIFEST_NUMERIC_DATE) %d(MANIFEST_NUMERIC_TIME)
1755
--- src/xfer.c
+++ src/xfer.c
@@ -1330,26 +1330,27 @@
1330 zScript = xfer_push_code();
1331 if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */
1332 pzUuidList = &zUuidList;
1333 pnUuidList = &nUuidList;
1334 }
1335 if( g.syncInfo.zLoginCard ){
1336 /* Login card received via HTTP header X-Fossil-Xfer-Login */
1337 blob_zero(&xfer.line);
1338 blob_append(&xfer.line, g.syncInfo.zLoginCard, -1);
1339 xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken,
1340 count(xfer.aToken));
1341 #if 0
1342 fprintf(stderr,"%s:%d: g.syncInfo.zLoginCard=[%s]\nnToken=%d tok[0]=%s line=%s\n",
1343 __FILE__, __LINE__, g.syncInfo.zLoginCard,
1344 xfer.nToken, xfer.nToken ? blob_str(&xfer.aToken[0]) : "<NULL>",
1345 blob_str(&xfer.line));
1346 #endif
1347 fossil_free( g.syncInfo.zLoginCard );
1348 g.syncInfo.zLoginCard = 0;
1349 if( xfer.nToken==4
1350 && blob_eq(&xfer.aToken[0], "login") ){
1351 g.syncInfo.bLoginCardHeader = 1;
1352 goto handle_login_card;
1353 }
1354 }
1355 while( blob_line(xfer.pIn, &xfer.line) ){
1356 if( blob_buffer(&xfer.line)[0]=='#' ) continue;
@@ -1604,11 +1605,11 @@
1605 @ error multiple\slogin\cards
1606 nErr++;
1607 break;
1608 }else{
1609 #if 0
1610 fprintf(stderr, "# handle_login_card: aToken[2]=[%.*s]\n",
1611 blob_size(&xfer.aToken[2]),
1612 blob_str(&xfer.aToken[2]));
1613 #endif
1614 if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
1615 || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
@@ -1616,10 +1617,15 @@
1617 cgi_reset_content();
1618 @ error login\sfailed
1619 nErr++;
1620 break;
1621 }
1622 #if 0
1623 fprintf(stderr, "# logged in as [%.*s]\n",
1624 blob_size(&xfer.aToken[1]),
1625 blob_str(&xfer.aToken[1]));
1626 #endif
1627 }
1628 }else
1629
1630 /* reqconfig NAME
1631 **
@@ -1745,10 +1751,12 @@
1751 ** is running. The DATE and TIME are a pure numeric ISO8601 time
1752 ** for the specific check-in of the client.
1753 */
1754 if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){
1755 xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
1756 g.syncInfo.bLoginCardHeader =
1757 xfer.remoteVersion>=RELEASE_VERSION_NUMBER;
1758 if( xfer.nToken>=5 ){
1759 xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
1760 xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
1761 @ pragma server-version %d(RELEASE_VERSION_NUMBER) \
1762 @ %d(MANIFEST_NUMERIC_DATE) %d(MANIFEST_NUMERIC_TIME)
1763

Keyboard Shortcuts

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