dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Copyright (c) 2007 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 file contains code for parsing URLs that appear on the command-line dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "url.h" dbda8d6ce9 2007-07-21 drh: 3dcaed8d86 2007-07-28 dan: /* Parse a URI authority. The parsed syntax is: 3dcaed8d86 2007-07-28 dan: ** 3dcaed8d86 2007-07-28 dan: ** [<username> : <password> @] <hostname> [: <port>] 3dcaed8d86 2007-07-28 dan: ** 3dcaed8d86 2007-07-28 dan: ** TODO: If the input string does not match this pattern, results are 3dcaed8d86 2007-07-28 dan: ** undefined (but should not crash or anything nasty like that). 3dcaed8d86 2007-07-28 dan: */ 3dcaed8d86 2007-07-28 dan: void url_parse_authority(char const *zUri, int *pIdx){ 3dcaed8d86 2007-07-28 dan: char *zUser = 0; 3dcaed8d86 2007-07-28 dan: char *zPass = 0; 3dcaed8d86 2007-07-28 dan: char *zHost = 0; 3dcaed8d86 2007-07-28 dan: int iPort = 80; 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: int iFirst = *pIdx; 3dcaed8d86 2007-07-28 dan: int iColon = -1; 3dcaed8d86 2007-07-28 dan: int ii; 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: /* Scan for the magic "@". If the authority contains this character, 3dcaed8d86 2007-07-28 dan: ** then we need to parse a username and password. 3dcaed8d86 2007-07-28 dan: */ 3dcaed8d86 2007-07-28 dan: for(ii=iFirst; zUri[ii] && zUri[ii]!='@' && zUri[ii]!= '/'; ii++){ 3dcaed8d86 2007-07-28 dan: if( zUri[ii]==':' ) iColon = ii; 3dcaed8d86 2007-07-28 dan: } 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: /* Parse the username and (optional) password. */ 3dcaed8d86 2007-07-28 dan: if( zUri[ii]=='@' ){ 3dcaed8d86 2007-07-28 dan: if( iColon>=0 ){ 3dcaed8d86 2007-07-28 dan: zUser = mprintf("%.*s", iColon-iFirst, &zUri[iFirst]); 3dcaed8d86 2007-07-28 dan: zPass = mprintf("%.*s", ii-(iColon+1), &zUri[iColon+1]); 3dcaed8d86 2007-07-28 dan: }else{ 3dcaed8d86 2007-07-28 dan: zUser = mprintf("%.*s", ii-iFirst, &zUri[iFirst]); 3dcaed8d86 2007-07-28 dan: } 3dcaed8d86 2007-07-28 dan: iFirst = ii+1; 3dcaed8d86 2007-07-28 dan: } 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: /* Parse the hostname. */ 3dcaed8d86 2007-07-28 dan: for(ii=iFirst; zUri[ii] && zUri[ii]!=':' && zUri[ii]!= '/'; ii++); 3dcaed8d86 2007-07-28 dan: zHost = mprintf("%.*s", ii-iFirst, &zUri[iFirst]); 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: /* Parse the port number, if one is specified. */ 3dcaed8d86 2007-07-28 dan: if( zUri[ii]==':' ){ 3dcaed8d86 2007-07-28 dan: iPort = atoi(&zUri[ii+1]); 3dcaed8d86 2007-07-28 dan: for(ii=iFirst; zUri[ii] && zUri[ii]!= '/'; ii++); 3dcaed8d86 2007-07-28 dan: } 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: /* Set the g.urlXXX variables to the parsed values. */ 3dcaed8d86 2007-07-28 dan: dehttpize(zUser); 3dcaed8d86 2007-07-28 dan: dehttpize(zPass); 3dcaed8d86 2007-07-28 dan: dehttpize(zHost); 3dcaed8d86 2007-07-28 dan: g.urlUsername = zUser; 3dcaed8d86 2007-07-28 dan: g.urlPassword = zPass; 3dcaed8d86 2007-07-28 dan: g.urlName = zHost; 3dcaed8d86 2007-07-28 dan: g.urlPort = iPort; 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: *pIdx = ii; 3dcaed8d86 2007-07-28 dan: } 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: /* 3dcaed8d86 2007-07-28 dan: ** Based on the values already stored in the other g.urlXXX variables, 3dcaed8d86 2007-07-28 dan: ** set the g.urlCanonical variable. 3dcaed8d86 2007-07-28 dan: */ 3dcaed8d86 2007-07-28 dan: void url_set_canon(){ 3dcaed8d86 2007-07-28 dan: g.urlCanonical = mprintf("http://%T%s%T%s%T:%d%T", 3dcaed8d86 2007-07-28 dan: (g.urlUsername ? g.urlUsername : ""), 3dcaed8d86 2007-07-28 dan: (g.urlPassword ? ":" : ""), 3dcaed8d86 2007-07-28 dan: (g.urlPassword ? g.urlPassword : ""), 3dcaed8d86 2007-07-28 dan: (g.urlUsername ? "@" : ""), 3dcaed8d86 2007-07-28 dan: g.urlName, g.urlPort, g.urlPath 3dcaed8d86 2007-07-28 dan: ); 3dcaed8d86 2007-07-28 dan: /* printf("%s\n", g.urlCanonical); */ 3dcaed8d86 2007-07-28 dan: } 3dcaed8d86 2007-07-28 dan: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Parse the given URL. Populate variables in the global "g" structure. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** g.urlIsFile True if this is a file URL dbda8d6ce9 2007-07-21 drh: ** g.urlName Hostname for HTTP:. Filename for FILE: dbda8d6ce9 2007-07-21 drh: ** g.urlPort Port name for HTTP. dbda8d6ce9 2007-07-21 drh: ** g.urlPath Path name for HTTP. dbda8d6ce9 2007-07-21 drh: ** g.urlCanonical The URL in canonical form dbda8d6ce9 2007-07-21 drh: ** 3dcaed8d86 2007-07-28 dan: ** If g.uriIsFile is false, indicating an http URI, then the following 3dcaed8d86 2007-07-28 dan: ** variables are also populated: 3dcaed8d86 2007-07-28 dan: ** 3dcaed8d86 2007-07-28 dan: ** g.urlUsername 3dcaed8d86 2007-07-28 dan: ** g.urlPassword 3dcaed8d86 2007-07-28 dan: ** 3dcaed8d86 2007-07-28 dan: ** TODO: At present, the only way to specify a username is to pass it 3dcaed8d86 2007-07-28 dan: ** as part of the URI. In the future, if no password is specified, 3dcaed8d86 2007-07-28 dan: ** fossil should use the get_passphrase() routine (user.c) to obtain 3dcaed8d86 2007-07-28 dan: ** a password from the user. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void url_parse(const char *zUrl){ dbda8d6ce9 2007-07-21 drh: int i, j, c; dbda8d6ce9 2007-07-21 drh: char *zFile; dbda8d6ce9 2007-07-21 drh: if( strncmp(zUrl, "http:", 5)==0 ){ dbda8d6ce9 2007-07-21 drh: g.urlIsFile = 0; 3dcaed8d86 2007-07-28 dan: 3dcaed8d86 2007-07-28 dan: i = 7; 3dcaed8d86 2007-07-28 dan: url_parse_authority(zUrl, &i); dbda8d6ce9 2007-07-21 drh: g.urlPath = mprintf(&zUrl[i]); dbda8d6ce9 2007-07-21 drh: dehttpize(g.urlPath); 3dcaed8d86 2007-07-28 dan: url_set_canon(); 3dcaed8d86 2007-07-28 dan: dbda8d6ce9 2007-07-21 drh: }else if( strncmp(zUrl, "file:", 5)==0 ){ dbda8d6ce9 2007-07-21 drh: g.urlIsFile = 1; dbda8d6ce9 2007-07-21 drh: if( zUrl[5]=='/' && zUrl[6]=='/' ){ dbda8d6ce9 2007-07-21 drh: i = 7; dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: i = 5; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: zFile = mprintf("%s", &zUrl[i]); dbda8d6ce9 2007-07-21 drh: }else if( file_isfile(zUrl) ){ dbda8d6ce9 2007-07-21 drh: g.urlIsFile = 1; dbda8d6ce9 2007-07-21 drh: zFile = mprintf("%s", zUrl); dbda8d6ce9 2007-07-21 drh: }else if( file_isdir(zUrl)==1 ){ dbda8d6ce9 2007-07-21 drh: zFile = mprintf("%s/FOSSIL", zUrl); dbda8d6ce9 2007-07-21 drh: if( file_isfile(zFile) ){ dbda8d6ce9 2007-07-21 drh: g.urlIsFile = 1; dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: free(zFile); dbda8d6ce9 2007-07-21 drh: fossil_panic("unknown repository: %s", zUrl); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: fossil_panic("unknown repository: %s", zUrl); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( g.urlIsFile ){ dbda8d6ce9 2007-07-21 drh: Blob cfile; dbda8d6ce9 2007-07-21 drh: dehttpize(zFile); dbda8d6ce9 2007-07-21 drh: file_canonical_name(zFile, &cfile); dbda8d6ce9 2007-07-21 drh: free(zFile); dbda8d6ce9 2007-07-21 drh: g.urlName = mprintf("%b", &cfile); dbda8d6ce9 2007-07-21 drh: g.urlCanonical = mprintf("file://%T", g.urlName); dbda8d6ce9 2007-07-21 drh: blob_reset(&cfile); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: }