@@ -42,7 +42,7 @@ static long curl_low_speed_time = -1;
4242static int curl_ftp_no_epsv ;
4343static const char * curl_http_proxy ;
4444static const char * curl_cookie_file ;
45- static char * user_name , * user_pass ;
45+ static char * user_name , * user_pass , * description ;
4646static const char * user_agent ;
4747
4848#if LIBCURL_VERSION_NUM >= 0x071700
@@ -139,6 +139,27 @@ static void process_curl_messages(void)
139139}
140140#endif
141141
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+
142163static int http_options (const char * var , const char * value , void * cb )
143164{
144165 if (!strcmp ("http.sslverify" , var )) {
@@ -214,7 +235,7 @@ static void init_curl_http_auth(CURL *result)
214235 if (user_name ) {
215236 struct strbuf up = STRBUF_INIT ;
216237 if (!user_pass )
217- user_pass = xstrdup (git_getpass ("Password: " ));
238+ user_pass = xstrdup (git_getpass_with_description ("Password" , description ));
218239 strbuf_addf (& up , "%s:%s" , user_name , user_pass );
219240 curl_easy_setopt (result , CURLOPT_USERPWD ,
220241 strbuf_detach (& up , NULL ));
@@ -229,7 +250,7 @@ static int has_cert_password(void)
229250 return 0 ;
230251 /* Only prompt the user once. */
231252 ssl_cert_password_required = -1 ;
232- ssl_cert_password = git_getpass ("Certificate Password: " );
253+ ssl_cert_password = git_getpass_with_description ("Certificate Password" , description );
233254 if (ssl_cert_password != NULL ) {
234255 ssl_cert_password = xstrdup (ssl_cert_password );
235256 return 1 ;
@@ -307,8 +328,7 @@ static CURL *get_curl_handle(void)
307328
308329static void http_auth_init (const char * url )
309330{
310- char * at , * colon , * cp , * slash , * decoded ;
311- int len ;
331+ const char * at , * colon , * cp , * slash , * host ;
312332
313333 cp = strstr (url , "://" );
314334 if (!cp )
@@ -324,34 +344,22 @@ static void http_auth_init(const char *url)
324344 at = strchr (cp , '@' );
325345 colon = strchr (cp , ':' );
326346 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 ) {
330352 /* 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 );
338354 user_pass = NULL ;
355+ host = at + 1 ;
339356 } 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 ;
354360 }
361+
362+ description = url_decode_mem (host , slash - host );
355363}
356364
357365static 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)
361369 * var = val ;
362370}
363371
364- void http_init (struct remote * remote )
372+ void http_init (struct remote * remote , const char * url )
365373{
366374 char * low_speed_limit ;
367375 char * low_speed_time ;
@@ -425,11 +433,11 @@ void http_init(struct remote *remote)
425433 if (getenv ("GIT_CURL_FTP_NO_EPSV" ))
426434 curl_ftp_no_epsv = 1 ;
427435
428- if (remote && remote -> url && remote -> url [ 0 ] ) {
429- http_auth_init (remote -> url [ 0 ] );
436+ if (url ) {
437+ http_auth_init (url );
430438 if (!ssl_cert_password_required &&
431439 getenv ("GIT_SSL_CERT_PASSWORD_PROTECTED" ) &&
432- !prefixcmp (remote -> url [ 0 ] , "https://" ))
440+ !prefixcmp (url , "https://" ))
433441 ssl_cert_password_required = 1 ;
434442 }
435443
@@ -847,7 +855,7 @@ static int http_request(const char *url, void *result, int target, int options)
847855 * but that is non-portable. Using git_getpass() can at least be stubbed
848856 * on other platforms with a different implementation if/when necessary.
849857 */
850- user_name = xstrdup (git_getpass ("Username: " ));
858+ user_name = xstrdup (git_getpass_with_description ("Username" , description ));
851859 init_curl_http_auth (slot -> curl );
852860 ret = HTTP_REAUTH ;
853861 }
@@ -870,13 +878,18 @@ static int http_request(const char *url, void *result, int target, int options)
870878 return ret ;
871879}
872880
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+
873890int http_get_strbuf (const char * url , struct strbuf * result , int options )
874891{
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 );
880893}
881894
882895/*
@@ -899,7 +912,7 @@ static int http_get_file(const char *url, const char *filename, int options)
899912 goto cleanup ;
900913 }
901914
902- ret = http_request (url , result , HTTP_REQUEST_FILE , options );
915+ ret = http_request_reauth (url , result , HTTP_REQUEST_FILE , options );
903916 fclose (result );
904917
905918 if ((ret == HTTP_OK ) && move_temp_to_file (tmpfile .buf , filename ))
0 commit comments