2017-02-07 16:53:16 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package   rewrite 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import   ( 
  
						 
					
						
							
								
									
										
										
										
											2018-07-08 03:18:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 "context" 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 "fmt" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 "regexp" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 "strconv" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 "strings" 
  
						 
					
						
							
								
									
										
										
										
											2018-02-14 07:00:04 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 "github.com/coredns/coredns/plugin" 
  
						 
					
						
							
								
									
										
										
										
											2018-07-02 15:39:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 "github.com/coredns/coredns/request" 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 "github.com/miekg/dns" 
  
						 
					
						
							
								
									
										
										
										
											2017-02-07 16:53:16 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// stringRewriter rewrites a string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type   stringRewriter   interface   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 rewriteString ( src   string )   string 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// regexStringRewriter can be used to rewrite strings by regex pattern. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it contains all the information required to detect and execute a rewrite 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// on a string. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type   regexStringRewriter   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 pattern       * regexp . Regexp 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 replacement   string 
  
						 
					
						
							
								
									
										
										
										
											2017-02-07 16:53:16 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var   _   stringRewriter   =   & regexStringRewriter { } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newStringRewriter ( pattern   * regexp . Regexp ,   replacement   string )   stringRewriter   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   & regexStringRewriter { pattern ,   replacement } 
  
						 
					
						
							
								
									
										
										
										
											2017-02-07 16:53:16 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func   ( r   * regexStringRewriter )   rewriteString ( src   string )   string   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 regexGroups   :=   r . pattern . FindStringSubmatch ( src ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   len ( regexGroups )   ==   0   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   src 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 s   :=   r . replacement 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 for   groupIndex ,   groupValue   :=   range   regexGroups   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 groupIndexStr   :=   "{"   +   strconv . Itoa ( groupIndex )   +   "}" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 s   =   strings . Replace ( s ,   groupIndexStr ,   groupValue ,   - 1 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   s 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// remapStringRewriter maps a dedicated string to another string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it also maps a the domain of a sub domain. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type   remapStringRewriter   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 orig          string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 replacement   string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var   _   stringRewriter   =   & remapStringRewriter { } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newRemapStringRewriter ( orig ,   replacement   string )   stringRewriter   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   & remapStringRewriter { orig ,   replacement } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   ( r   * remapStringRewriter )   rewriteString ( src   string )   string   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   src   ==   r . orig   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   r . replacement 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   strings . HasSuffix ( src ,   "." + r . orig )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   src [ 0 : len ( src ) - len ( r . orig ) ]   +   r . replacement 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   src 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// suffixStringRewriter maps a dedicated suffix string to another string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type   suffixStringRewriter   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 suffix        string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 replacement   string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var   _   stringRewriter   =   & suffixStringRewriter { } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newSuffixStringRewriter ( orig ,   replacement   string )   stringRewriter   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   & suffixStringRewriter { orig ,   replacement } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   ( r   * suffixStringRewriter )   rewriteString ( src   string )   string   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   strings . HasSuffix ( src ,   r . suffix )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   strings . TrimSuffix ( src ,   r . suffix )   +   r . replacement 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   src 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// nameRewriterResponseRule maps a record name according to a stringRewriter. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type   nameRewriterResponseRule   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 stringRewriter 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-13 17:49:36 +05:30 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func   ( r   * nameRewriterResponseRule )   RewriteResponse ( res   * dns . Msg ,   rr   dns . RR )   { 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 rr . Header ( ) . Name   =   r . rewriteString ( rr . Header ( ) . Name ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// valueRewriterResponseRule maps a record value according to a stringRewriter. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type   valueRewriterResponseRule   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 stringRewriter 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-13 17:49:36 +05:30 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func   ( r   * valueRewriterResponseRule )   RewriteResponse ( res   * dns . Msg ,   rr   dns . RR )   { 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 value   :=   getRecordValueForRewrite ( rr ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   value   !=   ""   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 new   :=   r . rewriteString ( value ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   new   !=   value   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 setRewrittenRecordValue ( rr ,   new ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const   ( 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // ExactMatch matches only on exact match of the name in the question section of a request 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 ExactMatch   =   "exact" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // PrefixMatch matches when the name begins with the matching string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 PrefixMatch   =   "prefix" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // SuffixMatch matches when the name ends with the matching string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 SuffixMatch   =   "suffix" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // SubstringMatch matches on partial match of the name in the question section of a request 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 SubstringMatch   =   "substring" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // RegexMatch matches when the name in the question section of a request matches a regular expression 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 RegexMatch   =   "regex" 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // AnswerMatch matches an answer rewrite 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 AnswerMatch   =   "answer" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // AutoMatch matches the auto name answer rewrite 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 AutoMatch   =   "auto" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // NameMatch matches the name answer rewrite 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 NameMatch   =   "name" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 // ValueMatch matches the value answer rewrite 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 ValueMatch   =   "value" 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type   nameRuleBase   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 nextAction    string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 auto          bool 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 replacement   string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 static        ResponseRules 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newNameRuleBase ( nextAction   string ,   auto   bool ,   replacement   string ,   staticResponses   ResponseRules )   nameRuleBase   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   nameRuleBase { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 nextAction :    nextAction , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 auto :          auto , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 replacement :   replacement , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 static :        staticResponses , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// responseRuleFor create for auto mode dynamically response rewriters for name and value 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// reverting the mapping done by the name rewrite rule, which can be found in the state. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   ( rule   * nameRuleBase )   responseRuleFor ( state   request . Request )   ( ResponseRules ,   Result )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   ! rule . auto   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   rule . static ,   RewriteDone 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 rewriter   :=   newRemapStringRewriter ( state . Req . Question [ 0 ] . Name ,   state . Name ( ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 rules   :=   ResponseRules { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 & nameRewriterResponseRule { rewriter } , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 & valueRewriterResponseRule { rewriter } , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   append ( rules ,   rule . static ... ) ,   RewriteDone 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Mode returns the processing nextAction 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   ( rule   * nameRuleBase )   Mode ( )   string   {   return   rule . nextAction   } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// exactNameRule rewrites the current request based upon exact match of the name 
  
						 
					
						
							
								
									
										
										
										
											2018-07-02 15:39:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// in the question section of the request. 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type   exactNameRule   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 nameRuleBase 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 from   string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newExactNameRule ( nextAction   string ,   orig ,   replacement   string ,   answers   ResponseRules )   Rule   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   & exactNameRule { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 newNameRuleBase ( nextAction ,   true ,   replacement ,   answers ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 orig , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   ( rule   * exactNameRule )   Rewrite ( ctx   context . Context ,   state   request . Request )   ( ResponseRules ,   Result )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   rule . from   ==   state . Name ( )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 state . Req . Question [ 0 ] . Name   =   rule . replacement 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   rule . responseRuleFor ( state ) 
  
						 
					
						
							
								
									
										
										
										
											2017-02-07 16:53:16 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 return   nil ,   RewriteIgnored 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// prefixNameRule rewrites the current request when the name begins with the matching string. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type   prefixNameRule   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 nameRuleBase 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 prefix   string 
  
						 
					
						
							
								
									
										
										
										
											2017-02-07 16:53:16 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
									
										
										
										
											2017-09-20 13:06:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func   newPrefixNameRule ( nextAction   string ,   auto   bool ,   prefix ,   replacement   string ,   answers   ResponseRules )   Rule   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   & prefixNameRule { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 newNameRuleBase ( nextAction ,   auto ,   replacement ,   answers ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 prefix , 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func   ( rule   * prefixNameRule )   Rewrite ( ctx   context . Context ,   state   request . Request )   ( ResponseRules ,   Result )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   strings . HasPrefix ( state . Name ( ) ,   rule . prefix )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 state . Req . Question [ 0 ] . Name   =   rule . replacement   +   strings . TrimPrefix ( state . Name ( ) ,   rule . prefix ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   rule . responseRuleFor ( state ) 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 return   nil ,   RewriteIgnored 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// suffixNameRule rewrites the current request when the name ends with the matching string. 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type   suffixNameRule   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 nameRuleBase 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 suffix   string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newSuffixNameRule ( nextAction   string ,   auto   bool ,   suffix ,   replacement   string ,   answers   ResponseRules )   Rule   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 var   rules   ResponseRules 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   auto   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 // for a suffix rewriter better standard response rewrites can be done 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 // just by using the original suffix/replacement in the opposite order 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 rewriter   :=   newSuffixStringRewriter ( replacement ,   suffix ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 rules   =   ResponseRules { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 & nameRewriterResponseRule { rewriter } , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 & valueRewriterResponseRule { rewriter } , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   & suffixNameRule { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 newNameRuleBase ( nextAction ,   false ,   replacement ,   append ( rules ,   answers ... ) ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 suffix , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   ( rule   * suffixNameRule )   Rewrite ( ctx   context . Context ,   state   request . Request )   ( ResponseRules ,   Result )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   strings . HasSuffix ( state . Name ( ) ,   rule . suffix )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 state . Req . Question [ 0 ] . Name   =   strings . TrimSuffix ( state . Name ( ) ,   rule . suffix )   +   rule . replacement 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   rule . responseRuleFor ( state ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   nil ,   RewriteIgnored 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// substringNameRule rewrites the current request based upon partial match of the 
  
						 
					
						
							
								
									
										
										
										
											2018-07-02 15:39:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// name in the question section of the request. 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type   substringNameRule   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 nameRuleBase 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 substring   string 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newSubstringNameRule ( nextAction   string ,   auto   bool ,   substring ,   replacement   string ,   answers   ResponseRules )   Rule   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   & substringNameRule { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 newNameRuleBase ( nextAction ,   auto ,   replacement ,   answers ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 substring , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   ( rule   * substringNameRule )   Rewrite ( ctx   context . Context ,   state   request . Request )   ( ResponseRules ,   Result )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   strings . Contains ( state . Name ( ) ,   rule . substring )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 state . Req . Question [ 0 ] . Name   =   strings . Replace ( state . Name ( ) ,   rule . substring ,   rule . replacement ,   - 1 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   rule . responseRuleFor ( state ) 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 return   nil ,   RewriteIgnored 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// regexNameRule rewrites the current request when the name in the question 
  
						 
					
						
							
								
									
										
										
										
											2018-07-02 15:39:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// section of the request matches a regular expression. 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type   regexNameRule   struct   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 nameRuleBase 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 pattern   * regexp . Regexp 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newRegexNameRule ( nextAction   string ,   auto   bool ,   pattern   * regexp . Regexp ,   replacement   string ,   answers   ResponseRules )   Rule   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   & regexNameRule { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 newNameRuleBase ( nextAction ,   auto ,   replacement ,   answers ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 pattern , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   ( rule   * regexNameRule )   Rewrite ( ctx   context . Context ,   state   request . Request )   ( ResponseRules ,   Result )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 regexGroups   :=   rule . pattern . FindStringSubmatch ( state . Name ( ) ) 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 if   len ( regexGroups )   ==   0   { 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 return   nil ,   RewriteIgnored 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 s   :=   rule . replacement 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 for   groupIndex ,   groupValue   :=   range   regexGroups   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 groupIndexStr   :=   "{"   +   strconv . Itoa ( groupIndex )   +   "}" 
  
						 
					
						
							
								
									
										
										
										
											2019-09-27 18:10:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 s   =   strings . Replace ( s ,   groupIndexStr ,   groupValue ,   - 1 ) 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2018-07-02 15:39:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 state . Req . Question [ 0 ] . Name   =   s 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 return   rule . responseRuleFor ( state ) 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// newNameRule creates a name matching rule based on exact, partial, or regex match 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   newNameRule ( nextAction   string ,   args   ... string )   ( Rule ,   error )   { 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 var   matchType ,   rewriteQuestionFrom ,   rewriteQuestionTo   string 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 if   len ( args )   <   2   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   nil ,   fmt . Errorf ( "too few arguments for a name rule" ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 if   len ( args )   ==   2   { 
  
						 
					
						
							
								
									
										
										
										
											2022-03-01 11:33:52 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 matchType   =   ExactMatch 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 rewriteQuestionFrom   =   plugin . Name ( args [ 0 ] ) . Normalize ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 rewriteQuestionTo   =   plugin . Name ( args [ 1 ] ) . Normalize ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   len ( args )   >=   3   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 matchType   =   strings . ToLower ( args [ 0 ] ) 
  
						 
					
						
							
								
									
										
										
										
											2022-03-01 11:33:52 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 if   matchType   ==   RegexMatch   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteQuestionFrom   =   args [ 1 ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteQuestionTo   =   args [ 2 ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 }   else   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteQuestionFrom   =   plugin . Name ( args [ 1 ] ) . Normalize ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteQuestionTo   =   plugin . Name ( args [ 2 ] ) . Normalize ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   matchType   ==   ExactMatch   ||   matchType   ==   SuffixMatch   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   ! hasClosingDot ( rewriteQuestionFrom )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteQuestionFrom   =   rewriteQuestionFrom   +   "." 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   ! hasClosingDot ( rewriteQuestionTo )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteQuestionTo   =   rewriteQuestionTo   +   "." 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 var   err   error 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 var   answers   ResponseRules 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 auto   :=   false 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   len ( args )   >   3   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 auto ,   answers ,   err   =   parseAnswerRules ( matchType ,   args [ 3 : ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   err   !=   nil   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 return   nil ,   err 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 switch   matchType   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 case   ExactMatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   _ ,   err   :=   isValidRegexPattern ( rewriteQuestionTo ,   rewriteQuestionFrom ) ;   err   !=   nil   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 return   nil ,   err 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   newExactNameRule ( nextAction ,   rewriteQuestionFrom ,   rewriteQuestionTo ,   answers ) ,   nil 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 case   PrefixMatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   newPrefixNameRule ( nextAction ,   auto ,   rewriteQuestionFrom ,   rewriteQuestionTo ,   answers ) ,   nil 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 case   SuffixMatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   newSuffixNameRule ( nextAction ,   auto ,   rewriteQuestionFrom ,   rewriteQuestionTo ,   answers ) ,   nil 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 case   SubstringMatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   newSubstringNameRule ( nextAction ,   auto ,   rewriteQuestionFrom ,   rewriteQuestionTo ,   answers ) ,   nil 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 case   RegexMatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 rewriteQuestionFromPattern ,   err   :=   isValidRegexPattern ( rewriteQuestionFrom ,   rewriteQuestionTo ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   err   !=   nil   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 return   nil ,   err 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 rewriteQuestionTo   :=   plugin . Name ( args [ 2 ] ) . Normalize ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   newRegexNameRule ( nextAction ,   auto ,   rewriteQuestionFromPattern ,   rewriteQuestionTo ,   answers ) ,   nil 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 default : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   nil ,   fmt . Errorf ( "name rule supports only exact, prefix, suffix, substring, and regex name matching, received: %s" ,   matchType ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func   parseAnswerRules ( name   string ,   args   [ ] string )   ( auto   bool ,   rules   ResponseRules ,   err   error )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 auto   =   false 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 arg   :=   0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 nameRules   :=   0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 last   :=   "" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   len ( args )   <   2   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   false ,   nil ,   fmt . Errorf ( "invalid arguments for %s rule" ,   name ) 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 for   arg   <   len ( args )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   last   ==   ""   &&   args [ arg ]   !=   AnswerMatch   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 if   last   ==   ""   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 return   false ,   nil ,   fmt . Errorf ( "exceeded the number of arguments for a non-answer rule argument for %s rule" ,   name ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 return   false ,   nil ,   fmt . Errorf ( "exceeded the number of arguments for %s answer rule for %s rule" ,   last ,   name ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   args [ arg ]   ==   AnswerMatch   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 arg ++ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   len ( args ) - arg   ==   0   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 return   false ,   nil ,   fmt . Errorf ( "type missing for answer rule for %s rule" ,   name ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 last   =   args [ arg ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 arg ++ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 switch   last   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 case   AutoMatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 auto   =   true 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 continue 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 case   NameMatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 if   len ( args ) - arg   <   2   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 return   false ,   nil ,   fmt . Errorf ( "%s answer rule for %s rule: 2 arguments required" ,   last ,   name ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteAnswerFrom   :=   args [ arg ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteAnswerTo   :=   args [ arg + 1 ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteAnswerFromPattern ,   err   :=   isValidRegexPattern ( rewriteAnswerFrom ,   rewriteAnswerTo ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteAnswerTo   =   plugin . Name ( rewriteAnswerTo ) . Normalize ( ) 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 if   err   !=   nil   { 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												 return   false ,   nil ,   fmt . Errorf ( "%s answer rule for %s rule: %s" ,   last ,   name ,   err ) 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 rules   =   append ( rules ,   & nameRewriterResponseRule { newStringRewriter ( rewriteAnswerFromPattern ,   rewriteAnswerTo ) } ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 arg   +=   2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 nameRules ++ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 case   ValueMatch : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 if   len ( args ) - arg   <   2   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 return   false ,   nil ,   fmt . Errorf ( "%s answer rule for %s rule: 2 arguments required" ,   last ,   name ) 
  
						 
					
						
							
								
									
										
										
										
											2021-02-23 09:12:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 rewriteAnswerFrom   :=   args [ arg ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteAnswerTo   :=   args [ arg + 1 ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteAnswerFromPattern ,   err   :=   isValidRegexPattern ( rewriteAnswerFrom ,   rewriteAnswerTo ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rewriteAnswerTo   =   plugin . Name ( rewriteAnswerTo ) . Normalize ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 if   err   !=   nil   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 return   false ,   nil ,   fmt . Errorf ( "%s answer rule for %s rule: %s" ,   last ,   name ,   err ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 rules   =   append ( rules ,   & valueRewriterResponseRule { newStringRewriter ( rewriteAnswerFromPattern ,   rewriteAnswerTo ) } ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 arg   +=   2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 default : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 return   false ,   nil ,   fmt . Errorf ( "invalid type %q for answer rule for %s rule" ,   last ,   name ) 
  
						 
					
						
							
								
									
										
										
										
											2018-01-18 10:41:14 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2017-12-13 11:31:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 if   auto   &&   nameRules   >   0   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 return   false ,   nil ,   fmt . Errorf ( "auto name answer rule cannot be combined with explicit name anwer rules" ) 
  
						 
					
						
							
								
									
										
										
										
											2021-02-23 09:12:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
									
										
										
										
											2021-05-04 10:05:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 return 
  
						 
					
						
							
								
									
										
										
										
											2021-02-24 10:22:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
									
										
										
										
											2018-01-18 10:41:14 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-09-01 15:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// hasClosingDot returns true if s has a closing dot at the end. 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func   hasClosingDot ( s   string )   bool   { 
  
						 
					
						
							
								
									
										
										
										
											2019-09-27 18:10:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 return   strings . HasSuffix ( s ,   "." ) 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-09-01 15:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// getSubExprUsage returns the number of subexpressions used in s. 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func   getSubExprUsage ( s   string )   int   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 subExprUsage   :=   0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 for   i   :=   0 ;   i   <=   100 ;   i ++   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 if   strings . Contains ( s ,   "{" + strconv . Itoa ( i ) + "}" )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 subExprUsage ++ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   subExprUsage 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-09-01 15:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// isValidRegexPattern returns a regular expression for pattern matching or errors, if any. 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func   isValidRegexPattern ( rewriteFrom ,   rewriteTo   string )   ( * regexp . Regexp ,   error )   { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 rewriteFromPattern ,   err   :=   regexp . Compile ( rewriteFrom ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   err   !=   nil   { 
  
						 
					
						
							
								
									
										
										
										
											2019-02-27 20:25:02 +07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 return   nil ,   fmt . Errorf ( "invalid regex matching pattern: %s" ,   rewriteFrom ) 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 if   getSubExprUsage ( rewriteTo )   >   rewriteFromPattern . NumSubexp ( )   { 
  
						 
					
						
							
								
									
										
										
										
											2019-02-27 20:25:02 +07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 return   nil ,   fmt . Errorf ( "the rewrite regex pattern (%s) uses more subexpressions than its corresponding matching regex pattern (%s)" ,   rewriteTo ,   rewriteFrom ) 
  
						 
					
						
							
								
									
										
										
										
											2018-10-23 16:59:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 return   rewriteFromPattern ,   nil 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}