Fossil SCM

Improved handling for remote repository passwords: When prompting for the password, also ask the user whether or not to remember the password, as browsers typically do for their password cache.

drh 2013-02-21 03:51 trunk
Commit 6d6740dcca7d1b4cb6897e57f7a3a6fd7392caa9
+3 -12
--- src/clone.c
+++ src/clone.c
@@ -115,23 +115,17 @@
115115
fossil_panic("file already exists: %s", g.argv[3]);
116116
}
117117
118118
zDefaultUser = find_option("admin-user","A",1);
119119
120
- url_parse(g.argv[2]);
120
+ url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
121121
if( g.urlIsFile ){
122122
file_copy(g.urlName, g.argv[3]);
123123
db_close(1);
124124
db_open_repository(g.argv[3]);
125125
db_record_repository_filename(g.argv[3]);
126
- db_multi_exec(
127
- "REPLACE INTO config(name,value,mtime)"
128
- " VALUES('server-code', lower(hex(randomblob(20))),now());"
129
- "REPLACE INTO config(name,value,mtime)"
130
- " VALUES('last-sync-url', '%q',now());",
131
- g.urlCanonical
132
- );
126
+ url_remember();
133127
if( !bPrivate ) delete_private_content();
134128
shun_artifacts();
135129
db_create_default_users(1, zDefaultUser);
136130
if( zDefaultUser ){
137131
g.zLogin = zDefaultUser;
@@ -146,11 +140,11 @@
146140
db_record_repository_filename(g.argv[3]);
147141
db_initial_setup(0, 0, zDefaultUser, 0);
148142
user_select();
149143
db_set("content-schema", CONTENT_SCHEMA, 0);
150144
db_set("aux-schema", AUX_SCHEMA, 0);
151
- db_set("last-sync-url", g.argv[2], 0);
145
+ url_remember();
152146
if( g.zSSLIdentity!=0 ){
153147
/* If the --ssl-identity option was specified, store it as a setting */
154148
Blob fn;
155149
blob_zero(&fn);
156150
file_canonical_name(g.zSSLIdentity, &fn, 0);
@@ -177,12 +171,9 @@
177171
}
178172
db_begin_transaction();
179173
fossil_print("Rebuilding repository meta-data...\n");
180174
rebuild_db(0, 1, 0);
181175
fossil_print("project-id: %s\n", db_get("project-code", 0));
182
- fossil_print("server-id: %s\n", db_get("server-code", 0));
183176
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
184177
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
185
- zPw = g.urlPasswd;
186
- if( !g.dontKeepUrl && zPw) db_set("last-sync-pw", obscure(zPw), 0);
187178
db_end_transaction(0);
188179
}
189180
--- src/clone.c
+++ src/clone.c
@@ -115,23 +115,17 @@
115 fossil_panic("file already exists: %s", g.argv[3]);
116 }
117
118 zDefaultUser = find_option("admin-user","A",1);
119
120 url_parse(g.argv[2]);
121 if( g.urlIsFile ){
122 file_copy(g.urlName, g.argv[3]);
123 db_close(1);
124 db_open_repository(g.argv[3]);
125 db_record_repository_filename(g.argv[3]);
126 db_multi_exec(
127 "REPLACE INTO config(name,value,mtime)"
128 " VALUES('server-code', lower(hex(randomblob(20))),now());"
129 "REPLACE INTO config(name,value,mtime)"
130 " VALUES('last-sync-url', '%q',now());",
131 g.urlCanonical
132 );
133 if( !bPrivate ) delete_private_content();
134 shun_artifacts();
135 db_create_default_users(1, zDefaultUser);
136 if( zDefaultUser ){
137 g.zLogin = zDefaultUser;
@@ -146,11 +140,11 @@
146 db_record_repository_filename(g.argv[3]);
147 db_initial_setup(0, 0, zDefaultUser, 0);
148 user_select();
149 db_set("content-schema", CONTENT_SCHEMA, 0);
150 db_set("aux-schema", AUX_SCHEMA, 0);
151 db_set("last-sync-url", g.argv[2], 0);
152 if( g.zSSLIdentity!=0 ){
153 /* If the --ssl-identity option was specified, store it as a setting */
154 Blob fn;
155 blob_zero(&fn);
156 file_canonical_name(g.zSSLIdentity, &fn, 0);
@@ -177,12 +171,9 @@
177 }
178 db_begin_transaction();
179 fossil_print("Rebuilding repository meta-data...\n");
180 rebuild_db(0, 1, 0);
181 fossil_print("project-id: %s\n", db_get("project-code", 0));
182 fossil_print("server-id: %s\n", db_get("server-code", 0));
183 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
184 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
185 zPw = g.urlPasswd;
186 if( !g.dontKeepUrl && zPw) db_set("last-sync-pw", obscure(zPw), 0);
187 db_end_transaction(0);
188 }
189
--- src/clone.c
+++ src/clone.c
@@ -115,23 +115,17 @@
115 fossil_panic("file already exists: %s", g.argv[3]);
116 }
117
118 zDefaultUser = find_option("admin-user","A",1);
119
120 url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
121 if( g.urlIsFile ){
122 file_copy(g.urlName, g.argv[3]);
123 db_close(1);
124 db_open_repository(g.argv[3]);
125 db_record_repository_filename(g.argv[3]);
126 url_remember();
 
 
 
 
 
 
127 if( !bPrivate ) delete_private_content();
128 shun_artifacts();
129 db_create_default_users(1, zDefaultUser);
130 if( zDefaultUser ){
131 g.zLogin = zDefaultUser;
@@ -146,11 +140,11 @@
140 db_record_repository_filename(g.argv[3]);
141 db_initial_setup(0, 0, zDefaultUser, 0);
142 user_select();
143 db_set("content-schema", CONTENT_SCHEMA, 0);
144 db_set("aux-schema", AUX_SCHEMA, 0);
145 url_remember();
146 if( g.zSSLIdentity!=0 ){
147 /* If the --ssl-identity option was specified, store it as a setting */
148 Blob fn;
149 blob_zero(&fn);
150 file_canonical_name(g.zSSLIdentity, &fn, 0);
@@ -177,12 +171,9 @@
171 }
172 db_begin_transaction();
173 fossil_print("Rebuilding repository meta-data...\n");
174 rebuild_db(0, 1, 0);
175 fossil_print("project-id: %s\n", db_get("project-code", 0));
 
176 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
177 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
 
 
178 db_end_transaction(0);
179 }
180
+5 -12
--- src/configure.c
+++ src/configure.c
@@ -878,14 +878,15 @@
878878
if( strncmp(zMethod, "pull", n)==0
879879
|| strncmp(zMethod, "push", n)==0
880880
|| strncmp(zMethod, "sync", n)==0
881881
){
882882
int mask;
883
- const char *zServer;
883
+ const char *zServer = 0;
884884
const char *zPw;
885885
int legacyFlag = 0;
886886
int overwriteFlag = 0;
887
+
887888
if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
888889
if( strncmp(zMethod,"pull",n)==0 ){
889890
overwriteFlag = find_option("overwrite",0,0)!=0;
890891
}
891892
url_proxy_options();
@@ -893,21 +894,13 @@
893894
usage("pull AREA ?URL?");
894895
}
895896
mask = configure_name_to_mask(g.argv[3], 1);
896897
if( g.argc==5 ){
897898
zServer = g.argv[4];
898
- zPw = 0;
899
- g.dontKeepUrl = 1;
900
- }else{
901
- zServer = db_get("last-sync-url", 0);
902
- if( zServer==0 ){
903
- fossil_fatal("no server specified");
904
- }
905
- zPw = unobscure(db_get("last-sync-pw", 0));
906
- }
907
- url_parse(zServer);
908
- if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
899
+ }
900
+ url_parse(zServer, URL_PROMPT_PW);
901
+ if( g.urlProtocol==0 ) fossil_fatal("no server URL specified");
909902
user_select();
910903
url_enable_proxy("via proxy: ");
911904
if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
912905
if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
913906
if( strncmp(zMethod, "push", n)==0 ){
914907
--- src/configure.c
+++ src/configure.c
@@ -878,14 +878,15 @@
878 if( strncmp(zMethod, "pull", n)==0
879 || strncmp(zMethod, "push", n)==0
880 || strncmp(zMethod, "sync", n)==0
881 ){
882 int mask;
883 const char *zServer;
884 const char *zPw;
885 int legacyFlag = 0;
886 int overwriteFlag = 0;
 
887 if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
888 if( strncmp(zMethod,"pull",n)==0 ){
889 overwriteFlag = find_option("overwrite",0,0)!=0;
890 }
891 url_proxy_options();
@@ -893,21 +894,13 @@
893 usage("pull AREA ?URL?");
894 }
895 mask = configure_name_to_mask(g.argv[3], 1);
896 if( g.argc==5 ){
897 zServer = g.argv[4];
898 zPw = 0;
899 g.dontKeepUrl = 1;
900 }else{
901 zServer = db_get("last-sync-url", 0);
902 if( zServer==0 ){
903 fossil_fatal("no server specified");
904 }
905 zPw = unobscure(db_get("last-sync-pw", 0));
906 }
907 url_parse(zServer);
908 if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
909 user_select();
910 url_enable_proxy("via proxy: ");
911 if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
912 if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
913 if( strncmp(zMethod, "push", n)==0 ){
914
--- src/configure.c
+++ src/configure.c
@@ -878,14 +878,15 @@
878 if( strncmp(zMethod, "pull", n)==0
879 || strncmp(zMethod, "push", n)==0
880 || strncmp(zMethod, "sync", n)==0
881 ){
882 int mask;
883 const char *zServer = 0;
884 const char *zPw;
885 int legacyFlag = 0;
886 int overwriteFlag = 0;
887
888 if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
889 if( strncmp(zMethod,"pull",n)==0 ){
890 overwriteFlag = find_option("overwrite",0,0)!=0;
891 }
892 url_proxy_options();
@@ -893,21 +894,13 @@
894 usage("pull AREA ?URL?");
895 }
896 mask = configure_name_to_mask(g.argv[3], 1);
897 if( g.argc==5 ){
898 zServer = g.argv[4];
899 }
900 url_parse(zServer, URL_PROMPT_PW);
901 if( g.urlProtocol==0 ) fossil_fatal("no server URL specified");
 
 
 
 
 
 
 
 
902 user_select();
903 url_enable_proxy("via proxy: ");
904 if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
905 if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
906 if( strncmp(zMethod, "push", n)==0 ){
907
+2 -2
--- src/http.c
+++ src/http.c
@@ -60,11 +60,10 @@
6060
zPw = 0;
6161
}else{
6262
/* Password failure while doing a sync from the command-line interface */
6363
url_prompt_for_password();
6464
zPw = g.urlPasswd;
65
- if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0);
6665
}
6766
6867
/* If the first character of the password is "#", then that character is
6968
** not really part of the password - it is an indicator that we should
7069
** use Basic Authentication. So skip that character.
@@ -72,10 +71,11 @@
7271
if( zPw && zPw[0]=='#' ) zPw++;
7372
7473
/* The login card wants the SHA1 hash of the password, so convert the
7574
** password to its SHA1 hash it it isn't already a SHA1 hash.
7675
*/
76
+ /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */
7777
if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
7878
7979
blob_append(&pw, zPw, -1);
8080
sha1sum_blob(&pw, &sig);
8181
blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
@@ -243,11 +243,11 @@
243243
while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
244244
j -= 4;
245245
zLine[j] = 0;
246246
}
247247
fossil_print("redirect to %s\n", &zLine[i]);
248
- url_parse(&zLine[i]);
248
+ url_parse(&zLine[i], 0);
249249
transport_close();
250250
return http_exchange(pSend, pReply, useLogin, maxRedirect);
251251
}else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
252252
if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
253253
isCompressed = 0;
254254
--- src/http.c
+++ src/http.c
@@ -60,11 +60,10 @@
60 zPw = 0;
61 }else{
62 /* Password failure while doing a sync from the command-line interface */
63 url_prompt_for_password();
64 zPw = g.urlPasswd;
65 if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0);
66 }
67
68 /* If the first character of the password is "#", then that character is
69 ** not really part of the password - it is an indicator that we should
70 ** use Basic Authentication. So skip that character.
@@ -72,10 +71,11 @@
72 if( zPw && zPw[0]=='#' ) zPw++;
73
74 /* The login card wants the SHA1 hash of the password, so convert the
75 ** password to its SHA1 hash it it isn't already a SHA1 hash.
76 */
 
