dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Copyright (c) 2006 D. Richard Hipp dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is free software; you can redistribute it and/or dbda8d6ce9 2007-07-21 drh: ** modify it under the terms of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License version 2 as published by the Free Software Foundation. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is distributed in the hope that it will be useful, dbda8d6ce9 2007-07-21 drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of dbda8d6ce9 2007-07-21 drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dbda8d6ce9 2007-07-21 drh: ** General Public License for more details. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** You should have received a copy of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License along with this library; if not, write to the dbda8d6ce9 2007-07-21 drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, dbda8d6ce9 2007-07-21 drh: ** Boston, MA 02111-1307, USA. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Author contact information: dbda8d6ce9 2007-07-21 drh: ** drh@hwaci.com dbda8d6ce9 2007-07-21 drh: ** http://www.hwaci.com/drh/ dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ******************************************************************************* dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This module codes the main() procedure that runs first when the dbda8d6ce9 2007-07-21 drh: ** program is invoked. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "main.h" dbda8d6ce9 2007-07-21 drh: #include <string.h> dbda8d6ce9 2007-07-21 drh: #include <time.h> dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: #if INTERFACE dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Number of elements in an array dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #define count(X) (sizeof(X)/sizeof(X[0])) dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Size of a UUID in characters dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #define UUID_SIZE 40 dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* 55342eb9fb 2008-05-17 drh: ** Maximum number of auxiliary parameters on reports 55342eb9fb 2008-05-17 drh: */ 55342eb9fb 2008-05-17 drh: #define MX_AUX 5 55342eb9fb 2008-05-17 drh: 55342eb9fb 2008-05-17 drh: /* dbda8d6ce9 2007-07-21 drh: ** All global variables are in this structure. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: struct Global { dbda8d6ce9 2007-07-21 drh: int argc; char **argv; /* Command-line arguments to the program */ dbda8d6ce9 2007-07-21 drh: int isConst; /* True if the output is unchanging */ dbda8d6ce9 2007-07-21 drh: sqlite3 *db; /* The connection to the databases */ dbda8d6ce9 2007-07-21 drh: int configOpen; /* True if the config database is open */ dbda8d6ce9 2007-07-21 drh: long long int now; /* Seconds since 1970 */ dbda8d6ce9 2007-07-21 drh: int repositoryOpen; /* True if the main repository database is open */ dbda8d6ce9 2007-07-21 drh: char *zRepositoryName; /* Name of the repository database */ dbda8d6ce9 2007-07-21 drh: int localOpen; /* True if the local database is open */ dbda8d6ce9 2007-07-21 drh: char *zLocalRoot; /* The directory holding the local database */ dbda8d6ce9 2007-07-21 drh: int minPrefix; /* Number of digits needed for a distinct UUID */ dbda8d6ce9 2007-07-21 drh: int fSqlTrace; /* True if -sqltrace flag is present */ dbda8d6ce9 2007-07-21 drh: int fSqlPrint; /* True if -sqlprint flag is present */ dbda8d6ce9 2007-07-21 drh: int fHttpTrace; /* Trace outbound HTTP requests */ 9ba6e4287b 2008-05-10 drh: int fNoSync; /* Do not do an autosync even. --nosync */ dbda8d6ce9 2007-07-21 drh: char *zPath; /* Name of webpage being served */ dbda8d6ce9 2007-07-21 drh: char *zExtra; /* Extra path information past the webpage name */ dbda8d6ce9 2007-07-21 drh: char *zBaseURL; /* Full text of the URL being served */ 50a58adb76 2007-10-10 drh: char *zTop; /* Parent directory of zPath */ dbda8d6ce9 2007-07-21 drh: const char *zContentType; /* The content type of the input HTTP request */ dbda8d6ce9 2007-07-21 drh: int iErrPriority; /* Priority of current error message */ dbda8d6ce9 2007-07-21 drh: char *zErrMsg; /* Text of an error message */ dbda8d6ce9 2007-07-21 drh: Blob cgiIn; /* Input to an xfer www method */ dbda8d6ce9 2007-07-21 drh: int cgiPanic; /* Write error messages to CGI */ dcc48662f8 2008-06-08 drh: int fullHttpReply; /* True for full HTTP reply. False for CGI reply */ fde1d82372 2008-02-13 drh: Th_Interp *interp; /* The TH1 interpreter */ e2e016c31f 2008-05-17 drh: FILE *httpIn; /* Accept HTTP input from here */ e2e016c31f 2008-05-17 drh: FILE *httpOut; /* Send HTTP output here */ 243e02bfbd 2008-05-18 drh: int xlinkClusterOnly; /* Set when cloning. Only process clusters */ e2e016c31f 2008-05-17 drh: e2e016c31f 2008-05-17 drh: int *aCommitFile; /* Array of files to be committed */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: int urlIsFile; /* True if a "file:" url */ dbda8d6ce9 2007-07-21 drh: char *urlName; /* Hostname for http: or filename for file: */ 1dbf332352 2008-05-05 drh: char *urlHostname; /* The HOST: parameter on http headers */ dbda8d6ce9 2007-07-21 drh: int urlPort; /* TCP port number for http: */ dbda8d6ce9 2007-07-21 drh: char *urlPath; /* Pathname for http: */ e621b6dbe3 2007-07-30 drh: char *urlUser; /* User id for http: */ e621b6dbe3 2007-07-30 drh: char *urlPasswd; /* Password for http: */ dbda8d6ce9 2007-07-21 drh: char *urlCanonical; /* Canonical representation of the URL */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: const char *zLogin; /* Login name. "" if not logged in. */ dbda8d6ce9 2007-07-21 drh: int noPswd; /* Logged in without password (on 127.0.0.1) */ dbda8d6ce9 2007-07-21 drh: int userUid; /* Integer user id */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* Information used to populate the RCVFROM table */ dbda8d6ce9 2007-07-21 drh: int rcvid; /* The rcvid. 0 if not yet defined. */ dbda8d6ce9 2007-07-21 drh: char *zIpAddr; /* The remote IP address */ dbda8d6ce9 2007-07-21 drh: char *zNonce; /* The nonce used for login */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* permissions used by the server */ 22c1ac41d4 2007-08-23 drh: int okSetup; /* s: use Setup screens on web interface */ 22c1ac41d4 2007-08-23 drh: int okAdmin; /* a: administrative permission */ 22c1ac41d4 2007-08-23 drh: int okDelete; /* d: delete wiki or tickets */ 22c1ac41d4 2007-08-23 drh: int okPassword; /* p: change password */ 22c1ac41d4 2007-08-23 drh: int okQuery; /* q: create new reports */ 22c1ac41d4 2007-08-23 drh: int okWrite; /* i: xfer inbound. checkin */ 22c1ac41d4 2007-08-23 drh: int okRead; /* o: xfer outbound. checkout */ 22c1ac41d4 2007-08-23 drh: int okHistory; /* h: access historical information. */ 22c1ac41d4 2007-08-23 drh: int okClone; /* g: clone */ 22c1ac41d4 2007-08-23 drh: int okRdWiki; /* j: view wiki via web */ 22c1ac41d4 2007-08-23 drh: int okNewWiki; /* f: create new wiki via web */ 22c1ac41d4 2007-08-23 drh: int okApndWiki; /* m: append to wiki via web */ 22c1ac41d4 2007-08-23 drh: int okWrWiki; /* k: edit wiki via web */ 22c1ac41d4 2007-08-23 drh: int okRdTkt; /* r: view tickets via web */ 22c1ac41d4 2007-08-23 drh: int okNewTkt; /* n: create new tickets */ 22c1ac41d4 2007-08-23 drh: int okApndTkt; /* c: append to tickets via the web */ 22c1ac41d4 2007-08-23 drh: int okWrTkt; /* w: make changes to tickets via web */ 49380d500a 2008-05-28 drh: int okTktFmt; /* t: create new ticket report formats */ 21326fb6f7 2008-07-19 drh: int okRdAddr; /* e: read email addresses or other private data */ fa6e993017 2008-08-12 cle: int okZip; /* z: download zipped artifact via /zip URL */ dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: FILE *fDebug; /* Write debug information here, if the file exists */ 55342eb9fb 2008-05-17 drh: 55342eb9fb 2008-05-17 drh: /* Storage for the aux() and/or option() SQL function arguments */ 55342eb9fb 2008-05-17 drh: int nAux; /* Number of distinct aux() or option() values */ 55342eb9fb 2008-05-17 drh: const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */ 55342eb9fb 2008-05-17 drh: char *azAuxParam[MX_AUX]; /* Param of each aux() or option() value */ 55342eb9fb 2008-05-17 drh: const char *azAuxVal[MX_AUX]; /* Value of each aux() or option() value */ 55342eb9fb 2008-05-17 drh: const char **azAuxOpt[MX_AUX]; /* Options of each option() value */ 55342eb9fb 2008-05-17 drh: int anAuxCols[MX_AUX]; /* Number of columns for option() values */ dbda8d6ce9 2007-07-21 drh: }; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Macro for debugging: dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #define CGIDEBUG(X) if( g.fDebug ) cgi_debug X dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: #endif dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: Global g; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** The table of web pages supported by this application is generated dbda8d6ce9 2007-07-21 drh: ** automatically by the "mkindex" program and written into a file dbda8d6ce9 2007-07-21 drh: ** named "page_index.h". We include that file here to get access dbda8d6ce9 2007-07-21 drh: ** to the table. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include "page_index.h" dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Search for a function whose name matches zName. Write a pointer to dbda8d6ce9 2007-07-21 drh: ** that function into *pxFunc and return 0. If no match is found, dbda8d6ce9 2007-07-21 drh: ** return 1. If the command is ambiguous return 2; dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** The NameMap structure and the tables we are searching against are dbda8d6ce9 2007-07-21 drh: ** defined in the page_index.h header file which is automatically dbda8d6ce9 2007-07-21 drh: ** generated by mkindex.c program. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static int name_search( dbda8d6ce9 2007-07-21 drh: const char *zName, /* The name we are looking for */ dbda8d6ce9 2007-07-21 drh: const NameMap *aMap, /* Search in this array */ dbda8d6ce9 2007-07-21 drh: int nMap, /* Number of slots in aMap[] */ c9fdb846fb 2007-08-18 drh: int *pIndex /* OUT: The index in aMap[] of the match */ dbda8d6ce9 2007-07-21 drh: ){ dbda8d6ce9 2007-07-21 drh: int upr, lwr, cnt, m, i; dbda8d6ce9 2007-07-21 drh: int n = strlen(zName); dbda8d6ce9 2007-07-21 drh: lwr = 0; dbda8d6ce9 2007-07-21 drh: upr = nMap-1; dbda8d6ce9 2007-07-21 drh: while( lwr<=upr ){ dbda8d6ce9 2007-07-21 drh: int mid, c; dbda8d6ce9 2007-07-21 drh: mid = (upr+lwr)/2; dbda8d6ce9 2007-07-21 drh: c = strcmp(zName, aMap[mid].zName); dbda8d6ce9 2007-07-21 drh: if( c==0 ){ c9fdb846fb 2007-08-18 drh: *pIndex = mid; dbda8d6ce9 2007-07-21 drh: return 0; dbda8d6ce9 2007-07-21 drh: }else if( c<0 ){ dbda8d6ce9 2007-07-21 drh: upr = mid - 1; dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: lwr = mid + 1; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: for(m=cnt=0, i=upr-2; i<=upr+3 && i<nMap; i++){ dbda8d6ce9 2007-07-21 drh: if( i<0 ) continue; dbda8d6ce9 2007-07-21 drh: if( strncmp(zName, aMap[i].zName, n)==0 ){ dbda8d6ce9 2007-07-21 drh: m = i; dbda8d6ce9 2007-07-21 drh: cnt++; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( cnt==1 ){ c9fdb846fb 2007-08-18 drh: *pIndex = m; dbda8d6ce9 2007-07-21 drh: return 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: return 1+(cnt>1); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** This procedure runs first. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: int main(int argc, char **argv){ dbda8d6ce9 2007-07-21 drh: const char *zCmdName; c9fdb846fb 2007-08-18 drh: int idx; dbda8d6ce9 2007-07-21 drh: int rc; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: g.now = time(0); dbda8d6ce9 2007-07-21 drh: g.argc = argc; dbda8d6ce9 2007-07-21 drh: g.argv = argv; dbda8d6ce9 2007-07-21 drh: if( getenv("GATEWAY_INTERFACE")!=0 ){ dbda8d6ce9 2007-07-21 drh: zCmdName = "cgi"; dbda8d6ce9 2007-07-21 drh: }else if( argc<2 ){ dbda8d6ce9 2007-07-21 drh: fprintf(stderr, "Usage: %s COMMAND ...\n", argv[0]); dbda8d6ce9 2007-07-21 drh: exit(1); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: g.fSqlTrace = find_option("sqltrace", 0, 0)!=0; dbda8d6ce9 2007-07-21 drh: g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; dbda8d6ce9 2007-07-21 drh: g.fHttpTrace = find_option("httptrace", 0, 0)!=0; dbda8d6ce9 2007-07-21 drh: g.zLogin = find_option("user", "U", 1); dbda8d6ce9 2007-07-21 drh: zCmdName = argv[1]; dbda8d6ce9 2007-07-21 drh: } c9fdb846fb 2007-08-18 drh: rc = name_search(zCmdName, aCommand, count(aCommand), &idx); dbda8d6ce9 2007-07-21 drh: if( rc==1 ){ dbda8d6ce9 2007-07-21 drh: fprintf(stderr,"%s: unknown command: %s\n" 0cd202a86e 2007-08-23 drh: "%s: use \"help\" for more information\n", dbda8d6ce9 2007-07-21 drh: argv[0], zCmdName, argv[0]); dbda8d6ce9 2007-07-21 drh: return 1; dbda8d6ce9 2007-07-21 drh: }else if( rc==2 ){ dbda8d6ce9 2007-07-21 drh: fprintf(stderr,"%s: ambiguous command prefix: %s\n" 0cd202a86e 2007-08-23 drh: "%s: use \"help\" for more information\n", dbda8d6ce9 2007-07-21 drh: argv[0], zCmdName, argv[0]); dbda8d6ce9 2007-07-21 drh: return 1; dbda8d6ce9 2007-07-21 drh: } c9fdb846fb 2007-08-18 drh: aCommand[idx].xFunc(); dbda8d6ce9 2007-07-21 drh: return 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Print an error message, rollback all databases, and quit. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void fossil_panic(const char *zFormat, ...){ dbda8d6ce9 2007-07-21 drh: char *z; dbda8d6ce9 2007-07-21 drh: va_list ap; dbfe682b92 2008-05-22 drh: static int once = 1; dbda8d6ce9 2007-07-21 drh: va_start(ap, zFormat); dbda8d6ce9 2007-07-21 drh: z = vmprintf(zFormat, ap); dbda8d6ce9 2007-07-21 drh: va_end(ap); dbfe682b92 2008-05-22 drh: if( g.cgiPanic && once ){ dbfe682b92 2008-05-22 drh: once = 0; dbfe682b92 2008-05-22 drh: cgi_printf("<p><font color=\"red\">%h</font></p>", z); dbda8d6ce9 2007-07-21 drh: cgi_reply(); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: fprintf(stderr, "%s: %s\n", g.argv[0], z); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_force_rollback(); dbda8d6ce9 2007-07-21 drh: exit(1); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: void fossil_fatal(const char *zFormat, ...){ dbda8d6ce9 2007-07-21 drh: char *z; dbda8d6ce9 2007-07-21 drh: va_list ap; dbda8d6ce9 2007-07-21 drh: va_start(ap, zFormat); dbda8d6ce9 2007-07-21 drh: z = vmprintf(zFormat, ap); dbda8d6ce9 2007-07-21 drh: va_end(ap); dbda8d6ce9 2007-07-21 drh: if( g.cgiPanic ){ dbda8d6ce9 2007-07-21 drh: g.cgiPanic = 0; 396cc2a4eb 2007-07-30 drh: cgi_printf("<p><font color=\"red\">%h</font></p>", z); dbda8d6ce9 2007-07-21 drh: cgi_reply(); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: fprintf(stderr, "%s: %s\n", g.argv[0], z); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_force_rollback(); dbda8d6ce9 2007-07-21 drh: exit(1); 844718abbf 2008-05-13 drh: } 844718abbf 2008-05-13 drh: void fossil_warning(const char *zFormat, ...){ 844718abbf 2008-05-13 drh: char *z; 844718abbf 2008-05-13 drh: va_list ap; 844718abbf 2008-05-13 drh: va_start(ap, zFormat); 844718abbf 2008-05-13 drh: z = vmprintf(zFormat, ap); 844718abbf 2008-05-13 drh: va_end(ap); 844718abbf 2008-05-13 drh: if( g.cgiPanic ){ 844718abbf 2008-05-13 drh: cgi_printf("<p><font color=\"red\">%h</font></p>", z); 844718abbf 2008-05-13 drh: }else{ 844718abbf 2008-05-13 drh: fprintf(stderr, "%s: %s\n", g.argv[0], z); 844718abbf 2008-05-13 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Print a usage comment and quit dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void usage(const char *zFormat){ dbda8d6ce9 2007-07-21 drh: fprintf(stderr, "Usage: %s %s %s\n", g.argv[0], g.argv[1], zFormat); dbda8d6ce9 2007-07-21 drh: exit(1); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Remove n elements from g.argv beginning with the i-th element. dbda8d6ce9 2007-07-21 drh: */ da4f0c2638 2008-02-01 aku: void remove_from_argv(int i, int n){ dbda8d6ce9 2007-07-21 drh: int j; dbda8d6ce9 2007-07-21 drh: for(j=i+n; j<g.argc; i++, j++){ dbda8d6ce9 2007-07-21 drh: g.argv[i] = g.argv[j]; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: g.argc = i; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Look for a command-line option. If present, return a pointer. dbda8d6ce9 2007-07-21 drh: ** Return NULL if missing. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** hasArg==0 means the option is a flag. It is either present or not. dbda8d6ce9 2007-07-21 drh: ** hasArg==1 means the option has an argument. Return a pointer to the dbda8d6ce9 2007-07-21 drh: ** argument. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: const char *find_option(const char *zLong, const char *zShort, int hasArg){ dbda8d6ce9 2007-07-21 drh: int i; be758137b0 2008-05-25 drh: int nLong; dbda8d6ce9 2007-07-21 drh: const char *zReturn = 0; dbda8d6ce9 2007-07-21 drh: assert( hasArg==0 || hasArg==1 ); be758137b0 2008-05-25 drh: nLong = strlen(zLong); dbda8d6ce9 2007-07-21 drh: for(i=2; i<g.argc; i++){ dbda8d6ce9 2007-07-21 drh: char *z = g.argv[i]; dbda8d6ce9 2007-07-21 drh: if( z[0]!='-' ) continue; dbda8d6ce9 2007-07-21 drh: z++; dbda8d6ce9 2007-07-21 drh: if( z[0]=='-' ){ dbda8d6ce9 2007-07-21 drh: if( z[1]==0 ){ dbda8d6ce9 2007-07-21 drh: remove_from_argv(i, 1); dbda8d6ce9 2007-07-21 drh: break; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: z++; dbda8d6ce9 2007-07-21 drh: } be758137b0 2008-05-25 drh: if( strncmp(z,zLong,nLong)==0 ){ be758137b0 2008-05-25 drh: if( hasArg && z[nLong]=='=' ){ be758137b0 2008-05-25 drh: zReturn = &z[nLong+1]; be758137b0 2008-05-25 drh: remove_from_argv(i, 1); be758137b0 2008-05-25 drh: break; be758137b0 2008-05-25 drh: }else if( z[nLong]==0 ){ be758137b0 2008-05-25 drh: zReturn = g.argv[i+hasArg]; be758137b0 2008-05-25 drh: remove_from_argv(i, 1+hasArg); be758137b0 2008-05-25 drh: break; be758137b0 2008-05-25 drh: } be758137b0 2008-05-25 drh: }else if( zShort!=0 && strcmp(z,zShort)==0 ){ dbda8d6ce9 2007-07-21 drh: zReturn = g.argv[i+hasArg]; dbda8d6ce9 2007-07-21 drh: remove_from_argv(i, 1+hasArg); dbda8d6ce9 2007-07-21 drh: break; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: return zReturn; 6aff11f03f 2007-08-03 drh: } 6aff11f03f 2007-08-03 drh: 6aff11f03f 2007-08-03 drh: /* da4f0c2638 2008-02-01 aku: ** Verify that there are no unprocessed command-line options. If 6aff11f03f 2007-08-03 drh: ** Any remaining command-line argument begins with "-" print 6aff11f03f 2007-08-03 drh: ** an error message and quit. 6aff11f03f 2007-08-03 drh: */ 6aff11f03f 2007-08-03 drh: void verify_all_options(void){ 6aff11f03f 2007-08-03 drh: int i; 6aff11f03f 2007-08-03 drh: for(i=1; i<g.argc; i++){ 6aff11f03f 2007-08-03 drh: if( g.argv[i][0]=='-' ){ 6aff11f03f 2007-08-03 drh: fossil_fatal("unrecognized command-line option: %s", g.argv[i]); 6aff11f03f 2007-08-03 drh: } 6aff11f03f 2007-08-03 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Print a list of words in multiple columns. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void multi_column_list(const char **azWord, int nWord){ dbda8d6ce9 2007-07-21 drh: int i, j, len; dbda8d6ce9 2007-07-21 drh: int mxLen = 0; dbda8d6ce9 2007-07-21 drh: int nCol; dbda8d6ce9 2007-07-21 drh: int nRow; dbda8d6ce9 2007-07-21 drh: for(i=0; i<nWord; i++){ dbda8d6ce9 2007-07-21 drh: len = strlen(azWord[i]); dbda8d6ce9 2007-07-21 drh: if( len>mxLen ) mxLen = len; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: nCol = 80/(mxLen+2); dbda8d6ce9 2007-07-21 drh: if( nCol==0 ) nCol = 1; dbda8d6ce9 2007-07-21 drh: nRow = (nWord + nCol - 1)/nCol; dbda8d6ce9 2007-07-21 drh: for(i=0; i<nRow; i++){ dbda8d6ce9 2007-07-21 drh: const char *zSpacer = ""; dbda8d6ce9 2007-07-21 drh: for(j=i; j<nWord; j+=nRow){ dbda8d6ce9 2007-07-21 drh: printf("%s%-*s", zSpacer, mxLen, azWord[j]); dbda8d6ce9 2007-07-21 drh: zSpacer = " "; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: printf("\n"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* b2e55c0d4d 2007-09-01 drh: ** COM MAND: commands c9fdb846fb 2007-08-18 drh: ** c9fdb846fb 2007-08-18 drh: ** Usage: %fossil commands c9fdb846fb 2007-08-18 drh: ** List all supported commands. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void cmd_cmd_list(void){ dbda8d6ce9 2007-07-21 drh: int i, nCmd; dbda8d6ce9 2007-07-21 drh: const char *aCmd[count(aCommand)]; dbda8d6ce9 2007-07-21 drh: for(i=nCmd=0; i<count(aCommand); i++){ dbda8d6ce9 2007-07-21 drh: if( strncmp(aCommand[i].zName,"test",4)==0 ) continue; c9fdb846fb 2007-08-18 drh: /* if( strcmp(aCommand[i].zName, g.argv[1])==0 ) continue; */ dbda8d6ce9 2007-07-21 drh: aCmd[nCmd++] = aCommand[i].zName; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: multi_column_list(aCmd, nCmd); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: test-commands dbda8d6ce9 2007-07-21 drh: ** c9fdb846fb 2007-08-18 drh: ** Usage: %fossil test-commands 6b85fd173e 2008-05-10 drh: ** c9fdb846fb 2007-08-18 drh: ** List all commands used for testing and debugging. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void cmd_test_cmd_list(void){ dbda8d6ce9 2007-07-21 drh: int i, nCmd; dbda8d6ce9 2007-07-21 drh: const char *aCmd[count(aCommand)]; dbda8d6ce9 2007-07-21 drh: for(i=nCmd=0; i<count(aCommand); i++){ dbda8d6ce9 2007-07-21 drh: if( strncmp(aCommand[i].zName,"test",4)!=0 ) continue; c9fdb846fb 2007-08-18 drh: /* if( strcmp(aCommand[i].zName, g.argv[1])==0 ) continue; */ dbda8d6ce9 2007-07-21 drh: aCmd[nCmd++] = aCommand[i].zName; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: multi_column_list(aCmd, nCmd); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* c9fdb846fb 2007-08-18 drh: ** COMMAND: help c9fdb846fb 2007-08-18 drh: ** c9fdb846fb 2007-08-18 drh: ** Usage: %fossil help COMMAND 6b85fd173e 2008-05-10 drh: ** c9fdb846fb 2007-08-18 drh: ** Display information on how to use COMMAND c9fdb846fb 2007-08-18 drh: */ c9fdb846fb 2007-08-18 drh: void help_cmd(void){ c9fdb846fb 2007-08-18 drh: int rc, idx; c9fdb846fb 2007-08-18 drh: const char *z; c9fdb846fb 2007-08-18 drh: if( g.argc!=3 ){ 6607844a01 2007-08-18 drh: printf("Usage: %s help COMMAND.\nAvailable COMMANDs:\n", g.argv[0]); c9fdb846fb 2007-08-18 drh: cmd_cmd_list(); c2d1e3c70a 2007-09-22 drh: printf("This is fossil version " MANIFEST_VERSION " " MANIFEST_DATE "\n"); c9fdb846fb 2007-08-18 drh: return; c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: rc = name_search(g.argv[2], aCommand, count(aCommand), &idx); c9fdb846fb 2007-08-18 drh: if( rc==1 ){ c9fdb846fb 2007-08-18 drh: fossil_fatal("unknown command: %s", g.argv[2]); c9fdb846fb 2007-08-18 drh: }else if( rc==2 ){ c9fdb846fb 2007-08-18 drh: fossil_fatal("ambiguous command prefix: %s", g.argv[2]); c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: z = aCmdHelp[idx]; c9fdb846fb 2007-08-18 drh: if( z==0 ){ c9fdb846fb 2007-08-18 drh: fossil_fatal("no help available for the %s command", c9fdb846fb 2007-08-18 drh: aCommand[idx].zName); c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: while( *z ){ c9fdb846fb 2007-08-18 drh: if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){ c9fdb846fb 2007-08-18 drh: printf("%s", g.argv[0]); c9fdb846fb 2007-08-18 drh: z += 7; c9fdb846fb 2007-08-18 drh: }else{ c9fdb846fb 2007-08-18 drh: putchar(*z); c9fdb846fb 2007-08-18 drh: z++; c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: putchar('\n'); c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: c9fdb846fb 2007-08-18 drh: /* 50a58adb76 2007-10-10 drh: ** Set the g.zBaseURL value to the full URL for the toplevel of 50a58adb76 2007-10-10 drh: ** the fossil tree. Set g.zHomeURL to g.zBaseURL without the 50a58adb76 2007-10-10 drh: ** leading "http://" and the host and port. dbda8d6ce9 2007-07-21 drh: */ 50a58adb76 2007-10-10 drh: void set_base_url(void){ dbda8d6ce9 2007-07-21 drh: int i; dbda8d6ce9 2007-07-21 drh: const char *zHost = PD("HTTP_HOST",""); dbda8d6ce9 2007-07-21 drh: const char *zMode = PD("HTTPS","off"); c23469468b 2008-05-13 drh: const char *zCur = PD("SCRIPT_NAME","/"); c23469468b 2008-05-13 drh: c23469468b 2008-05-13 drh: i = strlen(zCur); c23469468b 2008-05-13 drh: while( i>0 && zCur[i-1]=='/' ) i--; dbda8d6ce9 2007-07-21 drh: if( strcmp(zMode,"on")==0 ){ 50a58adb76 2007-10-10 drh: g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur); 1ce716b2ec 2007-10-11 drh: g.zTop = &g.zBaseURL[8+strlen(zHost)]; 50a58adb76 2007-10-10 drh: }else{ 50a58adb76 2007-10-10 drh: g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur); 1ce716b2ec 2007-10-11 drh: g.zTop = &g.zBaseURL[7+strlen(zHost)]; 1ce716b2ec 2007-10-11 drh: } 1ce716b2ec 2007-10-11 drh: } 1ce716b2ec 2007-10-11 drh: 1ce716b2ec 2007-10-11 drh: /* 68c24b1857 2008-05-16 drh: ** Send an HTTP redirect back to the designated Index Page. 68c24b1857 2008-05-16 drh: */ 68c24b1857 2008-05-16 drh: void fossil_redirect_home(void){ 68c24b1857 2008-05-16 drh: cgi_redirectf("%s%s", g.zBaseURL, db_get("index-page", "/index")); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Preconditions: dbda8d6ce9 2007-07-21 drh: ** 677aa71bca 2007-10-12 drh: ** * Environment variables are set up according to the CGI standard. dbda8d6ce9 2007-07-21 drh: ** * The respository database has been located and opened. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Process the webpage specified by the PATH_INFO or REQUEST_URI dbda8d6ce9 2007-07-21 drh: ** environment variable. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void process_one_web_page(void){ dbda8d6ce9 2007-07-21 drh: const char *zPathInfo; da4f0c2638 2008-02-01 aku: char *zPath = NULL; c9fdb846fb 2007-08-18 drh: int idx; c7c81df138 2008-05-16 drh: int i; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* Find the page that the user has requested, construct and deliver that dbda8d6ce9 2007-07-21 drh: ** page. dbda8d6ce9 2007-07-21 drh: */ c7c81df138 2008-05-16 drh: set_base_url(); dbda8d6ce9 2007-07-21 drh: zPathInfo = P("PATH_INFO"); c7c81df138 2008-05-16 drh: if( zPathInfo==0 || zPathInfo[0]==0 c7c81df138 2008-05-16 drh: || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){ 68c24b1857 2008-05-16 drh: fossil_redirect_home(); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: zPath = mprintf("%s", zPathInfo); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* Remove the leading "/" at the beginning of the path. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: g.zPath = &zPath[1]; dbda8d6ce9 2007-07-21 drh: for(i=1; zPath[i] && zPath[i]!='/'; i++){} dbda8d6ce9 2007-07-21 drh: if( zPath[i]=='/' ){ dbda8d6ce9 2007-07-21 drh: zPath[i] = 0; dbda8d6ce9 2007-07-21 drh: g.zExtra = &zPath[i+1]; 9f89a8e68e 2007-10-10 drh: }else{ 9f89a8e68e 2007-10-10 drh: g.zExtra = 0; 9f89a8e68e 2007-10-10 drh: } 9f89a8e68e 2007-10-10 drh: if( g.zExtra ){ dbda8d6ce9 2007-07-21 drh: /* CGI parameters get this treatment elsewhere, but places like getfile dbda8d6ce9 2007-07-21 drh: ** will use g.zExtra directly. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: dehttpize(g.zExtra); 677aa71bca 2007-10-12 drh: cgi_set_parameter_nocopy("name", g.zExtra); 9f89a8e68e 2007-10-10 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* Prevent robots from indexing this site. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: if( strcmp(g.zPath, "robots.txt")==0 ){ dbda8d6ce9 2007-07-21 drh: cgi_set_content_type("text/plain"); dbda8d6ce9 2007-07-21 drh: @ User-agent: * dbda8d6ce9 2007-07-21 drh: @ Disallow: / dbda8d6ce9 2007-07-21 drh: cgi_reply(); dbda8d6ce9 2007-07-21 drh: exit(0); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* Locate the method specified by the path and execute the function dbda8d6ce9 2007-07-21 drh: ** that implements that method. dbda8d6ce9 2007-07-21 drh: */ c9fdb846fb 2007-08-18 drh: if( name_search(g.zPath, aWebpage, count(aWebpage), &idx) && c9fdb846fb 2007-08-18 drh: name_search("not_found", aWebpage, count(aWebpage), &idx) ){ dbda8d6ce9 2007-07-21 drh: cgi_set_status(404,"Not Found"); dbda8d6ce9 2007-07-21 drh: @ <h1>Not Found</h1> dbda8d6ce9 2007-07-21 drh: @ <p>Page not found: %h(g.zPath)</p> dbda8d6ce9 2007-07-21 drh: }else{ c9fdb846fb 2007-08-18 drh: aWebpage[idx].xFunc(); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* Return the result. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: cgi_reply(); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: cgi dbda8d6ce9 2007-07-21 drh: ** 6607844a01 2007-08-18 drh: ** Usage: %fossil ?cgi? SCRIPT 6607844a01 2007-08-18 drh: ** 6607844a01 2007-08-18 drh: ** The SCRIPT argument is the name of a file that is the CGI script 6607844a01 2007-08-18 drh: ** that is being run. The command name, "cgi", may be omitted if 6607844a01 2007-08-18 drh: ** the GATEWAY_INTERFACE environment variable is set to "CGI" (which 6607844a01 2007-08-18 drh: ** should always be the case for CGI scripts run by a webserver.) The 6607844a01 2007-08-18 drh: ** SCRIPT file should look something like this: dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** #!/usr/bin/fossil dbda8d6ce9 2007-07-21 drh: ** repository: /home/somebody/project.db dbda8d6ce9 2007-07-21 drh: ** 6607844a01 2007-08-18 drh: ** The second line defines the name of the repository. After locating 6607844a01 2007-08-18 drh: ** the repository, fossil will generate a webpage on stdout based on 6607844a01 2007-08-18 drh: ** the values of standard CGI environment variables. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void cmd_cgi(void){ dbda8d6ce9 2007-07-21 drh: const char *zFile; dbda8d6ce9 2007-07-21 drh: Blob config, line, key, value; dbda8d6ce9 2007-07-21 drh: if( g.argc==3 && strcmp(g.argv[1],"cgi")==0 ){ dbda8d6ce9 2007-07-21 drh: zFile = g.argv[2]; dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: zFile = g.argv[1]; dbda8d6ce9 2007-07-21 drh: } b4f9d90ca3 2008-05-22 drh: g.httpOut = stdout; b4f9d90ca3 2008-05-22 drh: g.httpIn = stdin; 396cc2a4eb 2007-07-30 drh: g.cgiPanic = 1; dbda8d6ce9 2007-07-21 drh: blob_read_from_file(&config, zFile); dbda8d6ce9 2007-07-21 drh: while( blob_line(&config, &line) ){ dbda8d6ce9 2007-07-21 drh: if( !blob_token(&line, &key) ) continue; dbda8d6ce9 2007-07-21 drh: if( blob_buffer(&key)[0]=='#' ) continue; dbda8d6ce9 2007-07-21 drh: if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){ dbda8d6ce9 2007-07-21 drh: g.fDebug = fopen(blob_str(&value), "a"); dbda8d6ce9 2007-07-21 drh: blob_reset(&value); dbda8d6ce9 2007-07-21 drh: continue; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){ dbda8d6ce9 2007-07-21 drh: cgi_setenv("HOME", blob_str(&value)); dbda8d6ce9 2007-07-21 drh: blob_reset(&value); dbda8d6ce9 2007-07-21 drh: continue; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( blob_eq(&key, "repository:") && blob_token(&line, &value) ){ dbda8d6ce9 2007-07-21 drh: db_open_repository(blob_str(&value)); dbda8d6ce9 2007-07-21 drh: blob_reset(&value); dbda8d6ce9 2007-07-21 drh: blob_reset(&config); dbda8d6ce9 2007-07-21 drh: break; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( g.db==0 ){ dbda8d6ce9 2007-07-21 drh: cgi_panic("Unable to find or open the project repository"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: cgi_init(); dbda8d6ce9 2007-07-21 drh: process_one_web_page(); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* e2e016c31f 2008-05-17 drh: ** undocumented format: e2e016c31f 2008-05-17 drh: ** e2e016c31f 2008-05-17 drh: ** fossil http REPOSITORY INFILE OUTFILE IPADDR e2e016c31f 2008-05-17 drh: ** e2e016c31f 2008-05-17 drh: ** The argv==6 form is used by the win32 server only. e2e016c31f 2008-05-17 drh: ** dbda8d6ce9 2007-07-21 drh: ** COMMAND: http dbda8d6ce9 2007-07-21 drh: ** 6607844a01 2007-08-18 drh: ** Usage: %fossil http REPOSITORY dbda8d6ce9 2007-07-21 drh: ** 6607844a01 2007-08-18 drh: ** Handle a single HTTP request appearing on stdin. The resulting webpage 6607844a01 2007-08-18 drh: ** is delivered on stdout. This method is used to launch an HTTP request 6607844a01 2007-08-18 drh: ** handler from inetd, for example. The argument is the name of the 6607844a01 2007-08-18 drh: ** repository. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void cmd_http(void){ dcc48662f8 2008-06-08 drh: const char *zIpAddr; e2e016c31f 2008-05-17 drh: if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){ dbda8d6ce9 2007-07-21 drh: cgi_panic("no repository specified"); dbda8d6ce9 2007-07-21 drh: } f5e8b1d736 2007-08-04 drh: g.cgiPanic = 1; dcc48662f8 2008-06-08 drh: g.fullHttpReply = 1; dcc48662f8 2008-06-08 drh: if( g.argc==6 ){ dcc48662f8 2008-06-08 drh: g.httpIn = fopen(g.argv[3], "rb"); dcc48662f8 2008-06-08 drh: g.httpOut = fopen(g.argv[4], "wb"); dcc48662f8 2008-06-08 drh: zIpAddr = g.argv[5]; dcc48662f8 2008-06-08 drh: }else{ dcc48662f8 2008-06-08 drh: g.httpIn = stdin; dcc48662f8 2008-06-08 drh: g.httpOut = stdout; dcc48662f8 2008-06-08 drh: zIpAddr = 0; dcc48662f8 2008-06-08 drh: } e2e016c31f 2008-05-17 drh: if( g.argc>=3 ){ dbda8d6ce9 2007-07-21 drh: db_open_repository(g.argv[2]); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: } e2e016c31f 2008-05-17 drh: cgi_handle_http_request(zIpAddr); dbda8d6ce9 2007-07-21 drh: process_one_web_page(); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* 1e9c0e287e 2007-10-03 drh: ** COMMAND: test-http 1e9c0e287e 2007-10-03 drh: ** Works like the http command but gives setup permission to all users. 1e9c0e287e 2007-10-03 drh: */ 1e9c0e287e 2007-10-03 drh: void cmd_test_http(void){ 1e9c0e287e 2007-10-03 drh: login_set_capabilities("s"); 1e9c0e287e 2007-10-03 drh: cmd_http(); 1e9c0e287e 2007-10-03 drh: } 1e9c0e287e 2007-10-03 drh: 1e9c0e287e 2007-10-03 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: server dfb68976be 2008-05-17 drh: ** COMMAND: ui 6607844a01 2007-08-18 drh: ** 6607844a01 2007-08-18 drh: ** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY? dfb68976be 2008-05-17 drh: ** Or: %fossil ui ?-P|--port TCPPORT? ?REPOSITORY? dbda8d6ce9 2007-07-21 drh: ** 6607844a01 2007-08-18 drh: ** Open a socket and begin listening and responding to HTTP requests on 6607844a01 2007-08-18 drh: ** TCP port 8080, or on any other TCP port defined by the -P or 6607844a01 2007-08-18 drh: ** --port option. The optional argument is the name of the repository. 6607844a01 2007-08-18 drh: ** The repository argument may be omitted if the working directory is 6607844a01 2007-08-18 drh: ** within an open checkout. dbda8d6ce9 2007-07-21 drh: ** dfb68976be 2008-05-17 drh: ** The "ui" command automatically starts a web browser after initializing dfb68976be 2008-05-17 drh: ** the web server. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void cmd_webserver(void){ dbda8d6ce9 2007-07-21 drh: int iPort; dbda8d6ce9 2007-07-21 drh: const char *zPort; dfb68976be 2008-05-17 drh: char *zBrowser; dfb68976be 2008-05-17 drh: char *zBrowserCmd = 0; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: zPort = find_option("port", "P", 1); dbda8d6ce9 2007-07-21 drh: if( zPort ){ dbda8d6ce9 2007-07-21 drh: iPort = atoi(zPort); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: iPort = 8080; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); f5e8b1d736 2007-08-04 drh: if( g.argc==2 ){ f5e8b1d736 2007-08-04 drh: db_must_be_within_tree(); dcc48662f8 2008-06-08 drh: }else{ dcc48662f8 2008-06-08 drh: db_open_repository(g.argv[2]); e2e016c31f 2008-05-17 drh: } dcc48662f8 2008-06-08 drh: db_close(); e2e016c31f 2008-05-17 drh: #ifndef __MINGW32__ e2e016c31f 2008-05-17 drh: /* Unix implementation */ dfb68976be 2008-05-17 drh: if( g.argv[1][0]=='u' ){ dfb68976be 2008-05-17 drh: #if !defined(__DARWIN__) && !defined(__APPLE__) dfb68976be 2008-05-17 drh: zBrowser = db_get("web-browser", "firefox"); dfb68976be 2008-05-17 drh: #else dfb68976be 2008-05-17 drh: zBrowser = db_get("web-browser", "open"); dfb68976be 2008-05-17 drh: #endif dfb68976be 2008-05-17 drh: zBrowserCmd = mprintf("%s http://localhost:%d/ &", zBrowser, iPort); dfb68976be 2008-05-17 drh: } dfb68976be 2008-05-17 drh: if( cgi_http_server(iPort, zBrowserCmd) ){ e2e016c31f 2008-05-17 drh: fossil_fatal("unable to listen on TCP socket %d", iPort); f5e8b1d736 2007-08-04 drh: } e2e016c31f 2008-05-17 drh: g.httpIn = stdin; e2e016c31f 2008-05-17 drh: g.httpOut = stdout; dbda8d6ce9 2007-07-21 drh: if( g.fHttpTrace ){ dbda8d6ce9 2007-07-21 drh: fprintf(stderr, "====== SERVER pid %d =======\n", getpid()); dbda8d6ce9 2007-07-21 drh: } f5e8b1d736 2007-08-04 drh: g.cgiPanic = 1; dbda8d6ce9 2007-07-21 drh: if( g.argc==2 ){ dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: db_open_repository(g.argv[2]); dbda8d6ce9 2007-07-21 drh: } e2e016c31f 2008-05-17 drh: cgi_handle_http_request(0); dbda8d6ce9 2007-07-21 drh: process_one_web_page(); e2e016c31f 2008-05-17 drh: #else e2e016c31f 2008-05-17 drh: /* Win32 implementation */ dfb68976be 2008-05-17 drh: if( g.argv[1][0]=='u' ){ dfb68976be 2008-05-17 drh: zBrowser = db_get("web-browser", "start"); dfb68976be 2008-05-17 drh: zBrowserCmd = mprintf("%s http://127.0.0.1:%d/", zBrowser, iPort); dfb68976be 2008-05-17 drh: } dfb68976be 2008-05-17 drh: win32_http_server(iPort, zBrowserCmd); e2e016c31f 2008-05-17 drh: #endif dbda8d6ce9 2007-07-21 drh: }