Differences From:
File
src/url.c
part of check-in
[dbda8d6ce9]
- Initial check-in of m1 sources.
by
drh on
2007-07-21 14:10:57.
[view]
To:
File
src/url.c
part of check-in
[3dcaed8d86]
- When accessing a remote repository, if there is a username/password specified as part of the URI, use these to login.
by
dan on
2007-07-28 07:09:25.
[view]
@@ -25,8 +25,80 @@
*/
#include "config.h"
#include "url.h"
+/* Parse a URI authority. The parsed syntax is:
+**
+** [<username> : <password> @] <hostname> [: <port>]
+**
+** TODO: If the input string does not match this pattern, results are
+** undefined (but should not crash or anything nasty like that).
+*/
+void url_parse_authority(char const *zUri, int *pIdx){
+ char *zUser = 0;
+ char *zPass = 0;
+ char *zHost = 0;
+ int iPort = 80;
+
+ int iFirst = *pIdx;
+ int iColon = -1;
+ int ii;
+
+ /* Scan for the magic "@". If the authority contains this character,
+ ** then we need to parse a username and password.
+ */
+ for(ii=iFirst; zUri[ii] && zUri[ii]!='@' && zUri[ii]!= '/'; ii++){
+ if( zUri[ii]==':' ) iColon = ii;
+ }
+
+ /* Parse the username and (optional) password. */
+ if( zUri[ii]=='@' ){
+ if( iColon>=0 ){
+ zUser = mprintf("%.*s", iColon-iFirst, &zUri[iFirst]);
+ zPass = mprintf("%.*s", ii-(iColon+1), &zUri[iColon+1]);
+ }else{
+ zUser = mprintf("%.*s", ii-iFirst, &zUri[iFirst]);
+ }
+ iFirst = ii+1;
+ }
+
+ /* Parse the hostname. */
+ for(ii=iFirst; zUri[ii] && zUri[ii]!=':' && zUri[ii]!= '/'; ii++);
+ zHost = mprintf("%.*s", ii-iFirst, &zUri[iFirst]);
+
+ /* Parse the port number, if one is specified. */
+ if( zUri[ii]==':' ){
+ iPort = atoi(&zUri[ii+1]);
+ for(ii=iFirst; zUri[ii] && zUri[ii]!= '/'; ii++);
+ }
+
+ /* Set the g.urlXXX variables to the parsed values. */
+ dehttpize(zUser);
+ dehttpize(zPass);
+ dehttpize(zHost);
+ g.urlUsername = zUser;
+ g.urlPassword = zPass;
+ g.urlName = zHost;
+ g.urlPort = iPort;
+
+ *pIdx = ii;
+}
+
+/*
+** Based on the values already stored in the other g.urlXXX variables,
+** set the g.urlCanonical variable.
+*/
+void url_set_canon(){
+ g.urlCanonical = mprintf("http://%T%s%T%s%T:%d%T",
+ (g.urlUsername ? g.urlUsername : ""),
+ (g.urlPassword ? ":" : ""),
+ (g.urlPassword ? g.urlPassword : ""),
+ (g.urlUsername ? "@" : ""),
+ g.urlName, g.urlPort, g.urlPath
+ );
+ /* printf("%s\n", g.urlCanonical); */
+}
+
/*
** Parse the given URL. Populate variables in the global "g" structure.
**
** g.urlIsFile True if this is a file URL
@@ -34,31 +106,31 @@
** g.urlPort Port name for HTTP.
** g.urlPath Path name for HTTP.
** g.urlCanonical The URL in canonical form
**
+** If g.uriIsFile is false, indicating an http URI, then the following
+** variables are also populated:
+**
+** g.urlUsername
+** g.urlPassword
+**
+** TODO: At present, the only way to specify a username is to pass it
+** as part of the URI. In the future, if no password is specified,
+** fossil should use the get_passphrase() routine (user.c) to obtain
+** a password from the user.
*/
void url_parse(const char *zUrl){
int i, j, c;
char *zFile;
if( strncmp(zUrl, "http:", 5)==0 ){
g.urlIsFile = 0;
- for(i=7; (c=zUrl[i])!=0 && c!=':' && c!='/'; i++){}
- g.urlName = mprintf("%.*s", i-7, &zUrl[7]);
- for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
- if( c==':' ){
- g.urlPort = 0;
- i++;
- while( (c = zUrl[i])!=0 && isdigit(c) ){
- g.urlPort = g.urlPort*10 + c - '0';
- i++;
- }
- }else{
- g.urlPort = 80;
- }
+
+ i = 7;
+ url_parse_authority(zUrl, &i);
g.urlPath = mprintf(&zUrl[i]);
- dehttpize(g.urlName);
dehttpize(g.urlPath);
- g.urlCanonical = mprintf("http://%T:%d%T", g.urlName, g.urlPort, g.urlPath);
+ url_set_canon();
+
}else if( strncmp(zUrl, "file:", 5)==0 ){
g.urlIsFile = 1;
if( zUrl[5]=='/' && zUrl[6]=='/' ){
i = 7;