77 if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
78
79 blob_append(&pw, zPw, -1);
80 sha1sum_blob(&pw, &sig);
81 blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
@@ -243,11 +243,11 @@
243 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
244 j -= 4;
245 zLine[j] = 0;
246 }
247 fossil_print("redirect to %s\n", &zLine[i]);
248 url_parse(&zLine[i]);
249 transport_close();
250 return http_exchange(pSend, pReply, useLogin, maxRedirect);
251 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
252 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
253 isCompressed = 0;
254
--- src/http.c
+++ src/http.c
@@ -60,11 +60,10 @@
60 zPw = 0;
61 }else{
62 /* Password failure while doing a sync from the command-line interface */
63 url_prompt_for_password();
64 zPw = g.urlPasswd;
 
65 }
66
67 /* If the first character of the password is "#", then that character is
68 ** not really part of the password - it is an indicator that we should
69 ** use Basic Authentication. So skip that character.
@@ -72,10 +71,11 @@
71 if( zPw && zPw[0]=='#' ) zPw++;
72
73 /* The login card wants the SHA1 hash of the password, so convert the
74 ** password to its SHA1 hash it it isn't already a SHA1 hash.
75 */
76 /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */
77 if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
78
79 blob_append(&pw, zPw, -1);
80 sha1sum_blob(&pw, &sig);
81 blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
@@ -243,11 +243,11 @@
243 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
244 j -= 4;
245 zLine[j] = 0;
246 }
247 fossil_print("redirect to %s\n", &zLine[i]);
248 url_parse(&zLine[i], 0);
249 transport_close();
250 return http_exchange(pSend, pReply, useLogin, maxRedirect);
251 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
252 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
253 isCompressed = 0;
254
+1 -1
--- src/main.c
+++ src/main.c
@@ -172,11 +172,11 @@
172172
char *urlPasswd; /* Password for http: */
173173
char *urlCanonical; /* Canonical representation of the URL */
174174
char *urlProxyAuth; /* Proxy-Authorizer: string */
175175
char *urlFossil; /* The fossil query parameter on ssh: */
176176
char *urlShell; /* The shell query parameter on ssh: */
177
- int dontKeepUrl; /* Do not persist the URL */
177
+ unsigned urlFlags; /* Boolean flags controlling URL processing */
178178
179179
const char *zLogin; /* Login name. "" if not logged in. */
180180
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
181181
** SSL client identity */
182182
int useLocalauth; /* No login required if from 127.0.0.1 */
183183
--- src/main.c
+++ src/main.c
@@ -172,11 +172,11 @@
172 char *urlPasswd; /* Password for http: */
173 char *urlCanonical; /* Canonical representation of the URL */
174 char *urlProxyAuth; /* Proxy-Authorizer: string */
175 char *urlFossil; /* The fossil query parameter on ssh: */
176 char *urlShell; /* The shell query parameter on ssh: */
177 int dontKeepUrl; /* Do not persist the URL */
178
179 const char *zLogin; /* Login name. "" if not logged in. */
180 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
181 ** SSL client identity */
182 int useLocalauth; /* No login required if from 127.0.0.1 */
183
--- src/main.c
+++ src/main.c
@@ -172,11 +172,11 @@
172 char *urlPasswd; /* Password for http: */
173 char *urlCanonical; /* Canonical representation of the URL */
174 char *urlProxyAuth; /* Proxy-Authorizer: string */
175 char *urlFossil; /* The fossil query parameter on ssh: */
176 char *urlShell; /* The shell query parameter on ssh: */
177 unsigned urlFlags; /* Boolean flags controlling URL processing */
178
179 const char *zLogin; /* Login name. "" if not logged in. */
180 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
181 ** SSL client identity */
182 int useLocalauth; /* No login required if from 127.0.0.1 */
183
+11 -40
--- src/sync.c
+++ src/sync.c
@@ -27,11 +27,10 @@
2727
** if the argument is false.
2828
**
2929
** Return the number of errors.
3030
*/
3131
int autosync(int flags){
32
- const char *zUrl;
3332
const char *zAutosync;
3433
const char *zPw;
3534
int rc;
3635
int configSync = 0; /* configuration changes transferred */
3736
if( g.fNoSync ){
@@ -49,18 +48,14 @@
4948
return 0; /* Autosync is completely off */
5049
}
5150
}else{
5251
/* Autosync defaults on. To make it default off, "return" here. */
5352
}
54
- zUrl = db_get("last-sync-url", 0);
55
- if( zUrl==0 ){
56
- return 0; /* No default server */
57
- }
58
- zPw = unobscure(db_get("last-sync-pw", 0));
59
- url_parse(zUrl);
53
+ url_parse(0, URL_REMEMBER);
54
+ if( g.urlProtocol==0 ) return 0;
6055
if( g.urlUser!=0 && g.urlPasswd==0 ){
61
- g.urlPasswd = mprintf("%s", zPw);
56
+ g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
6257
}
6358
#if 0 /* Disabled for now */
6459
if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
6560
/* When doing an automatic pull, also automatically pull shuns from
6661
** the server if pull_shuns is enabled.
@@ -88,12 +83,13 @@
8883
*/
8984
static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){
9085
const char *zUrl = 0;
9186
const char *zPw = 0;
9287
unsigned configSync = 0;
88
+ unsigned urlFlags = URL_REMEMBER | URL_PROMPT_PW;
9389
int urlOptional = find_option("autourl",0,0)!=0;
94
- g.dontKeepUrl = find_option("once",0,0)!=0;
90
+ if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
9591
if( find_option("private",0,0)!=0 ){
9692
*pSyncFlags |= SYNC_PRIVATE;
9793
}
9894
if( find_option("verbose","v",0)!=0 ){
9995
*pSyncFlags |= SYNC_VERBOSE;
@@ -100,32 +96,19 @@
10096
}
10197
url_proxy_options();
10298
db_find_and_open_repository(0, 0);
10399
db_open_config(0);
104100
if( g.argc==2 ){
105
- zUrl = db_get("last-sync-url", 0);
106
- zPw = unobscure(db_get("last-sync-pw", 0));
107101
if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
108102
}else if( g.argc==3 ){
109103
zUrl = g.argv[2];
110104
}
111
- if( zUrl==0 ){
105
+ url_parse(zUrl, urlFlags);
106
+ if( g.urlProtocol==0 ){
112107
if( urlOptional ) fossil_exit(0);
113108
usage("URL");
114109
}
115
- url_parse(zUrl);
116
- if( g.urlUser!=0 && g.urlPasswd==0 && g.urlIsSsh==0 ){
117
- if( zPw==0 ){
118
- url_prompt_for_password();
119
- }else{
120
- g.urlPasswd = mprintf("%s", zPw);
121
- }
122
- }
123
- if( !g.dontKeepUrl ){
124
- db_set("last-sync-url", g.urlCanonical, 0);
125
- if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0);
126
- }
127110
user_select();
128111
if( g.argc==2 ){
129112
if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
130113
fossil_print("Sync with %s\n", g.urlCanonical);
131114
}else if( (*pSyncFlags) & SYNC_PUSH ){
@@ -258,30 +241,18 @@
258241
db_find_and_open_repository(0, 0);
259242
if( g.argc!=2 && g.argc!=3 ){
260243
usage("remote-url ?URL|off?");
261244
}
262245
if( g.argc==3 ){
263
- if( fossil_strcmp(g.argv[2],"off")==0 ){
264
- db_unset("last-sync-url", 0);
265
- db_unset("last-sync-pw", 0);
266
- }else{
267
- url_parse(g.argv[2]);
268
- if( g.urlUser && g.urlPasswd==0 && g.urlIsSsh==0 ){
269
- url_prompt_for_password();
270
- }
271
- db_set("last-sync-url", g.urlCanonical, 0);
272
- if( g.urlPasswd ){
273
- db_set("last-sync-pw", obscure(g.urlPasswd), 0);
274
- }else{
275
- db_unset("last-sync-pw", 0);
276
- }
277
- }
246
+ db_unset("last-sync-url", 0);
247
+ db_unset("last-sync-pw", 0);
248
+ url_parse(g.argv[2], URL_REMEMBER|URL_PROMPT_PW);
278249
}
279250
zUrl = db_get("last-sync-url", 0);
280251
if( zUrl==0 ){
281252
fossil_print("off\n");
282253
return;
283254
}else{
284
- url_parse(zUrl);
255
+ url_parse(zUrl, 0);
285256
fossil_print("%s\n", g.urlCanonical);
286257
}
287258
}
288259
--- src/sync.c
+++ src/sync.c
@@ -27,11 +27,10 @@
27 ** if the argument is false.
28 **
29 ** Return the number of errors.
30 */
31 int autosync(int flags){
32 const char *zUrl;
33 const char *zAutosync;
34 const char *zPw;
35 int rc;
36 int configSync = 0; /* configuration changes transferred */
37 if( g.fNoSync ){
@@ -49,18 +48,14 @@
49 return 0; /* Autosync is completely off */
50 }
51 }else{
52 /* Autosync defaults on. To make it default off, "return" here. */
53 }
54 zUrl = db_get("last-sync-url", 0);
55 if( zUrl==0 ){
56 return 0; /* No default server */
57 }
58 zPw = unobscure(db_get("last-sync-pw", 0));
59 url_parse(zUrl);
60 if( g.urlUser!=0 && g.urlPasswd==0 ){
61 g.urlPasswd = mprintf("%s", zPw);
62 }
63 #if 0 /* Disabled for now */
64 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
65 /* When doing an automatic pull, also automatically pull shuns from
66 ** the server if pull_shuns is enabled.
@@ -88,12 +83,13 @@
88 */
89 static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){
90 const char *zUrl = 0;
91 const char *zPw = 0;
92 unsigned configSync = 0;
 
93 int urlOptional = find_option("autourl",0,0)!=0;
94 g.dontKeepUrl = find_option("once",0,0)!=0;
95 if( find_option("private",0,0)!=0 ){
96 *pSyncFlags |= SYNC_PRIVATE;
97 }
98 if( find_option("verbose","v",0)!=0 ){
99 *pSyncFlags |= SYNC_VERBOSE;
@@ -100,32 +96,19 @@
100 }
101 url_proxy_options();
102 db_find_and_open_repository(0, 0);
103 db_open_config(0);
104 if( g.argc==2 ){
105 zUrl = db_get("last-sync-url", 0);
106 zPw = unobscure(db_get("last-sync-pw", 0));
107 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
108 }else if( g.argc==3 ){
109 zUrl = g.argv[2];
110 }
111 if( zUrl==0 ){
 
112 if( urlOptional ) fossil_exit(0);
113 usage("URL");
114 }
115 url_parse(zUrl);
116 if( g.urlUser!=0 && g.urlPasswd==0 && g.urlIsSsh==0 ){
117 if( zPw==0 ){
118 url_prompt_for_password();
119 }else{
120 g.urlPasswd = mprintf("%s", zPw);
121 }
122 }
123 if( !g.dontKeepUrl ){
124 db_set("last-sync-url", g.urlCanonical, 0);
125 if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0);
126 }
127 user_select();
128 if( g.argc==2 ){
129 if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
130 fossil_print("Sync with %s\n", g.urlCanonical);
131 }else if( (*pSyncFlags) & SYNC_PUSH ){
@@ -258,30 +241,18 @@
258 db_find_and_open_repository(0, 0);
259 if( g.argc!=2 && g.argc!=3 ){
260 usage("remote-url ?URL|off?");
261 }
262 if( g.argc==3 ){
263 if( fossil_strcmp(g.argv[2],"off")==0 ){
264 db_unset("last-sync-url", 0);
265 db_unset("last-sync-pw", 0);
266 }else{
267 url_parse(g.argv[2]);
268 if( g.urlUser && g.urlPasswd==0 && g.urlIsSsh==0 ){
269 url_prompt_for_password();
270 }
271 db_set("last-sync-url", g.urlCanonical, 0);
272 if( g.urlPasswd ){
273 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
274 }else{
275 db_unset("last-sync-pw", 0);
276 }
277 }
278 }
279 zUrl = db_get("last-sync-url", 0);
280 if( zUrl==0 ){
281 fossil_print("off\n");
282 return;
283 }else{
284 url_parse(zUrl);
285 fossil_print("%s\n", g.urlCanonical);
286 }
287 }
288
--- src/sync.c
+++ src/sync.c
@@ -27,11 +27,10 @@
27 ** if the argument is false.
28 **
29 ** Return the number of errors.
30 */
31 int autosync(int flags){
 
32 const char *zAutosync;
33 const char *zPw;
34 int rc;
35 int configSync = 0; /* configuration changes transferred */
36 if( g.fNoSync ){
@@ -49,18 +48,14 @@
48 return 0; /* Autosync is completely off */
49 }
50 }else{
51 /* Autosync defaults on. To make it default off, "return" here. */
52 }
53 url_parse(0, URL_REMEMBER);
54 if( g.urlProtocol==0 ) return 0;
 
 
 
 
55 if( g.urlUser!=0 && g.urlPasswd==0 ){
56 g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
57 }
58 #if 0 /* Disabled for now */
59 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
60 /* When doing an automatic pull, also automatically pull shuns from
61 ** the server if pull_shuns is enabled.
@@ -88,12 +83,13 @@
83 */
84 static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){
85 const char *zUrl = 0;
86 const char *zPw = 0;
87 unsigned configSync = 0;
88 unsigned urlFlags = URL_REMEMBER | URL_PROMPT_PW;
89 int urlOptional = find_option("autourl",0,0)!=0;
90 if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
91 if( find_option("private",0,0)!=0 ){
92 *pSyncFlags |= SYNC_PRIVATE;
93 }
94 if( find_option("verbose","v",0)!=0 ){
95 *pSyncFlags |= SYNC_VERBOSE;
@@ -100,32 +96,19 @@
96 }
97 url_proxy_options();
98 db_find_and_open_repository(0, 0);
99 db_open_config(0);
100 if( g.argc==2 ){
 
 
101 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
102 }else if( g.argc==3 ){
103 zUrl = g.argv[2];
104 }
105 url_parse(zUrl, urlFlags);
106 if( g.urlProtocol==0 ){
107 if( urlOptional ) fossil_exit(0);
108 usage("URL");
109 }
 
 
 
 
 
 
 
 
 
 
 
 
110 user_select();
111 if( g.argc==2 ){
112 if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
113 fossil_print("Sync with %s\n", g.urlCanonical);
114 }else if( (*pSyncFlags) & SYNC_PUSH ){
@@ -258,30 +241,18 @@
241 db_find_and_open_repository(0, 0);
242 if( g.argc!=2 && g.argc!=3 ){
243 usage("remote-url ?URL|off?");
244 }
245 if( g.argc==3 ){
246 db_unset("last-sync-url", 0);
247 db_unset("last-sync-pw", 0);
248 url_parse(g.argv[2], URL_REMEMBER|URL_PROMPT_PW);
 
 
 
 
 
 
 
 
 
 
 
 
249 }
250 zUrl = db_get("last-sync-url", 0);
251 if( zUrl==0 ){
252 fossil_print("off\n");
253 return;
254 }else{
255 url_parse(zUrl, 0);
256 fossil_print("%s\n", g.urlCanonical);
257 }
258 }
259
+82 -7
--- src/url.c
+++ src/url.c
@@ -17,10 +17,22 @@
1717
**
1818
** This file contains code for parsing URLs that appear on the command-line
1919
*/
2020
#include "config.h"
2121
#include "url.h"
22
+
23
+#if INTERFACE
24
+/*
25
+** Flags for url_parse()
26
+*/
27
+#define URL_PROMPT_PW 0x001 /* Prompt for password if needed */
28
+#define URL_REMEMBER 0x002 /* Remember the url for later reuse */
29
+#define URL_ASK_REMEMBER_PW 0x004 /* Ask whether to remember prompted pw */
30
+#define URL_REMEMBER_PW 0x008 /* Should remember pw */
31
+
32
+#endif /* INTERFACE */
33
+
2234
2335
/*
2436
** Convert a string to lower-case.
2537
*/
2638
static void url_tolower(char *z){
@@ -29,11 +41,12 @@
2941
z++;
3042
}
3143
}
3244
3345
/*
34
-** Parse the given URL. Populate variables in the global "g" structure.
46
+** Parse the given URL, which describes a sync server. Populate variables
47
+** in the global "g" structure as follows:
3548
**
3649
** g.urlIsFile True if FILE:
3750
** g.urlIsHttps True if HTTPS:
3851
** g.urlIsSsh True if SSH:
3952
** g.urlProtocol "http" or "https" or "file"
@@ -44,22 +57,32 @@
4457
** g.urlUser Userid.
4558
** g.urlPasswd Password.
4659
** g.urlHostname HOST:PORT or just HOST if port is the default.
4760
** g.urlCanonical The URL in canonical form, omitting the password
4861
**
49
-** HTTP url format is:
62
+** HTTP url format as follows (HTTPS is the same with a different scheme):
5063
**
5164
** http://userid:password@host:port/path
5265
**
5366
** SSH url format is:
5467
**
5568
** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe
5669
**
5770
*/
58
-void url_parse(const char *zUrl){
71
+void url_parse(const char *zUrl, unsigned int urlFlags){
5972
int i, j, c;
6073
char *zFile = 0;
74
+ int bPrompted = 0;
75
+ int bSetUrl = 1;
76
+
77
+ if( zUrl==0 ){
78
+ zUrl = db_get("last-sync-url", 0);
79
+ if( zUrl==0 ) return;
80
+ g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
81
+ bSetUrl = 0;
82
+ }
83
+
6184
if( strncmp(zUrl, "http://", 7)==0
6285
|| strncmp(zUrl, "https://", 8)==0
6386
|| strncmp(zUrl, "ssh://", 6)==0
6487
){
6588
int iStart;
@@ -188,15 +211,16 @@
188211
zFile = mprintf("%s/FOSSIL", zUrl);
189212
if( file_isfile(zFile) ){
190213
g.urlIsFile = 1;
191214
}else{
192215
free(zFile);
193
- fossil_panic("unknown repository: %s", zUrl);
216
+ fossil_fatal("unknown repository: %s", zUrl);
194217
}
195218
}else{
196
- fossil_panic("unknown repository: %s", zUrl);
219
+ fossil_fatal("unknown repository: %s", zUrl);
197220
}
221
+ g.urlFlags = urlFlags;
198222
if( g.urlIsFile ){
199223
Blob cfile;
200224
dehttpize(zFile);
201225
file_canonical_name(zFile, &cfile, 0);
202226
free(zFile);
@@ -203,23 +227,45 @@
203227
g.urlProtocol = "file";
204228
g.urlPath = "";
205229
g.urlName = mprintf("%b", &cfile);
206230
g.urlCanonical = mprintf("file://%T", g.urlName);
207231
blob_reset(&cfile);
232
+ }else if( g.urlUser!=0 && g.urlPasswd==0 && (urlFlags & URL_PROMPT_PW) ){
233
+ url_prompt_for_password();
234
+ bPrompted = 1;
235
+ }
236
+ if( urlFlags & URL_REMEMBER ){
237
+ if( bSetUrl ){
238
+ db_set("last-sync-url", g.urlCanonical, 0);
239
+ }
240
+ if( !bPrompted && g.urlPasswd && g.urlUser ){
241
+ db_set("last-sync-pw", obscure(g.urlPasswd), 0);
242
+ }
208243
}
209244
}
210245
211246
/*
212247
** COMMAND: test-urlparser
248
+**
249
+** Usage: %fossil test-urlparser URL ?options?
250
+**
251
+** --remember Store results in last-sync-url
252
+** --prompt-pw Prompt for password if missing
213253
*/
214254
void cmd_test_urlparser(void){
215255
int i;
256
+ unsigned fg = 0;
216257
url_proxy_options();
258
+ if( find_option("remember",0,0) ){
259
+ db_must_be_within_tree();
260
+ fg |= URL_REMEMBER;
261
+ }
262
+ if( find_option("prompt-pw",0,0) ) fg |= URL_PROMPT_PW;
217263
if( g.argc!=3 && g.argc!=4 ){
218264
usage("URL");
219265
}
220
- url_parse(g.argv[2]);
266
+ url_parse(g.argv[2], fg);
221267
for(i=0; i<2; i++){
222268
fossil_print("g.urlIsFile = %d\n", g.urlIsFile);
223269
fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps);
224270
fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh);
225271
fossil_print("g.urlProtocol = %s\n", g.urlProtocol);
@@ -230,10 +276,11 @@
230276
fossil_print("g.urlPath = %s\n", g.urlPath);
231277
fossil_print("g.urlUser = %s\n", g.urlUser);
232278
fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
233279
fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
234280
fossil_print("g.urlFossil = %s\n", g.urlFossil);
281
+ fossil_print("g.urlFlags = 0x%02x\n", g.urlFlags);
235282
if( g.urlIsFile || g.urlIsSsh ) break;
236283
if( i==0 ){
237284
fossil_print("********\n");
238285
url_enable_proxy("Using proxy: ");
239286
}
@@ -282,13 +329,14 @@
282329
if( zProxy && zProxy[0] && !is_false(zProxy) ){
283330
char *zOriginalUrl = g.urlCanonical;
284331
char *zOriginalHost = g.urlHostname;
285332
char *zOriginalUser = g.urlUser;
286333
char *zOriginalPasswd = g.urlPasswd;
334
+ unsigned uOriginalFlags = g.urlFlags;
287335
g.urlUser = 0;
288336
g.urlPasswd = "";
289
- url_parse(zProxy);
337
+ url_parse(zProxy, 0);
290338
if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
291339
g.urlPath = zOriginalUrl;
292340
g.urlHostname = zOriginalHost;
293341
if( g.urlUser ){
294342
char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
@@ -296,10 +344,11 @@
296344
g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
297345
free(zCredentials1);
298346
}
299347
g.urlUser = zOriginalUser;
300348
g.urlPasswd = zOriginalPasswd;
349
+ g.urlFlags = uOriginalFlags;
301350
}
302351
}
303352
304353
#if INTERFACE
305354
/*
@@ -382,19 +431,45 @@
382431
*/
383432
void url_prompt_for_password(void){
384433
if( isatty(fileno(stdin)) ){
385434
char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
386435
Blob x;
436
+ fossil_force_newline();
387437
prompt_for_password(zPrompt, &x, 0);
388438
free(zPrompt);
389439
g.urlPasswd = mprintf("%b", &x);
390440
blob_reset(&x);
441
+ if( g.urlPasswd[0]
442
+ && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
443
+ ){
444
+ char c;
445
+ prompt_user("remember password (Y/n)? ", &x);
446
+ c = blob_str(&x)[0];
447
+ blob_reset(&x);
448
+ if( c!='n' && c!='N' ){
449
+ g.urlFlags |= URL_REMEMBER_PW;
450
+ if( g.urlFlags & URL_REMEMBER ){
451
+ db_set("last-sync-pw", obscure(g.urlPasswd), 0);
452
+ }
453
+ }
454
+ }
391455
}else{
392456
fossil_fatal("missing or incorrect password for user \"%s\"",
393457
g.urlUser);
394458
}
395459
}
460
+
461
+/*
462
+** Remember the URL if requested.
463
+*/
464
+void url_remember(void){
465
+ db_set("last-sync-url", g.urlCanonical, 0);
466
+ if( g.urlFlags & URL_REMEMBER_PW ){
467
+ db_set("last-sync-pw", obscure(g.urlPasswd), 0);
468
+ }
469
+ g.urlFlags = URL_REMEMBER;
470
+}
396471
397472
/* Preemptively prompt for a password if a username is given in the
398473
** URL but no password.
399474
*/
400475
void url_get_password_if_needed(void){
401476
--- src/url.c
+++ src/url.c
@@ -17,10 +17,22 @@
17 **
18 ** This file contains code for parsing URLs that appear on the command-line
19 */
20 #include "config.h"
21 #include "url.h"
 
 
 
 
 
 
 
 
 
 
 
 
22
23 /*
24 ** Convert a string to lower-case.
25 */
26 static void url_tolower(char *z){
@@ -29,11 +41,12 @@
29 z++;
30 }
31 }
32
33 /*
34 ** Parse the given URL. Populate variables in the global "g" structure.
 
35 **
36 ** g.urlIsFile True if FILE:
37 ** g.urlIsHttps True if HTTPS:
38 ** g.urlIsSsh True if SSH:
39 ** g.urlProtocol "http" or "https" or "file"
@@ -44,22 +57,32 @@
44 ** g.urlUser Userid.
45 ** g.urlPasswd Password.
46 ** g.urlHostname HOST:PORT or just HOST if port is the default.
47 ** g.urlCanonical The URL in canonical form, omitting the password
48 **
49 ** HTTP url format is:
50 **
51 ** http://userid:password@host:port/path
52 **
53 ** SSH url format is:
54 **
55 ** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe
56 **
57 */
58 void url_parse(const char *zUrl){
59 int i, j, c;
60 char *zFile = 0;
 
 
 
 
 
 
 
 
 
 
61 if( strncmp(zUrl, "http://", 7)==0
62 || strncmp(zUrl, "https://", 8)==0
63 || strncmp(zUrl, "ssh://", 6)==0
64 ){
65 int iStart;
@@ -188,15 +211,16 @@
188 zFile = mprintf("%s/FOSSIL", zUrl);
189 if( file_isfile(zFile) ){
190 g.urlIsFile = 1;
191 }else{
192 free(zFile);
193 fossil_panic("unknown repository: %s", zUrl);
194 }
195 }else{
196 fossil_panic("unknown repository: %s", zUrl);
197 }
 
198 if( g.urlIsFile ){
199 Blob cfile;
200 dehttpize(zFile);
201 file_canonical_name(zFile, &cfile, 0);
202 free(zFile);
@@ -203,23 +227,45 @@
203 g.urlProtocol = "file";
204 g.urlPath = "";
205 g.urlName = mprintf("%b", &cfile);
206 g.urlCanonical = mprintf("file://%T", g.urlName);
207 blob_reset(&cfile);
 
 
 
 
 
 
 
 
 
 
 
208 }
209 }
210
211 /*
212 ** COMMAND: test-urlparser
 
 
 
 
 
213 */
214 void cmd_test_urlparser(void){
215 int i;
 
216 url_proxy_options();
 
 
 
 
 
217 if( g.argc!=3 && g.argc!=4 ){
218 usage("URL");
219 }
220 url_parse(g.argv[2]);
221 for(i=0; i<2; i++){
222 fossil_print("g.urlIsFile = %d\n", g.urlIsFile);
223 fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps);
224 fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh);
225 fossil_print("g.urlProtocol = %s\n", g.urlProtocol);
@@ -230,10 +276,11 @@
230 fossil_print("g.urlPath = %s\n", g.urlPath);
231 fossil_print("g.urlUser = %s\n", g.urlUser);
232 fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
233 fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
234 fossil_print("g.urlFossil = %s\n", g.urlFossil);
 
