Fossil SCM

When accessing a remote repository, if there is a username/password specified as part of the URI, use these to login.

dan 2007-07-28 07:09 trunk
Commit 3dcaed8d86cde74f050f862f0fc23cb7ea9cc0f1
+31
--- src/db.c
+++ src/db.c
@@ -762,10 +762,41 @@
762762
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
763763
}
764764
void db_lset_int(const char *zName, int value){
765765
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
766766
}
767
+
768
+int db_row_to_table(const char *zFormat, ...){
769
+ Stmt q;
770
+ va_list ap;
771
+ int rc;
772
+
773
+ va_start(ap, zFormat);
774
+ rc = db_vprepare(&q, zFormat, ap);
775
+ va_end(ap);
776
+ if( rc!=SQLITE_OK ){
777
+ return rc;
778
+ }
779
+
780
+ @ <table border="0" cellpadding="0" cellspacing="0">
781
+ if( db_step(&q)==SQLITE_ROW ){
782
+ int ii;
783
+ for(ii=0; ii<sqlite3_column_count(q.pStmt); ii++){
784
+ char *zCol = htmlize(sqlite3_column_name(q.pStmt, ii), -1);
785
+ char *zVal = htmlize(sqlite3_column_text(q.pStmt, ii), -1);
786
+
787
+ @ <tr><td align=right>%s(zCol):<td width=10><td>%s(zVal)
788
+
789
+ free(zVal);
790
+ free(zCol);
791
+ }
792
+ }
793
+ @ </table>
794
+
795
+ return db_finalize(&q);
796
+}
797
+
767798
768799
/*
769800
** COMMAND: open
770801
**
771802
** Create a new local repository.
772803
--- src/db.c
+++ src/db.c
@@ -762,10 +762,41 @@
762 return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
763 }
764 void db_lset_int(const char *zName, int value){
765 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
766 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
767
768 /*
769 ** COMMAND: open
770 **
771 ** Create a new local repository.
772
--- src/db.c
+++ src/db.c
@@ -762,10 +762,41 @@
762 return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
763 }
764 void db_lset_int(const char *zName, int value){
765 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
766 }
767
768 int db_row_to_table(const char *zFormat, ...){
769 Stmt q;
770 va_list ap;
771 int rc;
772
773 va_start(ap, zFormat);
774 rc = db_vprepare(&q, zFormat, ap);
775 va_end(ap);
776 if( rc!=SQLITE_OK ){
777 return rc;
778 }
779
780 @ <table border="0" cellpadding="0" cellspacing="0">
781 if( db_step(&q)==SQLITE_ROW ){
782 int ii;
783 for(ii=0; ii<sqlite3_column_count(q.pStmt); ii++){
784 char *zCol = htmlize(sqlite3_column_name(q.pStmt, ii), -1);
785 char *zVal = htmlize(sqlite3_column_text(q.pStmt, ii), -1);
786
787 @ <tr><td align=right>%s(zCol):<td width=10><td>%s(zVal)
788
789 free(zVal);
790 free(zCol);
791 }
792 }
793 @ </table>
794
795 return db_finalize(&q);
796 }
797
798
799 /*
800 ** COMMAND: open
801 **
802 ** Create a new local repository.
803
--- src/encode.c
+++ src/encode.c
@@ -182,10 +182,14 @@
182182
** Remove the HTTP encodings from a string. The conversion is done
183183
** in-place. Return the length of the string after conversion.
184184
*/
185185
int dehttpize(char *z){
186186
int i, j;
187
+
188
+ /* Treat a null pointer as a zero-length string. */
189
+ if( !z ) return 0;
190
+
187191
i = j = 0;
188192
while( z[i] ){
189193
switch( z[i] ){
190194
case '%':
191195
if( z[i+1] && z[i+2] ){
192196
--- src/encode.c
+++ src/encode.c
@@ -182,10 +182,14 @@
182 ** Remove the HTTP encodings from a string. The conversion is done
183 ** in-place. Return the length of the string after conversion.
184 */
185 int dehttpize(char *z){
186 int i, j;
 
 
 
 
187 i = j = 0;
188 while( z[i] ){
189 switch( z[i] ){
190 case '%':
191 if( z[i+1] && z[i+2] ){
192
--- src/encode.c
+++ src/encode.c
@@ -182,10 +182,14 @@
182 ** Remove the HTTP encodings from a string. The conversion is done
183 ** in-place. Return the length of the string after conversion.
184 */
185 int dehttpize(char *z){
186 int i, j;
187
188 /* Treat a null pointer as a zero-length string. */
189 if( !z ) return 0;
190
191 i = j = 0;
192 while( z[i] ){
193 switch( z[i] ){
194 case '%':
195 if( z[i+1] && z[i+2] ){
196
+20 -3
--- src/http.c
+++ src/http.c
@@ -152,24 +152,41 @@
152152
** The server address is contain in the "g" global structure. The
153153
** url_parse() routine should have been called prior to this routine
154154
** in order to fill this structure appropriately.
155155
*/
156156
void http_exchange(Blob *pSend, Blob *pRecv){
157
+ const char *zLogin; /* Username to send to server */
157158
Blob login, nonce, sig, pw, payload, hdr;
158159
const char *zSep;
159160
int i;
160161
int cnt = 0;
161162
162
- user_select();
163163
blob_zero(&nonce);
164164
blob_zero(&pw);
165165
db_blob(&nonce, "SELECT hex(randomblob(20))");
166166
blob_copy(&pw, &nonce);
167
- db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
167
+
168
+ if( g.urlUsername ){
169
+ /* In this case, a username and optionally a password were specified
170
+ ** as part of the URI to contact. This overrides the default user
171
+ ** and -user option (if any). If no password was specified as part
172
+ ** of the URI, use an empty string ("") as the password.
173
+ */
174
+ blob_append(&pw, g.urlPassword ? g.urlPassword : "", -1);
175
+ zLogin = g.urlUsername;
176
+ }else{
177
+ /* Otherwise, use either the default user or the user specified with
178
+ ** the -user option. Pull the password from the local repository.
179
+ */
180
+ user_select();
181
+ db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
182
+ zLogin = g.zLogin;
183
+ }
184
+
168185
sha1sum_blob(&pw, &sig);
169186
blob_zero(&login);
170
- blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
187
+ blob_appendf(&login, "login %s %b %b\n", zLogin, &nonce, &sig);
171188
blob_reset(&nonce);
172189
blob_reset(&pw);
173190
blob_reset(&sig);
174191
if( g.fHttpTrace ){
175192
payload = login;
176193
--- src/http.c
+++ src/http.c
@@ -152,24 +152,41 @@
152 ** The server address is contain in the "g" global structure. The
153 ** url_parse() routine should have been called prior to this routine
154 ** in order to fill this structure appropriately.
155 */
156 void http_exchange(Blob *pSend, Blob *pRecv){
 
157 Blob login, nonce, sig, pw, payload, hdr;
158 const char *zSep;
159 int i;
160 int cnt = 0;
161
162 user_select();
163 blob_zero(&nonce);
164 blob_zero(&pw);
165 db_blob(&nonce, "SELECT hex(randomblob(20))");
166 blob_copy(&pw, &nonce);
167 db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168 sha1sum_blob(&pw, &sig);
169 blob_zero(&login);
170 blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
171 blob_reset(&nonce);
172 blob_reset(&pw);
173 blob_reset(&sig);
174 if( g.fHttpTrace ){
175 payload = login;
176
--- src/http.c
+++ src/http.c
@@ -152,24 +152,41 @@
152 ** The server address is contain in the "g" global structure. The
153 ** url_parse() routine should have been called prior to this routine
154 ** in order to fill this structure appropriately.
155 */
156 void http_exchange(Blob *pSend, Blob *pRecv){
157 const char *zLogin; /* Username to send to server */
158 Blob login, nonce, sig, pw, payload, hdr;
159 const char *zSep;
160 int i;
161 int cnt = 0;
162
 
163 blob_zero(&nonce);
164 blob_zero(&pw);
165 db_blob(&nonce, "SELECT hex(randomblob(20))");
166 blob_copy(&pw, &nonce);
167
168 if( g.urlUsername ){
169 /* In this case, a username and optionally a password were specified
170 ** as part of the URI to contact. This overrides the default user
171 ** and -user option (if any). If no password was specified as part
172 ** of the URI, use an empty string ("") as the password.
173 */
174 blob_append(&pw, g.urlPassword ? g.urlPassword : "", -1);
175 zLogin = g.urlUsername;
176 }else{
177 /* Otherwise, use either the default user or the user specified with
178 ** the -user option. Pull the password from the local repository.
179 */
180 user_select();
181 db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
182 zLogin = g.zLogin;
183 }
184
185 sha1sum_blob(&pw, &sig);
186 blob_zero(&login);
187 blob_appendf(&login, "login %s %b %b\n", zLogin, &nonce, &sig);
188 blob_reset(&nonce);
189 blob_reset(&pw);
190 blob_reset(&sig);
191 if( g.fHttpTrace ){
192 payload = login;
193
+21 -5
--- src/info.c
+++ src/info.c
@@ -103,13 +103,13 @@
103103
}
104104
show_common_info(rid, "uuid:", 1);
105105
}
106106
}
107107
108
-#if 0
108
+#if 1
109109
/*
110
-** WEB PAGE: vinfo
110
+** WEBPAGE: vinfo
111111
**
112112
** Return information about a version. The version number is contained
113113
** in g.zExtra.
114114
*/
115115
void vinfo_page(void){
@@ -123,14 +123,28 @@
123123
if( rid==0 ){
124124
@ No such object: %h(g.argv[2])
125125
style_footer();
126126
return;
127127
}
128
+ db_row_to_table("SELECT "
129
+ " blob.uuid AS \"UUID\""
130
+ ", datetime(rcvfrom.mtime) AS \"Created\""
131
+ ", rcvfrom.uid AS \"User Id\""
132
+ ", blob.size AS \"Size\""
133
+ "FROM blob, rcvfrom "
134
+ "WHERE rid=%d", rid
135
+ );
136
+ style_footer();
137
+ return;
138
+
128139
db_prepare(&q,
129
- "SELECT uuid, datetime(mtime,'unixepoch'), datetime(ctime,'unixepoch'),"
130
- " uid, size, cksum, branch, comment, type"
131
- " FROM record WHERE rid=%d", rid
140
+ "SELECT "
141
+ "uuid, " /* 0 */
142
+ "datetime(mtime,'unixepoch')," /* 1 */
143
+ "datetime(ctime,'unixepoch')," /* 2 */
144
+ "uid, size, cksum, branch, comment, type" /* 3..8 */
145
+ "FROM record WHERE rid=%d", rid
132146
);
133147
if( db_step(&q)==SQLITE_ROW ){
134148
const char *z;
135149
const char *zSignedBy = db_text("unknown",
136150
"SELECT login FROM repuser WHERE uid=%d",
@@ -256,11 +270,13 @@
256270
}
257271
db_finalize(&q);
258272
}
259273
style_footer();
260274
}
275
+#endif
261276
277
+#if 0
262278
/*
263279
** WEB PAGE: diff
264280
**
265281
** Display the difference between two files determined by the v1 and v2
266282
** query parameters. If only v2 is given compute v1 as the parent of v2.
267283
--- src/info.c
+++ src/info.c
@@ -103,13 +103,13 @@
103 }
104 show_common_info(rid, "uuid:", 1);
105 }
106 }
107
108 #if 0
109 /*
110 ** WEB PAGE: vinfo
111 **
112 ** Return information about a version. The version number is contained
113 ** in g.zExtra.
114 */
115 void vinfo_page(void){
@@ -123,14 +123,28 @@
123 if( rid==0 ){
124 @ No such object: %h(g.argv[2])
125 style_footer();
126 return;
127 }
 
 
 
 
 
 
 
 
 
 
 
128 db_prepare(&q,
129 "SELECT uuid, datetime(mtime,'unixepoch'), datetime(ctime,'unixepoch'),"
130 " uid, size, cksum, branch, comment, type"
131 " FROM record WHERE rid=%d", rid
 
 
 
132 );
133 if( db_step(&q)==SQLITE_ROW ){
134 const char *z;
135 const char *zSignedBy = db_text("unknown",
136 "SELECT login FROM repuser WHERE uid=%d",
@@ -256,11 +270,13 @@
256 }
257 db_finalize(&q);
258 }
259 style_footer();
260 }
 
261
 
262 /*
263 ** WEB PAGE: diff
264 **
265 ** Display the difference between two files determined by the v1 and v2
266 ** query parameters. If only v2 is given compute v1 as the parent of v2.
267
--- src/info.c
+++ src/info.c
@@ -103,13 +103,13 @@
103 }
104 show_common_info(rid, "uuid:", 1);
105 }
106 }
107
108 #if 1
109 /*
110 ** WEBPAGE: vinfo
111 **
112 ** Return information about a version. The version number is contained
113 ** in g.zExtra.
114 */
115 void vinfo_page(void){
@@ -123,14 +123,28 @@
123 if( rid==0 ){
124 @ No such object: %h(g.argv[2])
125 style_footer();
126 return;
127 }
128 db_row_to_table("SELECT "
129 " blob.uuid AS \"UUID\""
130 ", datetime(rcvfrom.mtime) AS \"Created\""
131 ", rcvfrom.uid AS \"User Id\""
132 ", blob.size AS \"Size\""
133 "FROM blob, rcvfrom "
134 "WHERE rid=%d", rid
135 );
136 style_footer();
137 return;
138
139 db_prepare(&q,
140 "SELECT "
141 "uuid, " /* 0 */
142 "datetime(mtime,'unixepoch')," /* 1 */
143 "datetime(ctime,'unixepoch')," /* 2 */
144 "uid, size, cksum, branch, comment, type" /* 3..8 */
145 "FROM record WHERE rid=%d", rid
146 );
147 if( db_step(&q)==SQLITE_ROW ){
148 const char *z;
149 const char *zSignedBy = db_text("unknown",
150 "SELECT login FROM repuser WHERE uid=%d",
@@ -256,11 +270,13 @@
270 }
271 db_finalize(&q);
272 }
273 style_footer();
274 }
275 #endif
276
277 #if 0
278 /*
279 ** WEB PAGE: diff
280 **
281 ** Display the difference between two files determined by the v1 and v2
282 ** query parameters. If only v2 is given compute v1 as the parent of v2.
283
+2
--- src/main.c
+++ src/main.c
@@ -70,10 +70,12 @@
7070
int urlIsFile; /* True if a "file:" url */
7171
char *urlName; /* Hostname for http: or filename for file: */
7272
int urlPort; /* TCP port number for http: */
7373
char *urlPath; /* Pathname for http: */
7474
char *urlCanonical; /* Canonical representation of the URL */
75
+ char *urlUsername; /* Username specified as part of the URI */
76
+ char *urlPassword; /* Password specified as part of the URI */
7577
7678
const char *zLogin; /* Login name. "" if not logged in. */
7779
int isAnon; /* True if logged in anoymously */
7880
int noPswd; /* Logged in without password (on 127.0.0.1) */
7981
int userUid; /* Integer user id */
8082
--- src/main.c
+++ src/main.c
@@ -70,10 +70,12 @@
70 int urlIsFile; /* True if a "file:" url */
71 char *urlName; /* Hostname for http: or filename for file: */
72 int urlPort; /* TCP port number for http: */
73 char *urlPath; /* Pathname for http: */
74 char *urlCanonical; /* Canonical representation of the URL */
 
 
75
76 const char *zLogin; /* Login name. "" if not logged in. */
77 int isAnon; /* True if logged in anoymously */
78 int noPswd; /* Logged in without password (on 127.0.0.1) */
79 int userUid; /* Integer user id */
80
--- src/main.c
+++ src/main.c
@@ -70,10 +70,12 @@
70 int urlIsFile; /* True if a "file:" url */
71 char *urlName; /* Hostname for http: or filename for file: */
72 int urlPort; /* TCP port number for http: */
73 char *urlPath; /* Pathname for http: */
74 char *urlCanonical; /* Canonical representation of the URL */
75 char *urlUsername; /* Username specified as part of the URI */
76 char *urlPassword; /* Password specified as part of the URI */
77
78 const char *zLogin; /* Login name. "" if not logged in. */
79 int isAnon; /* True if logged in anoymously */
80 int noPswd; /* Logged in without password (on 127.0.0.1) */
81 int userUid; /* Integer user id */
82
+87 -15
--- src/url.c
+++ src/url.c
@@ -23,10 +23,82 @@
2323
**
2424
** This file contains code for parsing URLs that appear on the command-line
2525
*/
2626
#include "config.h"
2727
#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
+}
28100
29101
/*
30102
** Parse the given URL. Populate variables in the global "g" structure.
31103
**
32104
** g.urlIsFile True if this is a file URL
@@ -33,33 +105,33 @@
33105
** g.urlName Hostname for HTTP:. Filename for FILE:
34106
** g.urlPort Port name for HTTP.
35107
** g.urlPath Path name for HTTP.
36108
** g.urlCanonical The URL in canonical form
37109
**
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.
38120
*/
39121
void url_parse(const char *zUrl){
40122
int i, j, c;
41123
char *zFile;
42124
if( strncmp(zUrl, "http:", 5)==0 ){
43125
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);
57129
g.urlPath = mprintf(&zUrl[i]);
58
- dehttpize(g.urlName);
59130
dehttpize(g.urlPath);
60
- g.urlCanonical = mprintf("http://%T:%d%T", g.urlName, g.urlPort, g.urlPath);
131
+ url_set_canon();
132
+
61133
}else if( strncmp(zUrl, "file:", 5)==0 ){
62134
g.urlIsFile = 1;
63135
if( zUrl[5]=='/' && zUrl[6]=='/' ){
64136
i = 7;
65137
}else{
66138
--- src/url.c
+++ src/url.c
@@ -23,10 +23,82 @@
23 **
24 ** This file contains code for parsing URLs that appear on the command-line
25 */
26 #include "config.h"
27 #include "url.h"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
29 /*
30 ** Parse the given URL. Populate variables in the global "g" structure.
31 **
32 ** g.urlIsFile True if this is a file URL
@@ -33,33 +105,33 @@
33 ** g.urlName Hostname for HTTP:. Filename for FILE:
34 ** g.urlPort Port name for HTTP.
35 ** g.urlPath Path name for HTTP.
36 ** g.urlCanonical The URL in canonical form
37 **
 
 
 
 
 
 
 
 
 
 
38 */
39 void url_parse(const char *zUrl){
40 int i, j, c;
41 char *zFile;
42 if( strncmp(zUrl, "http:", 5)==0 ){
43 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 }
57 g.urlPath = mprintf(&zUrl[i]);
58 dehttpize(g.urlName);
59 dehttpize(g.urlPath);
60 g.urlCanonical = mprintf("http://%T:%d%T", g.urlName, g.urlPort, g.urlPath);
 
61 }else if( strncmp(zUrl, "file:", 5)==0 ){
62 g.urlIsFile = 1;
63 if( zUrl[5]=='/' && zUrl[6]=='/' ){
64 i = 7;
65 }else{
66
--- src/url.c
+++ src/url.c
@@ -23,10 +23,82 @@
23 **
24 ** This file contains code for parsing URLs that appear on the command-line
25 */
26 #include "config.h"
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 }
100
101 /*
102 ** Parse the given URL. Populate variables in the global "g" structure.
103 **
104 ** g.urlIsFile True if this is a file URL
@@ -33,33 +105,33 @@
105 ** g.urlName Hostname for HTTP:. Filename for FILE:
106 ** g.urlPort Port name for HTTP.
107 ** g.urlPath Path name for HTTP.
108 ** g.urlCanonical The URL in canonical form
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.
120 */
121 void url_parse(const char *zUrl){
122 int i, j, c;
123 char *zFile;
124 if( strncmp(zUrl, "http:", 5)==0 ){
125 g.urlIsFile = 0;
126
127 i = 7;
128 url_parse_authority(zUrl, &i);
 
 
 
 
 
 
 
 
 
 
129 g.urlPath = mprintf(&zUrl[i]);
 
130 dehttpize(g.urlPath);
131 url_set_canon();
132
133 }else if( strncmp(zUrl, "file:", 5)==0 ){
134 g.urlIsFile = 1;
135 if( zUrl[5]=='/' && zUrl[6]=='/' ){
136 i = 7;
137 }else{
138

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button