mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 07:12:26 -05:00 
			
		
		
		
	
		
			
	
	
		
			121 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			121 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | /* | ||
|  |  * | ||
|  |  * Copyright 2020 gRPC authors. | ||
|  |  * | ||
|  |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||
|  |  * you may not use this file except in compliance with the License. | ||
|  |  * You may obtain a copy of the License at | ||
|  |  * | ||
|  |  *     http://www.apache.org/licenses/LICENSE-2.0 | ||
|  |  * | ||
|  |  * Unless required by applicable law or agreed to in writing, software | ||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
|  |  * See the License for the specific language governing permissions and | ||
|  |  * limitations under the License. | ||
|  |  * | ||
|  |  */ | ||
|  | 
 | ||
|  | // Package metadata contains functions to set and get metadata from addresses. | ||
|  | // | ||
|  | // This package is experimental. | ||
|  | package metadata | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"fmt" | ||
|  | 	"strings" | ||
|  | 
 | ||
|  | 	"google.golang.org/grpc/metadata" | ||
|  | 	"google.golang.org/grpc/resolver" | ||
|  | ) | ||
|  | 
 | ||
|  | type mdKeyType string | ||
|  | 
 | ||
|  | const mdKey = mdKeyType("grpc.internal.address.metadata") | ||
|  | 
 | ||
|  | type mdValue metadata.MD | ||
|  | 
 | ||
|  | func (m mdValue) Equal(o interface{}) bool { | ||
|  | 	om, ok := o.(mdValue) | ||
|  | 	if !ok { | ||
|  | 		return false | ||
|  | 	} | ||
|  | 	if len(m) != len(om) { | ||
|  | 		return false | ||
|  | 	} | ||
|  | 	for k, v := range m { | ||
|  | 		ov := om[k] | ||
|  | 		if len(ov) != len(v) { | ||
|  | 			return false | ||
|  | 		} | ||
|  | 		for i, ve := range v { | ||
|  | 			if ov[i] != ve { | ||
|  | 				return false | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 	return true | ||
|  | } | ||
|  | 
 | ||
|  | // Get returns the metadata of addr. | ||
|  | func Get(addr resolver.Address) metadata.MD { | ||
|  | 	attrs := addr.Attributes | ||
|  | 	if attrs == nil { | ||
|  | 		return nil | ||
|  | 	} | ||
|  | 	md, _ := attrs.Value(mdKey).(mdValue) | ||
|  | 	return metadata.MD(md) | ||
|  | } | ||
|  | 
 | ||
|  | // Set sets (overrides) the metadata in addr. | ||
|  | // | ||
|  | // When a SubConn is created with this address, the RPCs sent on it will all | ||
|  | // have this metadata. | ||
|  | func Set(addr resolver.Address, md metadata.MD) resolver.Address { | ||
|  | 	addr.Attributes = addr.Attributes.WithValue(mdKey, mdValue(md)) | ||
|  | 	return addr | ||
|  | } | ||
|  | 
 | ||
|  | // Validate returns an error if the input md contains invalid keys or values. | ||
|  | // | ||
|  | // If the header is not a pseudo-header, the following items are checked: | ||
|  | // - header names must contain one or more characters from this set [0-9 a-z _ - .]. | ||
|  | // - if the header-name ends with a "-bin" suffix, no validation of the header value is performed. | ||
|  | // - otherwise, the header value must contain one or more characters from the set [%x20-%x7E]. | ||
|  | func Validate(md metadata.MD) error { | ||
|  | 	for k, vals := range md { | ||
|  | 		// pseudo-header will be ignored | ||
|  | 		if k[0] == ':' { | ||
|  | 			continue | ||
|  | 		} | ||
|  | 		// check key, for i that saving a conversion if not using for range | ||
|  | 		for i := 0; i < len(k); i++ { | ||
|  | 			r := k[i] | ||
|  | 			if !(r >= 'a' && r <= 'z') && !(r >= '0' && r <= '9') && r != '.' && r != '-' && r != '_' { | ||
|  | 				return fmt.Errorf("header key %q contains illegal characters not in [0-9a-z-_.]", k) | ||
|  | 			} | ||
|  | 		} | ||
|  | 		if strings.HasSuffix(k, "-bin") { | ||
|  | 			continue | ||
|  | 		} | ||
|  | 		// check value | ||
|  | 		for _, val := range vals { | ||
|  | 			if hasNotPrintable(val) { | ||
|  | 				return fmt.Errorf("header key %q contains value with non-printable ASCII characters", k) | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // hasNotPrintable return true if msg contains any characters which are not in %x20-%x7E | ||
|  | func hasNotPrintable(msg string) bool { | ||
|  | 	// for i that saving a conversion if not using for range | ||
|  | 	for i := 0; i < len(msg); i++ { | ||
|  | 		if msg[i] < 0x20 || msg[i] > 0x7E { | ||
|  | 			return true | ||
|  | 		} | ||
|  | 	} | ||
|  | 	return false | ||
|  | } |