44
45
* any. The "next" pointer is set to "end" if there is no next
47
* 'illegal' is a string of characters that are not allowed to
48
* be present in the pre-converted CP name.
51
49
* length (not including NUL termination) >= 0 of next
52
50
* component on success.
62
CPName_GetComponentGeneric(char const *begin, // IN: Beginning of buffer
63
char const *end, // IN: End of buffer
64
char const *illegal, // IN: Illegal characters
65
char const **next) // OUT: Start of next component
60
CPName_GetComponent(char const *begin, // IN: Beginning of buffer
61
char const *end, // IN: End of buffer
62
char const **next) // OUT: Start of next component
68
65
char const *myNext;
103
* Make sure the input buffer does not contain any illegal
104
* characters. In particular, we want to make sure that there
105
* are no path separator characters in the name. Since the
106
* cross-platform name format by definition does not use path
107
* separators, this is an error condition, and is likely the
108
* sign of an attack. See bug 27926. [bac]
110
* The test above ensures that *walk != NUL here, so we don't
111
* need to test it again before calling strchr().
113
if (strchr(illegal, *walk) != NULL) {
114
Log("CPName_GetComponentGeneric: error: Illegal char \"%c\" found in "
120
99
len = walk - begin;
123
* We're only interested in looking for dot/dotdot if the illegal character
124
* string isn't empty. These characters are only relevant when the resulting
125
* string is to be passed down to the filesystem. Some callers (such as the
126
* HGFS server, when dealing with actual filenames) do care about this
127
* validation, but others (like DnD, hgFileCopy, and the HGFS server when
128
* converting share names) just want to convert a CPName down to a
129
* nul-terminated string.
131
if (strcmp(illegal, "") != 0 &&
132
((len == 1 && memcmp(begin, ".", 1) == 0) ||
133
(len == 2 && memcmp(begin, "..", 2) == 0))) {
134
Log("CPName_GetComponentGeneric: error: found dot/dotdot\n");
139
102
return ((int) len);
144
107
*----------------------------------------------------------------------
109
* CPNameEscapeAndConvertFrom --
111
* Converts a cross-platform name representation into a string for
112
* use in the local filesystem.
113
* Escapes illegal characters as a part of convertion.
114
* This is a cross-platform implementation and takes the path separator
115
* argument as an argument. The path separator is prepended before each
116
* additional path component, so this function never adds a trailing path
121
* error < 0 on failure (the converted string did not fit in
122
* the buffer provided or the input was invalid).
127
*----------------------------------------------------------------------
131
CPNameEscapeAndConvertFrom(char const **bufIn, // IN/OUT: Input to convert
132
size_t *inSize, // IN/OUT: Size of input
133
size_t *outSize, // IN/OUT: Size of output buffer
134
char **bufOut, // IN/OUT: Output buffer
135
char pathSep) // IN: Path separator character
139
inputSize = HgfsEscape_GetSize(*bufIn, *inSize);
140
if (inputSize != 0) {
141
char *savedBufOut = *bufOut;
142
char const *savedOutConst = savedBufOut;
143
size_t savedOutSize = *outSize;
144
if (inputSize > *outSize) {
145
Log("CPNameEscapeAndConvertFrom: error: not enough room for escaping\n");
149
/* Leaving space for the leading path separator, thus output to savedBufOut + 1. */
150
*inSize = HgfsEscape_Do(*bufIn, *inSize, savedOutSize, savedBufOut + 1);
151
result = CPNameConvertFrom(&savedOutConst, inSize, outSize, bufOut, pathSep);
155
result = CPNameConvertFrom(bufIn, inSize, outSize, bufOut, pathSep);
162
*----------------------------------------------------------------------
146
164
* CPNameConvertFrom --
148
166
* Converts a cross-platform name representation into a string for
308
339
size_t bufOutSize, // IN: Size of the output buffer
309
340
char *bufOut) // OUT: Output buffer
311
return CPNameConvertTo(nameIn, bufOutSize, bufOut, '/', NULL);
342
return CPNameConvertTo(nameIn, bufOutSize, bufOut, '/');
339
370
size_t bufOutSize, // IN: Size of the output buffer
340
371
char *bufOut) // OUT: Output buffer
342
return CPNameConvertTo(nameIn, bufOutSize, bufOut, '\\', ":");
373
return CPNameConvertTo(nameIn, bufOutSize, bufOut, '\\');
351
382
* Makes a cross-platform name representation from the input string
352
383
* and writes it into the output buffer.
384
* HGFS convention is to echange names between guest and host in uescaped form.
385
* Both ends perform necessary name escaping according to its own rules
386
* to avoid presenitng invalid file names to OS. Thus the name needs to be unescaped
387
* as a part of conversion to host-independent format.
355
390
* On success, returns the number of bytes used in the
366
401
CPNameConvertTo(char const *nameIn, // IN: Buf to convert
367
402
size_t bufOutSize, // IN: Size of the output buffer
368
403
char *bufOut, // OUT: Output buffer
369
char pathSep, // IN: path separator to use
370
char *ignores) // IN: chars to not transfer to output
404
char pathSep) // IN: path separator to use
372
char const *origOut = bufOut;
406
char *origOut = bufOut;
373
407
char const *endOut = bufOut + bufOutSize;
374
408
size_t cpNameLength = 0;
385
* Copy the string to the output buf, converting all path separators into
386
* '\0' and ignoring the specified characters.
418
/* Copy the string to the output buf, converting all path separators into '\0'. */
388
419
for (; *nameIn != '\0' && bufOut < endOut; nameIn++) {
390
char *currIgnore = ignores;
393
while (*currIgnore != '\0') {
394
if (*nameIn == *currIgnore) {
402
*bufOut = (*nameIn == pathSep) ? '\0' : *nameIn;
406
*bufOut = (*nameIn == pathSep) ? '\0' : *nameIn;
420
*bufOut = (*nameIn == pathSep) ? '\0' : *nameIn;
427
440
while ((cpNameLength >= 1) && (origOut[cpNameLength - 1] == 0)) {
443
cpNameLength = HgfsEscape_Undo(origOut, cpNameLength);
431
445
/* Return number of bytes used */
432
446
return (int) cpNameLength;