@@ -26,6 +26,12 @@ static struct keyword_entry keywords[] = {
2626	{ "error" ,	GIT_COLOR_BOLD_RED  },
2727};
2828
29+ static  enum  {
30+ 	ALLOW_NO_CONTROL_CHARACTERS  =  0 ,
31+ 	ALLOW_ALL_CONTROL_CHARACTERS  =  1 ,
32+ 	ALLOW_ANSI_COLOR_SEQUENCES  =  2 
33+ } allow_control_characters  =  ALLOW_ANSI_COLOR_SEQUENCES ;
34+ 
2935/* Returns a color setting (GIT_COLOR_NEVER, etc). */ 
3036static  int  use_sideband_colors (void )
3137{
@@ -39,6 +45,25 @@ static int use_sideband_colors(void)
3945	if  (use_sideband_colors_cached  >= 0 )
4046		return  use_sideband_colors_cached ;
4147
48+ 	switch  (git_config_get_maybe_bool ("sideband.allowcontrolcharacters" , & i )) {
49+ 	case  0 : /* Boolean value */ 
50+ 		allow_control_characters  =  i  ? ALLOW_ALL_CONTROL_CHARACTERS  :
51+ 			ALLOW_NO_CONTROL_CHARACTERS ;
52+ 		break ;
53+ 	case  -1 : /* non-Boolean value */ 
54+ 		if  (git_config_get_string_tmp ("sideband.allowcontrolcharacters" ,
55+ 					      & value ))
56+ 			; /* huh? `get_maybe_bool()` returned -1 */ 
57+ 		else  if  (!strcmp (value , "color" ))
58+ 			allow_control_characters  =  ALLOW_ANSI_COLOR_SEQUENCES ;
59+ 		else 
60+ 			warning (_ ("unrecognized value for `sideband." 
61+ 				  "allowControlCharacters`: '%s'" ), value );
62+ 		break ;
63+ 	default :
64+ 		break ; /* not configured */ 
65+ 	}
66+ 
4267	if  (!git_config_get_string_tmp (key , & value ))
4368		use_sideband_colors_cached  =  git_config_colorbool (key , value );
4469	else  if  (!git_config_get_string_tmp ("color.ui" , & value ))
@@ -66,6 +91,55 @@ void list_config_color_sideband_slots(struct string_list *list, const char *pref
6691		list_config_item (list , prefix , keywords [i ].keyword );
6792}
6893
94+ static  int  handle_ansi_color_sequence (struct  strbuf  * dest , const  char  * src , int  n )
95+ {
96+ 	int  i ;
97+ 
98+ 	/* 
99+ 	 * Valid ANSI color sequences are of the form 
100+ 	 * 
101+ 	 * ESC [ [<n> [; <n>]*] m 
102+ 	 */ 
103+ 
104+ 	if  (allow_control_characters  !=  ALLOW_ANSI_COLOR_SEQUENCES  || 
105+ 	    n  <  3  ||  src [0 ] !=  '\x1b'  ||  src [1 ] !=  '[' )
106+ 		return  0 ;
107+ 
108+ 	for  (i  =  2 ; i  <  n ; i ++ ) {
109+ 		if  (src [i ] ==  'm' ) {
110+ 			strbuf_add (dest , src , i  +  1 );
111+ 			return  i ;
112+ 		}
113+ 		if  (!isdigit (src [i ]) &&  src [i ] !=  ';' )
114+ 			break ;
115+ 	}
116+ 
117+ 	return  0 ;
118+ }
119+ 
120+ static  void  strbuf_add_sanitized (struct  strbuf  * dest , const  char  * src , int  n )
121+ {
122+ 	int  i ;
123+ 
124+ 	if  (allow_control_characters  ==  ALLOW_ALL_CONTROL_CHARACTERS ) {
125+ 		strbuf_add (dest , src , n );
126+ 		return ;
127+ 	}
128+ 
129+ 	strbuf_grow (dest , n );
130+ 	for  (; n  &&  * src ; src ++ , n -- ) {
131+ 		if  (!iscntrl (* src ) ||  * src  ==  '\t'  ||  * src  ==  '\n' )
132+ 			strbuf_addch (dest , * src );
133+ 		else  if  ((i  =  handle_ansi_color_sequence (dest , src , n ))) {
134+ 			src  +=  i ;
135+ 			n  -=  i ;
136+ 		} else  {
137+ 			strbuf_addch (dest , '^' );
138+ 			strbuf_addch (dest , 0x40  +  * src );
139+ 		}
140+ 	}
141+ }
142+ 
69143/* 
70144 * Optionally highlight one keyword in remote output if it appears at the start 
71145 * of the line. This should be called for a single line only, which is 
@@ -81,7 +155,7 @@ static void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)
81155	int  i ;
82156
83157	if  (!want_color_stderr (use_sideband_colors ())) {
84- 		strbuf_add (dest , src , n );
158+ 		strbuf_add_sanitized (dest , src , n );
85159		return ;
86160	}
87161
@@ -114,7 +188,7 @@ static void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)
114188		}
115189	}
116190
117- 	strbuf_add (dest , src , n );
191+ 	strbuf_add_sanitized (dest , src , n );
118192}
119193
120194
0 commit comments