235 if( g.urlIsFile || g.urlIsSsh ) break;
236 if( i==0 ){
237 fossil_print("********\n");
238 url_enable_proxy("Using proxy: ");
239 }
@@ -282,13 +329,14 @@
282 if( zProxy && zProxy[0] && !is_false(zProxy) ){
283 char *zOriginalUrl = g.urlCanonical;
284 char *zOriginalHost = g.urlHostname;
285 char *zOriginalUser = g.urlUser;
286 char *zOriginalPasswd = g.urlPasswd;
 
287 g.urlUser = 0;
288 g.urlPasswd = "";
289 url_parse(zProxy);
290 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
291 g.urlPath = zOriginalUrl;
292 g.urlHostname = zOriginalHost;
293 if( g.urlUser ){
294 char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
@@ -296,10 +344,11 @@
296 g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
297 free(zCredentials1);
298 }
299 g.urlUser = zOriginalUser;
300 g.urlPasswd = zOriginalPasswd;
 
301 }
302 }
303
304 #if INTERFACE
305 /*
@@ -382,19 +431,45 @@
382 */
383 void url_prompt_for_password(void){
384 if( isatty(fileno(stdin)) ){
385 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
386 Blob x;
 
387 prompt_for_password(zPrompt, &x, 0);
388 free(zPrompt);
389 g.urlPasswd = mprintf("%b", &x);
390 blob_reset(&x);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391 }else{
392 fossil_fatal("missing or incorrect password for user \"%s\"",
393 g.urlUser);
394 }
395 }
 
 
 
 
 
 
 
 
 
 
 
