github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/mongo/utils/data_cleansing.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package utils
     5  
     6  import "strings"
     7  
     8  // EscapeKeys is used to escape bad keys in a map. A statusDoc without
     9  // escaped keys is broken.
    10  func EscapeKeys(input map[string]interface{}) map[string]interface{} {
    11  	return mapKeys(escapeReplacer.Replace, input)
    12  }
    13  
    14  // UnescapeKeys is used to restore escaped keys from a map to their
    15  // original values.
    16  func UnescapeKeys(input map[string]interface{}) map[string]interface{} {
    17  	return mapKeys(unescapeReplacer.Replace, input)
    18  }
    19  
    20  // EscapeString escapes a string to be safe to store in Mongo.
    21  func EscapeString(s string) string {
    22  	return escapeReplacer.Replace(s)
    23  }
    24  
    25  // UnescapeString restores escaped characters from a string to their
    26  // original values.
    27  func UnescapeString(s string) string {
    28  	return unescapeReplacer.Replace(s)
    29  }
    30  
    31  // See: http://docs.mongodb.org/manual/faq/developers/#faq-dollar-sign-escaping
    32  // for why we're using those replacements.
    33  const (
    34  	fullWidthDot    = "\uff0e"
    35  	fullWidthDollar = "\uff04"
    36  )
    37  
    38  var (
    39  	escapeReplacer   = strings.NewReplacer(".", fullWidthDot, "$", fullWidthDollar)
    40  	unescapeReplacer = strings.NewReplacer(fullWidthDot, ".", fullWidthDollar, "$")
    41  )
    42  
    43  // mapKeys returns a copy of the supplied map, with all nested map[string]interface{}
    44  // keys transformed by f. All other types are ignored.
    45  func mapKeys(f func(string) string, input map[string]interface{}) map[string]interface{} {
    46  	result := make(map[string]interface{})
    47  	for key, value := range input {
    48  		if submap, ok := value.(map[string]interface{}); ok {
    49  			value = mapKeys(f, submap)
    50  		}
    51  		result[f(key)] = value
    52  	}
    53  	return result
    54  }