summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/libsmb/libsmbclient.c87
1 files changed, 85 insertions, 2 deletions
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index 440527cd9d..916e388fe0 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -52,6 +52,82 @@ extern BOOL in_client;
*/
static int smbc_initialized = 0;
+static int
+hex2int( unsigned int _char )
+{
+ if ( _char >= 'A' && _char <='F')
+ return _char - 'A' + 10;
+ if ( _char >= 'a' && _char <='f')
+ return _char - 'a' + 10;
+ if ( _char >= '0' && _char <='9')
+ return _char - '0';
+ return -1;
+}
+
+static void
+decode_urlpart(char *segment)
+{
+ int old_length = strlen(segment);
+ int new_length = 0;
+ int new_length2 = 0;
+ int i = 0;
+ pstring new_segment;
+ char *new_usegment = 0;
+
+ if ( !old_length ) {
+ return;
+ }
+
+ /* make a copy of the old one */
+ new_usegment = (char*)malloc( old_length * 3 + 1 );
+
+ while( i < old_length ) {
+ int bReencode = False;
+ unsigned char character = segment[ i++ ];
+ if ((character <= ' ') || (character > 127))
+ bReencode = True;
+
+ new_usegment [ new_length2++ ] = character;
+ if (character == '%' ) {
+ int a = i+1 < old_length ? hex2int( segment[i] ) : -1;
+ int b = i+1 < old_length ? hex2int( segment[i+1] ) : -1;
+ if ((a == -1) || (b == -1)) { /* Only replace if sequence is valid */
+ /* Contains stray %, make sure to re-encode! */
+ bReencode = True;
+ } else {
+ /* Valid %xx sequence */
+ character = a * 16 + b; /* Replace with value of %dd */
+ if (!character)
+ break; /* Stop at %00 */
+
+ new_usegment [ new_length2++ ] = (unsigned char) segment[i++];
+ new_usegment [ new_length2++ ] = (unsigned char) segment[i++];
+ }
+ }
+ if (bReencode) {
+ unsigned int c = character / 16;
+ new_length2--;
+ new_usegment [ new_length2++ ] = '%';
+
+ c += (c > 9) ? ('A' - 10) : '0';
+ new_usegment[ new_length2++ ] = c;
+
+ c = character % 16;
+ c += (c > 9) ? ('A' - 10) : '0';
+ new_usegment[ new_length2++ ] = c;
+ }
+
+ new_segment [ new_length++ ] = character;
+ }
+ new_segment [ new_length ] = 0;
+
+ /* this assumes (very safely) that removing %aa sequences
+ only shortens the string */
+ strncpy(segment, new_segment, old_length);
+
+ free(new_usegment);
+}
+
/*
* Function to parse a path and turn it into components
*
@@ -97,7 +173,7 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
p += 2; /* Skip the // or \\ */
if (*p == (char)0)
- return 0;
+ goto decoding;
if (*p == '/') {
@@ -158,7 +234,7 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
}
- if (*p == (char)0) return 0; /* That's it ... */
+ if (*p == (char)0) goto decoding; /* That's it ... */
if (!next_token(&p, share, "/", sizeof(fstring))) {
@@ -170,6 +246,13 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
all_string_sub(path, "/", "\\", 0);
+ decoding:
+ decode_urlpart(path);
+ decode_urlpart(server);
+ decode_urlpart(share);
+ decode_urlpart(user);
+ decode_urlpart(password);
+
return 0;
}