Index: client/smbspool.c =================================================================== --- client/smbspool.c (revision 23407) +++ client/smbspool.c (working copy) @@ -47,6 +47,7 @@ static struct cli_state *smb_complete_connection(const char *, const char *,int , const char *, const char *, const char *, const char *, int); static struct cli_state *smb_connect(const char *, const char *, int, const char *, const char *, const char *, const char *); static int smb_print(struct cli_state *, char *, FILE *); +static char * uri_unescape_alloc(const char *); /* @@ -62,8 +63,9 @@ int port; /* Port number */ char uri[1024], /* URI */ *sep, /* Pointer to separator */ + *tmp, *tmp2, /* Temp pointers to do escaping */ *password; /* Password */ - const char *username, /* Username */ + char *username, /* Username */ *server, /* Server name */ *printer; /* Printer name */ const char *workgroup; /* Workgroup */ @@ -152,19 +154,24 @@ if ((sep = strrchr_m(uri, '@')) != NULL) { - username = uri + 6; + tmp = uri + 6; *sep++ = '\0'; + /* username is in tmp */ + server = sep; /* * Extract password as needed... */ - if ((password = strchr_m(username, ':')) != NULL) - *password++ = '\0'; - else + if ((tmp2 = strchr_m(tmp, ':')) != NULL) { + *tmp2++ = '\0'; + password = uri_unescape_alloc(tmp2); + } else { password = null_str; + } + username = uri_unescape_alloc(tmp); } else { @@ -173,16 +180,18 @@ server = uri + 6; } - if ((sep = strchr_m(server, '/')) == NULL) + tmp = server; + + if ((sep = strchr_m(tmp, '/')) == NULL) { fputs("ERROR: Bad URI - need printer name!\n", stderr); return (1); } *sep++ = '\0'; - printer = sep; + tmp2 = sep; - if ((sep = strchr_m(printer, '/')) != NULL) + if ((sep = strchr_m(tmp2, '/')) != NULL) { /* * Convert to smb://[username:password@]workgroup/server/printer... @@ -190,12 +199,15 @@ *sep++ = '\0'; - workgroup = server; - server = printer; - printer = sep; + workgroup = uri_unescape_alloc(tmp); + server = uri_unescape_alloc(tmp2); + printer = uri_unescape_alloc(sep); } - else + else { workgroup = NULL; + server = uri_unescape_alloc(tmp); + printer = uri_unescape_alloc(tmp2); + } if ((sep = strrchr_m(server, ':')) != NULL) { @@ -203,7 +215,7 @@ port=atoi(sep); } - else + else port=0; @@ -588,3 +600,38 @@ else return (0); } + +static char *uri_unescape_alloc(const char *uritok) +{ + char *t, *ret; + const char *p; + long int val; + char eval[3]; + + ret = (char *)SMB_MALLOC(strlen(uritok)+1); + + if (!ret) return NULL; + + eval[2] = '\0'; + + for (p = uritok, t = ret; *p; p++, t++) { + if (*p == '%') { /* unescape hex */ + p++; + eval[0] = *p; + p++; + eval[1] = *p; + val = strtol(eval, NULL, 16); + if ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE) { + SAFE_FREE(ret); + return NULL; + } + *t = (char)val; + } else { + *t = *p; + } + } + + *t = '\0'; /*terminate*/ + + return ret; +}