| ︙ | | | ︙ | |
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
int *aCommitFile; /* Array of files to be committed */
int markPrivate; /* All new artifacts are private if true */
char *ckinLockFail; /* Check-in lock failure received from server */
int clockSkewSeen; /* True if clocks on client and server out of sync */
int wikiFlags; /* Wiki conversion flags applied to %W */
char isHTTP; /* True if server/CGI modes, else assume CLI. */
char javascriptHyperlink; /* If true, set href= using script, not HTML */
Blob httpHeader; /* Complete text of the HTTP request header */
UrlData url; /* Information about current URL */
const char *zLogin; /* Login name. NULL or "" if not logged in. */
const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
** SSL client identity */
|
|
|
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
int *aCommitFile; /* Array of files to be committed */
int markPrivate; /* All new artifacts are private if true */
char *ckinLockFail; /* Check-in lock failure received from server */
int clockSkewSeen; /* True if clocks on client and server out of sync */
int wikiFlags; /* Wiki conversion flags applied to %W */
char isHTTP; /* True if server/CGI modes, else assume CLI. */
char jsHref; /* If true, set href= using javascript, not HTML */
Blob httpHeader; /* Complete text of the HTTP request header */
UrlData url; /* Information about current URL */
const char *zLogin; /* Login name. NULL or "" if not logged in. */
const char *zCkoutAlias; /* doc/ uses this branch as an alias for "ckout" */
const char *zMainMenuFile; /* --mainmenu FILE from server/ui/cgi */
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
** SSL client identity */
|
| ︙ | | | ︙ | |
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
|
unsigned int i, j, k; /* Loop counters */
int n; /* Number of bytes in one line */
unsigned int nArg; /* Number of new arguments */
char *z; /* General use string pointer */
char **newArgv; /* New expanded g.argv under construction */
const char *zFileName; /* input file name */
FILE *inFile; /* input FILE */
#if defined(_WIN32)
wchar_t buf[MAX_PATH];
#endif
g.argc = argc;
g.argv = argv;
sqlite3_initialize();
#if defined(_WIN32) && defined(BROKEN_MINGW_CMDLINE)
for(i=0; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
#else
for(i=0; i<g.argc; i++) g.argv[i] = fossil_path_to_utf8(g.argv[i]);
#endif
#if defined(_WIN32)
GetModuleFileNameW(NULL, buf, MAX_PATH);
g.nameOfExe = fossil_path_to_utf8(buf);
#else
g.nameOfExe = g.argv[0];
#endif
for(i=1; i<g.argc-1; i++){
z = g.argv[i];
if( z[0]!='-' ) continue;
z++;
if( z[0]=='-' ) z++;
if( z[0]==0 ) return; /* Stop searching at "--" */
if( fossil_strcmp(z, "args")==0 ) break;
|
<
<
<
<
<
<
<
|
<
|
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
|
unsigned int i, j, k; /* Loop counters */
int n; /* Number of bytes in one line */
unsigned int nArg; /* Number of new arguments */
char *z; /* General use string pointer */
char **newArgv; /* New expanded g.argv under construction */
const char *zFileName; /* input file name */
FILE *inFile; /* input FILE */
g.argc = argc;
g.argv = argv;
sqlite3_initialize();
#if defined(_WIN32) && defined(BROKEN_MINGW_CMDLINE)
for(i=0; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
#else
for(i=0; i<g.argc; i++) g.argv[i] = fossil_path_to_utf8(g.argv[i]);
#endif
g.nameOfExe = file_fullexename(g.argv[0]);
for(i=1; i<g.argc-1; i++){
z = g.argv[i];
if( z[0]!='-' ) continue;
z++;
if( z[0]=='-' ) z++;
if( z[0]==0 ) return; /* Stop searching at "--" */
if( fossil_strcmp(z, "args")==0 ) break;
|
| ︙ | | | ︙ | |
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
|
}
}
fossil_exit(0);
#endif
}else if( rc==2 ){
Blob couldbe;
blob_init(&couldbe,0,0);
dispatch_matching_names(zCmdName, &couldbe);
fossil_print("%s: ambiguous command prefix: %s\n"
"%s: could be any of:%s\n"
"%s: use \"help\" for more information\n",
g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
fossil_exit(1);
}
#ifdef FOSSIL_ENABLE_JSON
|
|
|
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
|
}
}
fossil_exit(0);
#endif
}else if( rc==2 ){
Blob couldbe;
blob_init(&couldbe,0,0);
dispatch_matching_names(zCmdName, CMDFLAG_COMMAND, &couldbe);
fossil_print("%s: ambiguous command prefix: %s\n"
"%s: could be any of:%s\n"
"%s: use \"help\" for more information\n",
g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
fossil_exit(1);
}
#ifdef FOSSIL_ENABLE_JSON
|
| ︙ | | | ︙ | |
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
|
zURL = mprintf("%s%T?%s", g.zHttpsURL, P("PATH_INFO"), zQS);
}
cgi_redirect_with_status(zURL, 301, "Moved Permanently");
return 1;
}
return 0;
}
/*
** Preconditions:
**
** * Environment variables are set up according to the CGI standard.
**
** If the repository is known, it has already been opened. If unknown,
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
|
zURL = mprintf("%s%T?%s", g.zHttpsURL, P("PATH_INFO"), zQS);
}
cgi_redirect_with_status(zURL, 301, "Moved Permanently");
return 1;
}
return 0;
}
/*
** Send a 404 Not Found reply
*/
void fossil_not_found_page(void){
#ifdef FOSSIL_ENABLE_JSON
if(g.json.isJsonMode){
json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
return;
}
#endif
@ <html><head>
@ <meta name="viewport" \
@ content="width=device-width, initial-scale=1.0">
@ </head><body>
@ <h1>Not Found</h1>
@ </body>
cgi_set_status(404, "Not Found");
cgi_reply();
}
/*
** Preconditions:
**
** * Environment variables are set up according to the CGI standard.
**
** If the repository is known, it has already been opened. If unknown,
|
| ︙ | | | ︙ | |
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
|
if( (zPathInfo[0]==0 || strcmp(zPathInfo,"/")==0)
&& allowRepoList
&& repo_list_page() ){
/* Will return a list of repositories */
}else if( zNotFound ){
cgi_redirect(zNotFound);
}else{
#ifdef FOSSIL_ENABLE_JSON
if(g.json.isJsonMode){
json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
return;
}
#endif
@ <html><head>
@ <meta name="viewport" \
@ content="width=device-width, initial-scale=1.0">
@ </head><body>
@ <h1>Not Found</h1>
@ </body>
cgi_set_status(404, "Not Found");
cgi_reply();
}
return;
}
break;
}
/* Add the repository name (without the ".fossil" suffix) to the end
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
|
if( (zPathInfo[0]==0 || strcmp(zPathInfo,"/")==0)
&& allowRepoList
&& repo_list_page() ){
/* Will return a list of repositories */
}else if( zNotFound ){
cgi_redirect(zNotFound);
}else{
fossil_not_found_page();
}
return;
}
break;
}
/* Add the repository name (without the ".fossil" suffix) to the end
|
| ︙ | | | ︙ | |
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
|
}
}
/* At this point, the appropriate repository database file will have
** been opened.
*/
/*
** Check to see if the first term of PATH_INFO specifies an
** alternative skin. This will be the case if the first term of
** PATH_INFO begins with "draftN/" where N is an integer between 1
** and 9. If so, activate the skin associated with that draft.
*/
if( zPathInfo && strncmp(zPathInfo,"/draft",6)==0
&& zPathInfo[6]>='1' && zPathInfo[6]<='9'
&& (zPathInfo[7]=='/' || zPathInfo[7]==0)
){
int iSkin = zPathInfo[6] - '0';
char *zNewScript;
skin_use_draft(iSkin);
zNewScript = mprintf("%T/draft%d", P("SCRIPT_NAME"), iSkin);
if( g.zTop ) g.zTop = mprintf("%R/draft%d", iSkin);
if( g.zBaseURL ) g.zBaseURL = mprintf("%s/draft%d", g.zBaseURL, iSkin);
zPathInfo += 7;
g.nExtraURL += 7;
cgi_replace_parameter("PATH_INFO", zPathInfo);
|
<
>
>
>
>
>
|
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
|
}
}
/* At this point, the appropriate repository database file will have
** been opened.
*/
/*
** Check to see if the first term of PATH_INFO specifies an
** alternative skin. This will be the case if the first term of
** PATH_INFO begins with "draftN/" where N is an integer between 1
** and 9. If so, activate the skin associated with that draft.
*/
if( zPathInfo && strncmp(zPathInfo,"/draft",6)==0
&& zPathInfo[6]>='1' && zPathInfo[6]<='9'
&& (zPathInfo[7]=='/' || zPathInfo[7]==0)
){
int iSkin = zPathInfo[6] - '0';
char *zNewScript;
if( db_int(0,"SELECT count(*) FROM config WHERE name GLOB 'draft%d-*'",
iSkin)<5 ){
fossil_not_found_page();
fossil_exit(0);
}
skin_use_draft(iSkin);
zNewScript = mprintf("%T/draft%d", P("SCRIPT_NAME"), iSkin);
if( g.zTop ) g.zTop = mprintf("%R/draft%d", iSkin);
if( g.zBaseURL ) g.zBaseURL = mprintf("%s/draft%d", g.zBaseURL, iSkin);
zPathInfo += 7;
g.nExtraURL += 7;
cgi_replace_parameter("PATH_INFO", zPathInfo);
|
| ︙ | | | ︙ | |
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|
#endif
{
@ <h1>Server Configuration Error</h1>
@ <p>The database schema on the server is out-of-date. Please ask
@ the administrator to run <b>fossil rebuild</b>.</p>
}
}else{
#ifdef FOSSIL_ENABLE_JSON
static int jsonOnce = 0;
if( jsonOnce==0 && g.json.isJsonMode!=0 ){
assert(json_is_bootstrapped_early());
json_bootstrap_late();
jsonOnce = 1;
}
|
>
>
>
|
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
|
#endif
{
@ <h1>Server Configuration Error</h1>
@ <p>The database schema on the server is out-of-date. Please ask
@ the administrator to run <b>fossil rebuild</b>.</p>
}
}else{
if(0==(CMDFLAG_LDAVG_EXEMPT & pCmd->eCmdFlags)){
load_control();
}
#ifdef FOSSIL_ENABLE_JSON
static int jsonOnce = 0;
if( jsonOnce==0 && g.json.isJsonMode!=0 ){
assert(json_is_bootstrapped_early());
json_bootstrap_late();
jsonOnce = 1;
}
|
| ︙ | | | ︙ | |
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
|
/*
** COMMAND: http*
**
** Usage: %fossil http ?REPOSITORY? ?OPTIONS?
**
** Handle a single HTTP request appearing on stdin. The resulting webpage
** is delivered on stdout. This method is used to launch an HTTP request
** handler from inetd, for example. The argument is the name of the
** repository.
**
** If REPOSITORY is a directory that contains one or more repositories,
** either directly in REPOSITORY itself or in subdirectories, and
** with names of the form "*.fossil" then a prefix of the URL pathname
** selects from among the various repositories. If the pathname does
** not select a valid repository and the --notfound option is available,
** then the server redirects (HTTP code 302) to the URL of --notfound.
** When REPOSITORY is a directory, the pathname must contain only
** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
** and every "." must be surrounded on both sides by alphanumerics or else
** a 404 error is returned. Static content files in the directory are
** returned if they match comma-separate GLOB pattern specified by --files
** and do not match "*.fossil*" and have a well-known suffix.
**
** The --host option can be used to specify the hostname for the server.
** The --https option indicates that the request came from HTTPS rather
** than HTTP. If --nossl is given, then SSL connections will not be available,
** thus also no redirecting from http: to https: will take place.
**
** If the --localauth option is given, then automatic login is performed
** for requests coming from localhost, if the "localauth" setting is not
** enabled.
**
** Options:
** --acme Deliver files from the ".well-known" subdirectory
** --baseurl URL base URL (useful with reverse proxies)
** --cert FILE Use TLS (HTTPS) encryption with the certificate (the
** fullchain.pem) taken from FILE.
** --chroot DIR Use directory for chroot instead of repository path.
** --ckout-alias N Treat URIs of the form /doc/N/... as if they were
** /doc/ckout/...
** --extroot DIR document root for the /ext extension mechanism
** --files GLOB comma-separate glob patterns for static file to serve
** --host NAME specify hostname of the server
** --https signal a request coming in via https
** --in FILE Take input from FILE instead of standard input
** --ipaddr ADDR Assume the request comes from the given IP address
** --jsmode MODE Determine how JavaScript is delivered with pages.
** Mode can be one of:
** inline All JavaScript is inserted inline at
** one or more points in the HTML file.
** separate Separate HTTP requests are made for
** each JavaScript file.
** bundled Groups JavaScript files into one or
** more bundled requests which
** concatenate scripts together.
** Depending on the needs of any given page, inline
** and bundled modes might result in a single
** amalgamated script or several, but both approaches
** result in fewer HTTP requests than the separate mode.
** --localauth enable automatic login for local connections
** --mainmenu FILE Override the mainmenu config setting with the contents
** of the given file.
** --nocompress do not compress HTTP replies
** --nodelay omit backoffice processing if it would delay
** process exit
** --nojail drop root privilege but do not enter the chroot jail
** --nossl signal that no SSL connections are available
** --notfound URL use URL as "HTTP 404, object not found" page.
** --out FILE write results to FILE instead of to standard output
** --pkey FILE Read the private key used for TLS from FILE.
** --repolist If REPOSITORY is directory, URL "/" lists all repos
** --scgi Interpret input as SCGI rather than HTTP
** --skin LABEL Use override skin LABEL
** --th-trace trace TH1 execution (for debugging purposes)
** --usepidkey Use saved encryption key from parent process. This is
** only necessary when using SEE on Windows.
**
** See also: [[cgi]], [[server]], [[winsrv]]
*/
void cmd_http(void){
const char *zIpAddr = 0;
|
|
|
<
<
<
<
<
<
<
<
<
|
|
|
|
>
>
|
>
|
|
|
|
>
|
|
>
|
|
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
|
/*
** COMMAND: http*
**
** Usage: %fossil http ?REPOSITORY? ?OPTIONS?
**
** Handle a single HTTP request appearing on stdin. The resulting webpage
** is delivered on stdout. This method is used to launch an HTTP request
** handler from inetd, for example. The REPOSITORY argument is the name of
** the repository.
**
** If REPOSITORY is a directory that contains one or more repositories,
** either directly in REPOSITORY itself or in subdirectories, and
** with names of the form "*.fossil" then a prefix of the URL pathname
** selects from among the various repositories. If the pathname does
** not select a valid repository and the --notfound option is available,
** then the server redirects (HTTP code 302) to the URL of --notfound.
** When REPOSITORY is a directory, the pathname must contain only
** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/"
** and every "." must be surrounded on both sides by alphanumerics or else
** a 404 error is returned. Static content files in the directory are
** returned if they match comma-separate GLOB pattern specified by --files
** and do not match "*.fossil*" and have a well-known suffix.
**
** Options:
** --acme Deliver files from the ".well-known" subdirectory
** --baseurl URL base URL (useful with reverse proxies)
** --cert FILE Use TLS (HTTPS) encryption with the certificate (the
** fullchain.pem) taken from FILE.
** --chroot DIR Use directory for chroot instead of repository path.
** --ckout-alias N Treat URIs of the form /doc/N/... as if they were
** /doc/ckout/...
** --extroot DIR Document root for the /ext extension mechanism
** --files GLOB Comma-separate glob patterns for static file to serve
** --host NAME DNS Hostname of the server
** --https The HTTP request originated from https but has already
** been decoded by a reverse proxy. Hence, URLs created
** by Fossil should use "https:" rather than "http:".
** --in FILE Take input from FILE instead of standard input
** --ipaddr ADDR Assume the request comes from the given IP address
** --jsmode MODE Determine how JavaScript is delivered with pages.
** Mode can be one of:
** inline All JavaScript is inserted inline at
** one or more points in the HTML file.
** separate Separate HTTP requests are made for
** each JavaScript file.
** bundled Groups JavaScript files into one or
** more bundled requests which
** concatenate scripts together.
** Depending on the needs of any given page, inline
** and bundled modes might result in a single
** amalgamated script or several, but both approaches
** result in fewer HTTP requests than the separate mode.
** --localauth Connections from localhost are given "setup"
** privileges without having to log in.
** --mainmenu FILE Override the mainmenu config setting with the contents
** of the given file.
** --nocompress Do not compress HTTP replies
** --nodelay Omit backoffice processing if it would delay
** process exit
** --nojail Drop root privilege but do not enter the chroot jail
** --nossl Do not do http: to https: redirects, regardless of
** the redirect-to-https setting.
** --notfound URL Use URL as the "HTTP 404, object not found" page.
** --out FILE Write the HTTP reply to FILE instead of to
** standard output
** --pkey FILE Read the private key used for TLS from FILE.
** --repolist If REPOSITORY is directory, URL "/" lists all repos
** --scgi Interpret input as SCGI rather than HTTP
** --skin LABEL Use override skin LABEL
** --th-trace Trace TH1 execution (for debugging purposes)
** --usepidkey Use saved encryption key from parent process. This is
** only necessary when using SEE on Windows.
**
** See also: [[cgi]], [[server]], [[winsrv]]
*/
void cmd_http(void){
const char *zIpAddr = 0;
|
| ︙ | | | ︙ | |
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
|
zInFile = find_option("in",0,1);
if( zInFile ){
backoffice_disable();
g.httpIn = fossil_fopen(zInFile, "rb");
if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile);
}else{
g.httpIn = stdin;
}
zOutFile = find_option("out",0,1);
if( zOutFile ){
g.httpOut = fossil_fopen(zOutFile, "wb");
if( g.httpOut==0 ) fossil_fatal("cannot open \"%s\" for writing", zOutFile);
}else{
g.httpOut = stdout;
}
zIpAddr = find_option("ipaddr",0,1);
useSCGI = find_option("scgi", 0, 0)!=0;
zAltBase = find_option("baseurl", 0, 1);
if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay();
if( zAltBase ) set_base_url(zAltBase);
if( find_option("https",0,0)!=0 ){
|
>
>
>
>
>
>
|
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
|
zInFile = find_option("in",0,1);
if( zInFile ){
backoffice_disable();
g.httpIn = fossil_fopen(zInFile, "rb");
if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile);
}else{
g.httpIn = stdin;
#if defined(_WIN32)
_setmode(_fileno(stdin), _O_BINARY);
#endif
}
zOutFile = find_option("out",0,1);
if( zOutFile ){
g.httpOut = fossil_fopen(zOutFile, "wb");
if( g.httpOut==0 ) fossil_fatal("cannot open \"%s\" for writing", zOutFile);
}else{
g.httpOut = stdout;
#if defined(_WIN32)
_setmode(_fileno(stdout), _O_BINARY);
#endif
}
zIpAddr = find_option("ipaddr",0,1);
useSCGI = find_option("scgi", 0, 0)!=0;
zAltBase = find_option("baseurl", 0, 1);
if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay();
if( zAltBase ) set_base_url(zAltBase);
if( find_option("https",0,0)!=0 ){
|
| ︙ | | | ︙ | |