@@ -42,7 +42,7 @@ static long curl_low_speed_time = -1;
42
42
static int curl_ftp_no_epsv ;
43
43
static const char * curl_http_proxy ;
44
44
static const char * curl_cookie_file ;
45
- static char * user_name , * user_pass ;
45
+ static char * user_name , * user_pass , * description ;
46
46
static const char * user_agent ;
47
47
48
48
#if LIBCURL_VERSION_NUM >= 0x071700
@@ -139,6 +139,27 @@ static void process_curl_messages(void)
139
139
}
140
140
#endif
141
141
142
+ static char * git_getpass_with_description (const char * what , const char * desc )
143
+ {
144
+ struct strbuf prompt = STRBUF_INIT ;
145
+ char * r ;
146
+
147
+ if (desc )
148
+ strbuf_addf (& prompt , "%s for '%s': " , what , desc );
149
+ else
150
+ strbuf_addf (& prompt , "%s: " , what );
151
+ /*
152
+ * NEEDSWORK: for usernames, we should do something less magical that
153
+ * actually echoes the characters. However, we need to read from
154
+ * /dev/tty and not stdio, which is not portable (but getpass will do
155
+ * it for us). http.c uses the same workaround.
156
+ */
157
+ r = git_getpass (prompt .buf );
158
+
159
+ strbuf_release (& prompt );
160
+ return xstrdup (r );
161
+ }
162
+
142
163
static int http_options (const char * var , const char * value , void * cb )
143
164
{
144
165
if (!strcmp ("http.sslverify" , var )) {
@@ -214,7 +235,7 @@ static void init_curl_http_auth(CURL *result)
214
235
if (user_name ) {
215
236
struct strbuf up = STRBUF_INIT ;
216
237
if (!user_pass )
217
- user_pass = xstrdup (git_getpass ("Password: " ));
238
+ user_pass = xstrdup (git_getpass_with_description ("Password" , description ));
218
239
strbuf_addf (& up , "%s:%s" , user_name , user_pass );
219
240
curl_easy_setopt (result , CURLOPT_USERPWD ,
220
241
strbuf_detach (& up , NULL ));
@@ -229,7 +250,7 @@ static int has_cert_password(void)
229
250
return 0 ;
230
251
/* Only prompt the user once. */
231
252
ssl_cert_password_required = -1 ;
232
- ssl_cert_password = git_getpass ("Certificate Password: " );
253
+ ssl_cert_password = git_getpass_with_description ("Certificate Password" , description );
233
254
if (ssl_cert_password != NULL ) {
234
255
ssl_cert_password = xstrdup (ssl_cert_password );
235
256
return 1 ;
@@ -307,8 +328,7 @@ static CURL *get_curl_handle(void)
307
328
308
329
static void http_auth_init (const char * url )
309
330
{
310
- char * at , * colon , * cp , * slash , * decoded ;
311
- int len ;
331
+ const char * at , * colon , * cp , * slash , * host ;
312
332
313
333
cp = strstr (url , "://" );
314
334
if (!cp )
@@ -324,34 +344,22 @@ static void http_auth_init(const char *url)
324
344
at = strchr (cp , '@' );
325
345
colon = strchr (cp , ':' );
326
346
slash = strchrnul (cp , '/' );
327
- if (!at || slash <= at )
328
- return ; /* No credentials */
329
- if (!colon || at <= colon ) {
347
+ if (!at || slash <= at ) {
348
+ /* No credentials, but we may have to ask for some later */
349
+ host = cp ;
350
+ }
351
+ else if (!colon || at <= colon ) {
330
352
/* Only username */
331
- len = at - cp ;
332
- user_name = xmalloc (len + 1 );
333
- memcpy (user_name , cp , len );
334
- user_name [len ] = '\0' ;
335
- decoded = url_decode (user_name );
336
- free (user_name );
337
- user_name = decoded ;
353
+ user_name = url_decode_mem (cp , at - cp );
338
354
user_pass = NULL ;
355
+ host = at + 1 ;
339
356
} else {
340
- len = colon - cp ;
341
- user_name = xmalloc (len + 1 );
342
- memcpy (user_name , cp , len );
343
- user_name [len ] = '\0' ;
344
- decoded = url_decode (user_name );
345
- free (user_name );
346
- user_name = decoded ;
347
- len = at - (colon + 1 );
348
- user_pass = xmalloc (len + 1 );
349
- memcpy (user_pass , colon + 1 , len );
350
- user_pass [len ] = '\0' ;
351
- decoded = url_decode (user_pass );
352
- free (user_pass );
353
- user_pass = decoded ;
357
+ user_name = url_decode_mem (cp , colon - cp );
358
+ user_pass = url_decode_mem (colon + 1 , at - (colon + 1 ));
359
+ host = at + 1 ;
354
360
}
361
+
362
+ description = url_decode_mem (host , slash - host );
355
363
}
356
364
357
365
static void set_from_env (const char * * var , const char * envname )
@@ -361,7 +369,7 @@ static void set_from_env(const char **var, const char *envname)
361
369
* var = val ;
362
370
}
363
371
364
- void http_init (struct remote * remote )
372
+ void http_init (struct remote * remote , const char * url )
365
373
{
366
374
char * low_speed_limit ;
367
375
char * low_speed_time ;
@@ -425,11 +433,11 @@ void http_init(struct remote *remote)
425
433
if (getenv ("GIT_CURL_FTP_NO_EPSV" ))
426
434
curl_ftp_no_epsv = 1 ;
427
435
428
- if (remote && remote -> url && remote -> url [ 0 ] ) {
429
- http_auth_init (remote -> url [ 0 ] );
436
+ if (url ) {
437
+ http_auth_init (url );
430
438
if (!ssl_cert_password_required &&
431
439
getenv ("GIT_SSL_CERT_PASSWORD_PROTECTED" ) &&
432
- !prefixcmp (remote -> url [ 0 ] , "https://" ))
440
+ !prefixcmp (url , "https://" ))
433
441
ssl_cert_password_required = 1 ;
434
442
}
435
443
@@ -847,7 +855,7 @@ static int http_request(const char *url, void *result, int target, int options)
847
855
* but that is non-portable. Using git_getpass() can at least be stubbed
848
856
* on other platforms with a different implementation if/when necessary.
849
857
*/
850
- user_name = xstrdup (git_getpass ("Username: " ));
858
+ user_name = xstrdup (git_getpass_with_description ("Username" , description ));
851
859
init_curl_http_auth (slot -> curl );
852
860
ret = HTTP_REAUTH ;
853
861
}
@@ -870,13 +878,18 @@ static int http_request(const char *url, void *result, int target, int options)
870
878
return ret ;
871
879
}
872
880
881
+ static int http_request_reauth (const char * url , void * result , int target ,
882
+ int options )
883
+ {
884
+ int ret = http_request (url , result , target , options );
885
+ if (ret != HTTP_REAUTH )
886
+ return ret ;
887
+ return http_request (url , result , target , options );
888
+ }
889
+
873
890
int http_get_strbuf (const char * url , struct strbuf * result , int options )
874
891
{
875
- int http_ret = http_request (url , result , HTTP_REQUEST_STRBUF , options );
876
- if (http_ret == HTTP_REAUTH ) {
877
- http_ret = http_request (url , result , HTTP_REQUEST_STRBUF , options );
878
- }
879
- return http_ret ;
892
+ return http_request_reauth (url , result , HTTP_REQUEST_STRBUF , options );
880
893
}
881
894
882
895
/*
@@ -899,7 +912,7 @@ static int http_get_file(const char *url, const char *filename, int options)
899
912
goto cleanup ;
900
913
}
901
914
902
- ret = http_request (url , result , HTTP_REQUEST_FILE , options );
915
+ ret = http_request_reauth (url , result , HTTP_REQUEST_FILE , options );
903
916
fclose (result );
904
917
905
918
if ((ret == HTTP_OK ) && move_temp_to_file (tmpfile .buf , filename ))
0 commit comments