396
397 /* Preemptively prompt for a password if a username is given in the
398 ** URL but no password.
399 */
400 void url_get_password_if_needed(void){
401
--- src/url.c
+++ src/url.c
@@ -17,10 +17,22 @@
17 **
18 ** This file contains code for parsing URLs that appear on the command-line
19 */
20 #include "config.h"
21 #include "url.h"
22
23 #if INTERFACE
24 /*
25 ** Flags for url_parse()
26 */
27 #define URL_PROMPT_PW 0x001 /* Prompt for password if needed */
28 #define URL_REMEMBER 0x002 /* Remember the url for later reuse */
29 #define URL_ASK_REMEMBER_PW 0x004 /* Ask whether to remember prompted pw */
30 #define URL_REMEMBER_PW 0x008 /* Should remember pw */
31
32 #endif /* INTERFACE */
33
34
35 /*
36 ** Convert a string to lower-case.
37 */
38 static void url_tolower(char *z){
@@ -29,11 +41,12 @@
41 z++;
42 }
43 }
44
45 /*
46 ** Parse the given URL, which describes a sync server. Populate variables
47 ** in the global "g" structure as follows:
48 **
49 ** g.urlIsFile True if FILE:
50 ** g.urlIsHttps True if HTTPS:
51 ** g.urlIsSsh True if SSH:
52 ** g.urlProtocol "http" or "https" or "file"
@@ -44,22 +57,32 @@
57 ** g.urlUser Userid.
58 ** g.urlPasswd Password.
59 ** g.urlHostname HOST:PORT or just HOST if port is the default.
60 ** g.urlCanonical The URL in canonical form, omitting the password
61 **
62 ** HTTP url format as follows (HTTPS is the same with a different scheme):
63 **
64 ** http://userid:password@host:port/path
65 **
66 ** SSH url format is:
67 **
68 ** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe
69 **
70 */
71 void url_parse(const char *zUrl, unsigned int urlFlags){
72 int i, j, c;
73 char *zFile = 0;
74 int bPrompted = 0;
75 int bSetUrl = 1;
76
77 if( zUrl==0 ){
78 zUrl = db_get("last-sync-url", 0);
79 if( zUrl==0 ) return;
80 g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
81 bSetUrl = 0;
82 }
83
84 if( strncmp(zUrl, "http://", 7)==0
85 || strncmp(zUrl, "https://", 8)==0
86 || strncmp(zUrl, "ssh://", 6)==0
87 ){
88 int iStart;
@@ -188,15 +211,16 @@
211 zFile = mprintf("%s/FOSSIL", zUrl);
212 if( file_isfile(zFile) ){
213 g.urlIsFile = 1;
214 }else{
215 free(zFile);
216 fossil_fatal("unknown repository: %s", zUrl);
217 }
218 }else{
219 fossil_fatal("unknown repository: %s", zUrl);
220 }
221 g.urlFlags = urlFlags;
222 if( g.urlIsFile ){
223 Blob cfile;
224 dehttpize(zFile);
225 file_canonical_name(zFile, &cfile, 0);
226 free(zFile);
@@ -203,23 +227,45 @@
227 g.urlProtocol = "file";
228 g.urlPath = "";
229 g.urlName = mprintf("%b", &cfile);
230 g.urlCanonical = mprintf("file://%T", g.urlName);
231 blob_reset(&cfile);
232 }else if( g.urlUser!=0 && g.urlPasswd==0 && (urlFlags & URL_PROMPT_PW) ){
233 url_prompt_for_password();
234 bPrompted = 1;
235 }
236 if( urlFlags & URL_REMEMBER ){
237 if( bSetUrl ){
238 db_set("last-sync-url", g.urlCanonical, 0);
239 }
240 if( !bPrompted && g.urlPasswd && g.urlUser ){
241 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
242 }
243 }
244 }
245
246 /*
247 ** COMMAND: test-urlparser
248 **
249 ** Usage: %fossil test-urlparser URL ?options?
250 **
251 ** --remember Store results in last-sync-url
252 ** --prompt-pw Prompt for password if missing
253 */
254 void cmd_test_urlparser(void){
255 int i;
256 unsigned fg = 0;
257 url_proxy_options();
258 if( find_option("remember",0,0) ){
259 db_must_be_within_tree();
260 fg |= URL_REMEMBER;
261 }
262 if( find_option("prompt-pw",0,0) ) fg |= URL_PROMPT_PW;
263 if( g.argc!=3 && g.argc!=4 ){
264 usage("URL");
265 }
266 url_parse(g.argv[2], fg);
267 for(i=0; i<2; i++){
268 fossil_print("g.urlIsFile = %d\n", g.urlIsFile);
269 fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps);
270 fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh);
271 fossil_print("g.urlProtocol = %s\n", g.urlProtocol);
@@ -230,10 +276,11 @@
276 fossil_print("g.urlPath = %s\n", g.urlPath);
277 fossil_print("g.urlUser = %s\n", g.urlUser);
278 fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
279 fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
280 fossil_print("g.urlFossil = %s\n", g.urlFossil);
281 fossil_print("g.urlFlags = 0x%02x\n", g.urlFlags);
282 if( g.urlIsFile || g.urlIsSsh ) break;
283 if( i==0 ){
284 fossil_print("********\n");
285 url_enable_proxy("Using proxy: ");
286 }
@@ -282,13 +329,14 @@
329 if( zProxy && zProxy[0] && !is_false(zProxy) ){
330 char *zOriginalUrl = g.urlCanonical;
331 char *zOriginalHost = g.urlHostname;
332 char *zOriginalUser = g.urlUser;
333 char *zOriginalPasswd = g.urlPasswd;
334 unsigned uOriginalFlags = g.urlFlags;
335 g.urlUser = 0;
336 g.urlPasswd = "";
337 url_parse(zProxy, 0);
338 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
339 g.urlPath = zOriginalUrl;
340 g.urlHostname = zOriginalHost;
341 if( g.urlUser ){
342 char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
@@ -296,10 +344,11 @@
344 g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
345 free(zCredentials1);
346 }
347 g.urlUser = zOriginalUser;
348 g.urlPasswd = zOriginalPasswd;
349 g.urlFlags = uOriginalFlags;
350 }
351 }
352
353 #if INTERFACE
354 /*
@@ -382,19 +431,45 @@
431 */
432 void url_prompt_for_password(void){
433 if( isatty(fileno(stdin)) ){
434 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
435 Blob x;
436 fossil_force_newline();
437 prompt_for_password(zPrompt, &x, 0);
438 free(zPrompt);
439 g.urlPasswd = mprintf("%b", &x);
440 blob_reset(&x);
441 if( g.urlPasswd[0]
442 && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
443 ){
444 char c;
445 prompt_user("remember password (Y/n)? ", &x);
446 c = blob_str(&x)[0];
447 blob_reset(&x);
448 if( c!='n' && c!='N' ){
449 g.urlFlags |= URL_REMEMBER_PW;
450 if( g.urlFlags & URL_REMEMBER ){
451 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
452 }
453 }
454 }
455 }else{
456 fossil_fatal("missing or incorrect password for user \"%s\"",
457 g.urlUser);
458 }
459 }
460
461 /*
462 ** Remember the URL if requested.
463 */
464 void url_remember(void){
465 db_set("last-sync-url", g.urlCanonical, 0);
466 if( g.urlFlags & URL_REMEMBER_PW ){
467 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
468 }
469 g.urlFlags = URL_REMEMBER;
470 }
471
472 /* Preemptively prompt for a password if a username is given in the
473 ** URL but no password.
474 */
475 void url_get_password_if_needed(void){
476
+2 -5
--- src/user.c
+++ src/user.c
@@ -335,15 +335,12 @@
335335
336336
if( attempt_user(fossil_getenv("USER")) ) return;
337337
338338
if( attempt_user(fossil_getenv("USERNAME")) ) return;
339339
340
- zUrl = db_get("last-sync-url", 0);
341
- if( zUrl ){
342
- url_parse(zUrl);
343
- if( attempt_user(g.urlUser) ) return;
344
- }
340
+ url_parse(0, 0);
341
+ if( g.urlUser && attempt_user(g.urlUser) ) return;
345342
346343
fossil_print(
347344
"Cannot figure out who you are! Consider using the --user\n"
348345
"command line option, setting your USER environment variable,\n"
349346
"or setting a default user with \"fossil user default USER\".\n"
350347
--- src/user.c
+++ src/user.c
@@ -335,15 +335,12 @@
335
336 if( attempt_user(fossil_getenv("USER")) ) return;
337
338 if( attempt_user(fossil_getenv("USERNAME")) ) return;
339
340 zUrl = db_get("last-sync-url", 0);
341 if( zUrl ){
342 url_parse(zUrl);
343 if( attempt_user(g.urlUser) ) return;
344 }
345
346 fossil_print(
347 "Cannot figure out who you are! Consider using the --user\n"
348 "command line option, setting your USER environment variable,\n"
349 "or setting a default user with \"fossil user default USER\".\n"
350
--- src/user.c
+++ src/user.c
@@ -335,15 +335,12 @@
335
336 if( attempt_user(fossil_getenv("USER")) ) return;
337
338 if( attempt_user(fossil_getenv("USERNAME")) ) return;
339
340 url_parse(0, 0);
341 if( g.urlUser && attempt_user(g.urlUser) ) return;
 
 
 
342
343 fossil_print(
344 "Cannot figure out who you are! Consider using the --user\n"
345 "command line option, setting your USER environment variable,\n"
346 "or setting a default user with \"fossil user default USER\".\n"
347
+5 -4
--- src/xfer.c
+++ src/xfer.c
@@ -1738,21 +1738,22 @@
17381738
*/
17391739
if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
17401740
if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
17411741
char *zMsg = blob_terminate(&xfer.aToken[1]);
17421742
defossilize(zMsg);
1743
+ fossil_force_newline();
1744
+ fossil_print("Error: %s\n", zMsg);
17431745
if( fossil_strcmp(zMsg, "login failed")==0 ){
17441746
if( nCycle<2 ){
1745
- if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
1747
+ g.urlPasswd = 0;
17461748
go = 1;
1749
+ if( g.cgiOutput==0 ) url_prompt_for_password();
17471750
}
17481751
}else{
17491752
blob_appendf(&xfer.err, "server says: %s\n", zMsg);
1753
+ nErr++;
17501754
}
1751
- fossil_force_newline();
1752
- fossil_warning("Error: %s", zMsg);
1753
- nErr++;
17541755
break;
17551756
}
17561757
}else
17571758
17581759
/* Unknown message */
17591760
--- src/xfer.c
+++ src/xfer.c
@@ -1738,21 +1738,22 @@
1738 */
1739 if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
1740 if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
1741 char *zMsg = blob_terminate(&xfer.aToken[1]);
1742 defossilize(zMsg);
 
 
1743 if( fossil_strcmp(zMsg, "login failed")==0 ){
1744 if( nCycle<2 ){
1745 if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
1746 go = 1;
 
1747 }
1748 }else{
1749 blob_appendf(&xfer.err, "server says: %s\n", zMsg);
 
1750 }
1751 fossil_force_newline();
1752 fossil_warning("Error: %s", zMsg);
1753 nErr++;
1754 break;
1755 }
1756 }else
1757
1758 /* Unknown message */
1759
--- src/xfer.c
+++ src/xfer.c
@@ -1738,21 +1738,22 @@
1738 */
1739 if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
1740 if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
1741 char *zMsg = blob_terminate(&xfer.aToken[1]);
1742 defossilize(zMsg);
1743 fossil_force_newline();
1744 fossil_print("Error: %s\n", zMsg);
1745 if( fossil_strcmp(zMsg, "login failed")==0 ){
1746 if( nCycle<2 ){
1747 g.urlPasswd = 0;
1748 go = 1;
1749 if( g.cgiOutput==0 ) url_prompt_for_password();
1750 }
1751 }else{
1752 blob_appendf(&xfer.err, "server says: %s\n", zMsg);
1753 nErr++;
1754 }
 
 
 
1755 break;
1756 }
1757 }else
1758
1759 /* Unknown message */
1760

Keyboard Shortcuts

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