Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Doc improvements and internal API renaming for clarity. No functional changes. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | xfer-login-card |
| Files: | files | file ages | folders |
| SHA3-256: |
286110dec0d1b95f82743768b5c7572e |
| User & Date: | stephan 2025-07-24 02:20:36.703 |
Context
|
2025-07-24
| ||
| 02:41 | Update the change log and sync.wiki for the login card additions. ... (check-in: edfa01d9d2 user: stephan tags: xfer-login-card) | |
| 02:20 | Doc improvements and internal API renaming for clarity. No functional changes. ... (check-in: 286110dec0 user: stephan tags: xfer-login-card) | |
| 01:12 | Remove some debug output. ... (check-in: d1b7be2ff8 user: stephan tags: xfer-login-card) | |
Changes
Changes to src/cgi.c.
| ︙ | ︙ | |||
1282 1283 1284 1285 1286 1287 1288 | static NORETURN void malformed_request(const char *zMsg, ...); /* ** Checks the QUERY_STRING environment variable, sets it up via ** add_param_list() and, if found, applies its "skin" setting. Returns ** 0 if no QUERY_STRING is set, else it returns a bitmask of: ** | | | | | 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 |
static NORETURN void malformed_request(const char *zMsg, ...);
/*
** Checks the QUERY_STRING environment variable, sets it up via
** add_param_list() and, if found, applies its "skin" setting. Returns
** 0 if no QUERY_STRING is set, else it returns a bitmask of:
**
** 0x01 = QUERY_STRING was set up
** 0x02 = "skin" GET arg was processed
** 0x04 = "x-f-x-l" GET arg was processed.
**
* In the case of the skin, the cookie may still need flushing
** by the page, via cookie_render().
*/
int cgi_setup_query_string(void){
int rc = 0;
char * z = (char*)P("QUERY_STRING");
|
| ︙ | ︙ | |||
1316 1317 1318 1319 1320 1321 1322 |
if( !g.syncInfo.zLoginCard && 0!=(z=(char*)P("x-f-x-l")) ){
/* CGI fossil instances do not read the HTTP headers, so
** they cannot see the X-Fossil-Xfer-Login card. As a consolation
** to them, we'll accept that via this query argument. */
rc |= 0x04;
fossil_free( g.syncInfo.zLoginCard );
g.syncInfo.zLoginCard = fossil_strdup(z);
| | | 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 |
if( !g.syncInfo.zLoginCard && 0!=(z=(char*)P("x-f-x-l")) ){
/* CGI fossil instances do not read the HTTP headers, so
** they cannot see the X-Fossil-Xfer-Login card. As a consolation
** to them, we'll accept that via this query argument. */
rc |= 0x04;
fossil_free( g.syncInfo.zLoginCard );
g.syncInfo.zLoginCard = fossil_strdup(z);
g.syncInfo.fLoginCardMode = 3;
cgi_delete_parameter("x-f-x-l");
}
}
return rc;
}
/*
|
| ︙ | ︙ | |||
2139 2140 2141 2142 2143 2144 2145 | char *z, *zToken; int i; const char *zScheme = "http"; char zLine[2000]; /* A single line of input. */ g.fullHttpReply = 1; g.zReqType = "HTTP"; | < | 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 |
char *z, *zToken;
int i;
const char *zScheme = "http";
char zLine[2000]; /* A single line of input. */
g.fullHttpReply = 1;
g.zReqType = "HTTP";
if( cgi_fgets(zLine, sizeof(zLine))==0 ){
malformed_request("missing header");
}
blob_append(&g.httpHeader, zLine, -1);
cgi_trace(zLine);
zToken = extract_token(zLine, &z);
if( zToken==0 ){
|
| ︙ | ︙ | |||
2238 2239 2240 2241 2242 2243 2244 |
if( sscanf(zVal,"bytes=%d-%d",&x1,&x2)==2 && x1>=0 && x1<=x2 ){
rangeStart = x1;
rangeEnd = x2+1;
}
}else if( fossil_strcmp(zFieldName, "x-fossil-xfer-login:")==0 ){
fossil_free( g.syncInfo.zLoginCard );
g.syncInfo.zLoginCard = fossil_strdup(zVal);
| | | 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 |
if( sscanf(zVal,"bytes=%d-%d",&x1,&x2)==2 && x1>=0 && x1<=x2 ){
rangeStart = x1;
rangeEnd = x2+1;
}
}else if( fossil_strcmp(zFieldName, "x-fossil-xfer-login:")==0 ){
fossil_free( g.syncInfo.zLoginCard );
g.syncInfo.zLoginCard = fossil_strdup(zVal);
g.syncInfo.fLoginCardMode = 1;
}
}
cgi_setenv("REQUEST_SCHEME",zScheme);
cgi_init();
cgi_trace(0);
}
|
| ︙ | ︙ |
Changes to src/http.c.
| ︙ | ︙ | |||
135 136 137 138 139 140 141 |
** g.url.path, replacing any "?..." part of g.url.path. ABC = the
** %T-encoded contents of pLogin. This is workaround for feeding the
** login card to CGI-hosted fossil instances, as those do not read the
** HTTP headers so cannot see the X-Fossil-Xfer-Login (x-f-x-l)
** header.
*/
static void url_append_login_card(Blob * const pLogin){
| | | | | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
** g.url.path, replacing any "?..." part of g.url.path. ABC = the
** %T-encoded contents of pLogin. This is workaround for feeding the
** login card to CGI-hosted fossil instances, as those do not read the
** HTTP headers so cannot see the X-Fossil-Xfer-Login (x-f-x-l)
** header.
*/
static void url_append_login_card(Blob * const pLogin){
if( g.syncInfo.fLoginCardMode ||
g.syncInfo.remoteVersion >= RELEASE_VERSION_NUMBER ){
char * x;
char * z = g.url.path;
while( z && *z && '?'!=*z ) ++z;
if( z && *z ) *z = 0;
x = mprintf("%s?x-f-x-l=%T", g.url.path ? g.url.path : "/",
blob_str(pLogin));
fossil_free(g.url.path);
g.url.path = x;
if( !g.syncInfo.fLoginCardMode ){
g.syncInfo.fLoginCardMode = 4;
}
}
}
/*
** Construct an appropriate HTTP request header. Write the header
** into pHdr. This routine initializes the pHdr blob. pPayload is
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 |
fossil_free(zEncoded);
}
blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
if( pLogin && blob_size(pLogin) ){
blob_appendf(pHdr, "X-Fossil-Xfer-Login: %b\r\n", pLogin)
| | > > | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
fossil_free(zEncoded);
}
blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
if( pLogin && blob_size(pLogin) ){
blob_appendf(pHdr, "X-Fossil-Xfer-Login: %b\r\n", pLogin)
/* Noting that CGIs can't read headers, but test-http can. If we
** set this _only_ as a URL argument then we lose that info for
** purposes of feeding it back through test-http. */;
}
if( nPayload ){
if( zAltMimetype ){
blob_appendf(pHdr, "Content-Type: %s\r\n", zAltMimetype);
}else if( g.fHttpTrace ){
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
}else{
|
| ︙ | ︙ | |||
499 500 501 502 503 504 505 |
}
/* Construct the login card and prepare the complete payload */
blob_zero(&login);
if( blob_size(pSend)==0 ){
blob_zero(&payload);
}else{
if( mHttpFlags & HTTP_USE_LOGIN ) http_build_login_card(pSend, &login);
| | | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
}
/* Construct the login card and prepare the complete payload */
blob_zero(&login);
if( blob_size(pSend)==0 ){
blob_zero(&payload);
}else{
if( mHttpFlags & HTTP_USE_LOGIN ) http_build_login_card(pSend, &login);
if( g.syncInfo.fLoginCardMode>0 ){
/* The login card will be sent via an HTTP header and/or URL flag. */
if( g.fHttpTrace || (mHttpFlags & HTTP_NOCOMPRESS)!=0 ){
/* Maintenance note: we cannot blob_swap(pSend,&payload) here
** because the HTTP 401 and redirect response handling below
** needs pSend unmodified. payload won't be modified after
** this point, so we can make it a proxy for pSend for
** zero heap memory. */
|
| ︙ | ︙ | |||
692 693 694 695 696 697 698 |
}else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
isError = 1;
}
}
}else if( fossil_strnicmp(zLine, "x-fossil-xfer-login: ", 21)==0 ){
fossil_free( g.syncInfo.zLoginCard );
g.syncInfo.zLoginCard = fossil_strdup(&zLine[21]);
| | | 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 |
}else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
isError = 1;
}
}
}else if( fossil_strnicmp(zLine, "x-fossil-xfer-login: ", 21)==0 ){
fossil_free( g.syncInfo.zLoginCard );
g.syncInfo.zLoginCard = fossil_strdup(&zLine[21]);
g.syncInfo.fLoginCardMode = 1;
}
}
if( iHttpVersion<0 ){
/* We got nothing back from the server. If using the ssh: protocol,
** this might mean we need to add or remove the PATH=... argument
** to the SSH command being sent. If that is the case, retry the
** request after adding or removing the PATH= argument.
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
290 291 292 293 294 295 296 |
int nPendingRequest; /* # of HTTP requests in "fossil server" */
int nRequest; /* Total # of HTTP request */
int bAvoidDeltaManifests; /* Avoid using delta manifests if true */
/* State for communicating specific details between the inbound HTTP
** header parser (cgi.c), xfer.c, and http.c. */
struct {
| | | | | > | | < | | < | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
int nPendingRequest; /* # of HTTP requests in "fossil server" */
int nRequest; /* Total # of HTTP request */
int bAvoidDeltaManifests; /* Avoid using delta manifests if true */
/* State for communicating specific details between the inbound HTTP
** header parser (cgi.c), xfer.c, and http.c. */
struct {
char *zLoginCard; /* Inbound "X-Fossil-Xfer-Login" request
** header or "x-f-x-l" URL parameter. */
int fLoginCardMode; /* If non-0, emit login cards in outbound
** requests as a HTTP header or URL
** parameter instead of as part of the
** payload. Gets activated on-demand based
** on xfer traffic contents. Values, for
** diagnostic/debugging purposes: 1=CLI
** --flag. 2=inbound HTTP header. 3=query
** string arg. 4=http_build_header(). */
int remoteVersion; /* Remote fossil version. Used for negotiating
** how to handle the login card. */
} syncInfo;
#ifdef FOSSIL_ENABLE_JSON
struct FossilJsonBits {
int isJsonMode; /* True if running in JSON mode, else
false. This changes how errors are
|
| ︙ | ︙ | |||
774 775 776 777 778 779 780 | #ifdef FOSSIL_ENABLE_TCL memset(&g.tcl, 0, sizeof(TclContext)); g.tcl.argc = g.argc; g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */ #endif g.mainTimerId = fossil_timer_start(); capture_case_sensitive_option(); | | | 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
#ifdef FOSSIL_ENABLE_TCL
memset(&g.tcl, 0, sizeof(TclContext));
g.tcl.argc = g.argc;
g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
#endif
g.mainTimerId = fossil_timer_start();
capture_case_sensitive_option();
g.syncInfo.fLoginCardMode =
/* This is only for facilitating development of the
** xfer-login-card branch. It will be removed or re-imagined at
** some point. */
!!find_option("login-card-header","lch", 0);
g.zVfsName = find_option("vfs",0,1);
if( g.zVfsName==0 ){
g.zVfsName = fossil_getenv("FOSSIL_VFS");
|
| ︙ | ︙ |