| | @@ -23,10 +23,82 @@ |
| 23 | 23 | ** |
| 24 | 24 | ** This file contains code for parsing URLs that appear on the command-line |
| 25 | 25 | */ |
| 26 | 26 | #include "config.h" |
| 27 | 27 | #include "url.h" |
| 28 | + |
| 29 | +/* Parse a URI authority. The parsed syntax is: |
| 30 | +** |
| 31 | +** [<username> : <password> @] <hostname> [: <port>] |
| 32 | +** |
| 33 | +** TODO: If the input string does not match this pattern, results are |
| 34 | +** undefined (but should not crash or anything nasty like that). |
| 35 | +*/ |
| 36 | +void url_parse_authority(char const *zUri, int *pIdx){ |
| 37 | + char *zUser = 0; |
| 38 | + char *zPass = 0; |
| 39 | + char *zHost = 0; |
| 40 | + int iPort = 80; |
| 41 | + |
| 42 | + int iFirst = *pIdx; |
| 43 | + int iColon = -1; |
| 44 | + int ii; |
| 45 | + |
| 46 | + /* Scan for the magic "@". If the authority contains this character, |
| 47 | + ** then we need to parse a username and password. |
| 48 | + */ |
| 49 | + for(ii=iFirst; zUri[ii] && zUri[ii]!='@' && zUri[ii]!= '/'; ii++){ |
| 50 | + if( zUri[ii]==':' ) iColon = ii; |
| 51 | + } |
| 52 | + |
| 53 | + /* Parse the username and (optional) password. */ |
| 54 | + if( zUri[ii]=='@' ){ |
| 55 | + if( iColon>=0 ){ |
| 56 | + zUser = mprintf("%.*s", iColon-iFirst, &zUri[iFirst]); |
| 57 | + zPass = mprintf("%.*s", ii-(iColon+1), &zUri[iColon+1]); |
| 58 | + }else{ |
| 59 | + zUser = mprintf("%.*s", ii-iFirst, &zUri[iFirst]); |
| 60 | + } |
| 61 | + iFirst = ii+1; |
| 62 | + } |
| 63 | + |
| 64 | + /* Parse the hostname. */ |
| 65 | + for(ii=iFirst; zUri[ii] && zUri[ii]!=':' && zUri[ii]!= '/'; ii++); |
| 66 | + zHost = mprintf("%.*s", ii-iFirst, &zUri[iFirst]); |
| 67 | + |
| 68 | + /* Parse the port number, if one is specified. */ |
| 69 | + if( zUri[ii]==':' ){ |
| 70 | + iPort = atoi(&zUri[ii+1]); |
| 71 | + for(ii=iFirst; zUri[ii] && zUri[ii]!= '/'; ii++); |
| 72 | + } |
| 73 | + |
| 74 | + /* Set the g.urlXXX variables to the parsed values. */ |
| 75 | + dehttpize(zUser); |
| 76 | + dehttpize(zPass); |
| 77 | + dehttpize(zHost); |
| 78 | + g.urlUsername = zUser; |
| 79 | + g.urlPassword = zPass; |
| 80 | + g.urlName = zHost; |
| 81 | + g.urlPort = iPort; |
| 82 | + |
| 83 | + *pIdx = ii; |
| 84 | +} |
| 85 | + |
| 86 | +/* |
| 87 | +** Based on the values already stored in the other g.urlXXX variables, |
| 88 | +** set the g.urlCanonical variable. |
| 89 | +*/ |
| 90 | +void url_set_canon(){ |
| 91 | + g.urlCanonical = mprintf("http://%T%s%T%s%T:%d%T", |
| 92 | + (g.urlUsername ? g.urlUsername : ""), |
| 93 | + (g.urlPassword ? ":" : ""), |
| 94 | + (g.urlPassword ? g.urlPassword : ""), |
| 95 | + (g.urlUsername ? "@" : ""), |
| 96 | + g.urlName, g.urlPort, g.urlPath |
| 97 | + ); |
| 98 | + /* printf("%s\n", g.urlCanonical); */ |
| 99 | +} |
| 28 | 100 | |
| 29 | 101 | /* |
| 30 | 102 | ** Parse the given URL. Populate variables in the global "g" structure. |
| 31 | 103 | ** |
| 32 | 104 | ** g.urlIsFile True if this is a file URL |
| | @@ -33,33 +105,33 @@ |
| 33 | 105 | ** g.urlName Hostname for HTTP:. Filename for FILE: |
| 34 | 106 | ** g.urlPort Port name for HTTP. |
| 35 | 107 | ** g.urlPath Path name for HTTP. |
| 36 | 108 | ** g.urlCanonical The URL in canonical form |
| 37 | 109 | ** |
| 110 | +** If g.uriIsFile is false, indicating an http URI, then the following |
| 111 | +** variables are also populated: |
| 112 | +** |
| 113 | +** g.urlUsername |
| 114 | +** g.urlPassword |
| 115 | +** |
| 116 | +** TODO: At present, the only way to specify a username is to pass it |
| 117 | +** as part of the URI. In the future, if no password is specified, |
| 118 | +** fossil should use the get_passphrase() routine (user.c) to obtain |
| 119 | +** a password from the user. |
| 38 | 120 | */ |
| 39 | 121 | void url_parse(const char *zUrl){ |
| 40 | 122 | int i, j, c; |
| 41 | 123 | char *zFile; |
| 42 | 124 | if( strncmp(zUrl, "http:", 5)==0 ){ |
| 43 | 125 | g.urlIsFile = 0; |
| 44 | | - for(i=7; (c=zUrl[i])!=0 && c!=':' && c!='/'; i++){} |
| 45 | | - g.urlName = mprintf("%.*s", i-7, &zUrl[7]); |
| 46 | | - for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); } |
| 47 | | - if( c==':' ){ |
| 48 | | - g.urlPort = 0; |
| 49 | | - i++; |
| 50 | | - while( (c = zUrl[i])!=0 && isdigit(c) ){ |
| 51 | | - g.urlPort = g.urlPort*10 + c - '0'; |
| 52 | | - i++; |
| 53 | | - } |
| 54 | | - }else{ |
| 55 | | - g.urlPort = 80; |
| 56 | | - } |
| 126 | + |
| 127 | + i = 7; |
| 128 | + url_parse_authority(zUrl, &i); |
| 57 | 129 | g.urlPath = mprintf(&zUrl[i]); |
| 58 | | - dehttpize(g.urlName); |
| 59 | 130 | dehttpize(g.urlPath); |
| 60 | | - g.urlCanonical = mprintf("http://%T:%d%T", g.urlName, g.urlPort, g.urlPath); |
| 131 | + url_set_canon(); |
| 132 | + |
| 61 | 133 | }else if( strncmp(zUrl, "file:", 5)==0 ){ |
| 62 | 134 | g.urlIsFile = 1; |
| 63 | 135 | if( zUrl[5]=='/' && zUrl[6]=='/' ){ |
| 64 | 136 | i = 7; |
| 65 | 137 | }else{ |
| 66 | 138 | |