github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/backend/onedrive/replace.go (about)

     1  /*
     2  Translate file names for one drive
     3  
     4  OneDrive reserved characters
     5  
     6  The following characters are OneDrive reserved characters, and can't
     7  be used in OneDrive folder and file names.
     8  
     9    onedrive-reserved  = "/" / "\" / "*" / "<" / ">" / "?" / ":" / "|"
    10    onedrive-business-reserved
    11                       = "/" / "\" / "*" / "<" / ">" / "?" / ":" / "|" / "#" / "%"
    12  
    13  Note: Folder names can't end with a period (.).
    14  
    15  Note: OneDrive for Business file or folder names cannot begin with a
    16  tilde ('~').
    17  
    18  */
    19  
    20  package onedrive
    21  
    22  import (
    23  	"regexp"
    24  	"strings"
    25  )
    26  
    27  // charMap holds replacements for characters
    28  //
    29  // Onedrive has a restricted set of characters compared to other cloud
    30  // storage systems, so we to map these to the FULLWIDTH unicode
    31  // equivalents
    32  //
    33  // http://unicode-search.net/unicode-namesearch.pl?term=SOLIDUS
    34  var (
    35  	charMap = map[rune]rune{
    36  		'\\': '\', // FULLWIDTH REVERSE SOLIDUS
    37  		'*':  '*', // FULLWIDTH ASTERISK
    38  		'<':  '<', // FULLWIDTH LESS-THAN SIGN
    39  		'>':  '>', // FULLWIDTH GREATER-THAN SIGN
    40  		'?':  '?', // FULLWIDTH QUESTION MARK
    41  		':':  ':', // FULLWIDTH COLON
    42  		'|':  '|', // FULLWIDTH VERTICAL LINE
    43  		'#':  '#', // FULLWIDTH NUMBER SIGN
    44  		'%':  '%', // FULLWIDTH PERCENT SIGN
    45  		'"':  '"', // FULLWIDTH QUOTATION MARK - not on the list but seems to be reserved
    46  		'.':  '.', // FULLWIDTH FULL STOP
    47  		'~':  '~', // FULLWIDTH TILDE
    48  		' ':  '␠', // SYMBOL FOR SPACE
    49  	}
    50  	invCharMap           map[rune]rune
    51  	fixEndingInPeriod    = regexp.MustCompile(`\.(/|$)`)
    52  	fixStartingWithTilde = regexp.MustCompile(`(/|^)~`)
    53  	fixStartingWithSpace = regexp.MustCompile(`(/|^) `)
    54  )
    55  
    56  func init() {
    57  	// Create inverse charMap
    58  	invCharMap = make(map[rune]rune, len(charMap))
    59  	for k, v := range charMap {
    60  		invCharMap[v] = k
    61  	}
    62  }
    63  
    64  // replaceReservedChars takes a path and substitutes any reserved
    65  // characters in it
    66  func replaceReservedChars(in string) string {
    67  	// Folder names can't end with a period '.'
    68  	in = fixEndingInPeriod.ReplaceAllString(in, string(charMap['.'])+"$1")
    69  	// OneDrive for Business file or folder names cannot begin with a tilde '~'
    70  	in = fixStartingWithTilde.ReplaceAllString(in, "$1"+string(charMap['~']))
    71  	// Apparently file names can't start with space either
    72  	in = fixStartingWithSpace.ReplaceAllString(in, "$1"+string(charMap[' ']))
    73  	// Replace reserved characters
    74  	return strings.Map(func(c rune) rune {
    75  		if replacement, ok := charMap[c]; ok && c != '.' && c != '~' && c != ' ' {
    76  			return replacement
    77  		}
    78  		return c
    79  	}, in)
    80  }
    81  
    82  // restoreReservedChars takes a path and undoes any substitutions
    83  // made by replaceReservedChars
    84  func restoreReservedChars(in string) string {
    85  	return strings.Map(func(c rune) rune {
    86  		if replacement, ok := invCharMap[c]; ok {
    87  			return replacement
    88  		}
    89  		return c
    90  	}, in)
    91  }