Overview
SHA1 Hash: | 3dcaed8d86cde74f050f862f0fc23cb7ea9cc0f1 |
---|---|
Date: | 2007-07-28 07:09:25 |
User: | dan |
Comment: | When accessing a remote repository, if there is a username/password specified as part of the URI, use these to login. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/db.c from [e56e457646] to [fcfc75c8b2].
@@ -762,10 +762,41 @@ return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName); } void db_lset_int(const char *zName, int value){ db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); } + +int db_row_to_table(const char *zFormat, ...){ + Stmt q; + va_list ap; + int rc; + + va_start(ap, zFormat); + rc = db_vprepare(&q, zFormat, ap); + va_end(ap); + if( rc!=SQLITE_OK ){ + return rc; + } + + @ <table border="0" cellpadding="0" cellspacing="0"> + if( db_step(&q)==SQLITE_ROW ){ + int ii; + for(ii=0; ii<sqlite3_column_count(q.pStmt); ii++){ + char *zCol = htmlize(sqlite3_column_name(q.pStmt, ii), -1); + char *zVal = htmlize(sqlite3_column_text(q.pStmt, ii), -1); + + @ <tr><td align=right>%s(zCol):<td width=10><td>%s(zVal) + + free(zVal); + free(zCol); + } + } + @ </table> + + return db_finalize(&q); +} + /* ** COMMAND: open ** ** Create a new local repository.
Modified src/encode.c from [af8a8318d1] to [6c31150f72].
@@ -182,10 +182,14 @@ ** Remove the HTTP encodings from a string. The conversion is done ** in-place. Return the length of the string after conversion. */ int dehttpize(char *z){ int i, j; + + /* Treat a null pointer as a zero-length string. */ + if( !z ) return 0; + i = j = 0; while( z[i] ){ switch( z[i] ){ case '%': if( z[i+1] && z[i+2] ){
Modified src/http.c from [3b83a20834] to [d56d77ab24].
@@ -152,24 +152,41 @@ ** The server address is contain in the "g" global structure. The ** url_parse() routine should have been called prior to this routine ** in order to fill this structure appropriately. */ void http_exchange(Blob *pSend, Blob *pRecv){ + const char *zLogin; /* Username to send to server */ Blob login, nonce, sig, pw, payload, hdr; const char *zSep; int i; int cnt = 0; - user_select(); blob_zero(&nonce); blob_zero(&pw); db_blob(&nonce, "SELECT hex(randomblob(20))"); blob_copy(&pw, &nonce); - db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid); + + if( g.urlUsername ){ + /* In this case, a username and optionally a password were specified + ** as part of the URI to contact. This overrides the default user + ** and -user option (if any). If no password was specified as part + ** of the URI, use an empty string ("") as the password. + */ + blob_append(&pw, g.urlPassword ? g.urlPassword : "", -1); + zLogin = g.urlUsername; + }else{ + /* Otherwise, use either the default user or the user specified with + ** the -user option. Pull the password from the local repository. + */ + user_select(); + db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid); + zLogin = g.zLogin; + } + sha1sum_blob(&pw, &sig); blob_zero(&login); - blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig); + blob_appendf(&login, "login %s %b %b\n", zLogin, &nonce, &sig); blob_reset(&nonce); blob_reset(&pw); blob_reset(&sig); if( g.fHttpTrace ){ payload = login;
Modified src/info.c from [cb6cea5bd7] to [199807a9fd].
@@ -103,13 +103,13 @@ } show_common_info(rid, "uuid:", 1); } } -#if 0 +#if 1 /* -** WEB PAGE: vinfo +** WEBPAGE: vinfo ** ** Return information about a version. The version number is contained ** in g.zExtra. */ void vinfo_page(void){ @@ -123,14 +123,28 @@ if( rid==0 ){ @ No such object: %h(g.argv[2]) style_footer(); return; } + db_row_to_table("SELECT " + " blob.uuid AS \"UUID\"" + ", datetime(rcvfrom.mtime) AS \"Created\"" + ", rcvfrom.uid AS \"User Id\"" + ", blob.size AS \"Size\"" + "FROM blob, rcvfrom " + "WHERE rid=%d", rid + ); + style_footer(); + return; + db_prepare(&q, - "SELECT uuid, datetime(mtime,'unixepoch'), datetime(ctime,'unixepoch')," - " uid, size, cksum, branch, comment, type" - " FROM record WHERE rid=%d", rid + "SELECT " + "uuid, " /* 0 */ + "datetime(mtime,'unixepoch')," /* 1 */ + "datetime(ctime,'unixepoch')," /* 2 */ + "uid, size, cksum, branch, comment, type" /* 3..8 */ + "FROM record WHERE rid=%d", rid ); if( db_step(&q)==SQLITE_ROW ){ const char *z; const char *zSignedBy = db_text("unknown", "SELECT login FROM repuser WHERE uid=%d", @@ -256,11 +270,13 @@ } db_finalize(&q); } style_footer(); } +#endif +#if 0 /* ** WEB PAGE: diff ** ** Display the difference between two files determined by the v1 and v2 ** query parameters. If only v2 is given compute v1 as the parent of v2.
Modified src/main.c from [e0071db8be] to [93362928df].
@@ -70,10 +70,12 @@ int urlIsFile; /* True if a "file:" url */ char *urlName; /* Hostname for http: or filename for file: */ int urlPort; /* TCP port number for http: */ char *urlPath; /* Pathname for http: */ char *urlCanonical; /* Canonical representation of the URL */ + char *urlUsername; /* Username specified as part of the URI */ + char *urlPassword; /* Password specified as part of the URI */ const char *zLogin; /* Login name. "" if not logged in. */ int isAnon; /* True if logged in anoymously */ int noPswd; /* Logged in without password (on 127.0.0.1) */ int userUid; /* Integer user id */
Modified src/url.c from [f3bcafe705] to [1a6d7505c6].
@@ -24,42 +24,114 @@ ** This file contains code for parsing URLs that appear on the command-line */ #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 ** g.urlName Hostname for HTTP:. Filename for FILE: ** 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; }else{