@@ -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