|
|
@@ -141,27 +141,87 @@ slapi_ldap_url_parse(const char *url, LDAPURLDesc **ludpp, int require_dn, int *
|
|
|
PR_ASSERT(url);
|
|
|
PR_ASSERT(ludpp);
|
|
|
int rc;
|
|
|
+ const char *url_to_use = url;
|
|
|
+#if defined(USE_OPENLDAP)
|
|
|
+ char *urlescaped = NULL;
|
|
|
+#endif
|
|
|
|
|
|
if (secure) {
|
|
|
*secure = 0;
|
|
|
}
|
|
|
+#if defined(USE_OPENLDAP)
|
|
|
+ /* openldap does not support the non-standard multi host:port URLs supported
|
|
|
+ by mozldap - so we have to fake out openldap - replace all spaces with %20 -
|
|
|
+ replace all but the last colon with %3A
|
|
|
+ Go to the 3rd '/' or to the end of the string (convert only the host:port part) */
|
|
|
+ if (url) {
|
|
|
+ char *p = strstr(url, "://");
|
|
|
+ if (p) {
|
|
|
+ int foundspace = 0;
|
|
|
+ int coloncount = 0;
|
|
|
+ char *lastcolon = NULL;
|
|
|
+ p += 3;
|
|
|
+ for (; *p && (*p != '/'); p++) {
|
|
|
+ if (*p == ' ') {
|
|
|
+ foundspace = 1;
|
|
|
+ }
|
|
|
+ if (*p == ':') {
|
|
|
+ coloncount++;
|
|
|
+ lastcolon = p;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (foundspace) {
|
|
|
+ char *src = NULL, *dest = NULL;
|
|
|
+ /* have to convert url */
|
|
|
+ /* len * 3 is way too much, but acceptable */
|
|
|
+ urlescaped = slapi_ch_calloc(strlen(url) * 3, sizeof(char));
|
|
|
+ dest = urlescaped;
|
|
|
+ /* copy the scheme */
|
|
|
+ src = strstr(url, "://");
|
|
|
+ src += 3;
|
|
|
+ memcpy(dest, url, src-url);
|
|
|
+ dest += (src-url);
|
|
|
+ /* we have to convert all spaces to %20 - we have to convert
|
|
|
+ all colons except the last one to %3A */
|
|
|
+ for (; *src; ++src) {
|
|
|
+ if (src < p) {
|
|
|
+ if (*src == ' ') {
|
|
|
+ memcpy(dest, "%20", 3);
|
|
|
+ dest += 3;
|
|
|
+ } else if ((coloncount > 1) && (*src == ':') && (src != lastcolon)) {
|
|
|
+ memcpy(dest, "%3A", 3);
|
|
|
+ dest += 3;
|
|
|
+ } else {
|
|
|
+ *dest++ = *src;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ *dest++ = *src;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *dest = '\0';
|
|
|
+ url_to_use = urlescaped;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
#if defined(HAVE_LDAP_URL_PARSE_NO_DEFAULTS)
|
|
|
- rc = ldap_url_parse_no_defaults(url, ludpp, require_dn);
|
|
|
+ rc = ldap_url_parse_no_defaults(url_to_use, ludpp, require_dn);
|
|
|
if (!rc && *ludpp && secure) {
|
|
|
*secure = (*ludpp)->lud_options & LDAP_URL_OPT_SECURE;
|
|
|
}
|
|
|
#else /* openldap */
|
|
|
#if defined(HAVE_LDAP_URL_PARSE_EXT) && defined(LDAP_PVT_URL_PARSE_NONE) && defined(LDAP_PVT_URL_PARSE_NOEMPTY_DN)
|
|
|
- rc = ldap_url_parse_ext(url, ludpp, require_dn ? LDAP_PVT_URL_PARSE_NONE : LDAP_PVT_URL_PARSE_NOEMPTY_DN);
|
|
|
+ rc = ldap_url_parse_ext(url_to_use, ludpp, require_dn ? LDAP_PVT_URL_PARSE_NONE : LDAP_PVT_URL_PARSE_NOEMPTY_DN);
|
|
|
#else
|
|
|
- rc = ldap_url_parse(url, ludpp);
|
|
|
+ rc = ldap_url_parse(url_to_use, ludpp);
|
|
|
if ((rc || !*ludpp) && !require_dn) { /* failed - see if failure was due to missing dn */
|
|
|
- size_t len = strlen(url);
|
|
|
+ size_t len = strlen(url_to_use);
|
|
|
/* assume the url is just scheme://host:port[/] - add the empty string
|
|
|
as the DN (adding a trailing / first if needed) and try to parse
|
|
|
again
|
|
|
*/
|
|
|
- char *urlcopy = slapi_ch_smprintf("%s%s%s", url, (url[len-1] == '/' ? "" : "/"), "");
|
|
|
+ char *urlcopy = slapi_ch_smprintf("%s%s%s", url_to_use, (url_to_use[len-1] == '/' ? "" : "/"), "");
|
|
|
if (*ludpp) {
|
|
|
ldap_free_urldesc(*ludpp); /* free the old one, if any */
|
|
|
}
|
|
|
@@ -177,6 +237,35 @@ slapi_ldap_url_parse(const char *url, LDAPURLDesc **ludpp, int require_dn, int *
|
|
|
}
|
|
|
#endif /* openldap */
|
|
|
|
|
|
+#if defined(USE_OPENLDAP)
|
|
|
+ if (urlescaped && (*ludpp) && (*ludpp)->lud_host) {
|
|
|
+ /* have to unescape lud_host - can unescape in place */
|
|
|
+ char *p = strstr((*ludpp)->lud_host, "://");
|
|
|
+ if (p) {
|
|
|
+ char *dest = NULL;
|
|
|
+ p += 3;
|
|
|
+ dest = p;
|
|
|
+ /* up to the first '/', unescape the host */
|
|
|
+ for (; *p && (*p != '/'); p++) {
|
|
|
+ if (!strncmp(p, "%20", 3)) {
|
|
|
+ *dest++ = ' ';
|
|
|
+ p += 2;
|
|
|
+ } else if (!strncmp(p, "%3A", 3)) {
|
|
|
+ *dest++ = ':';
|
|
|
+ p += 2;
|
|
|
+ } else {
|
|
|
+ *dest++ = *p;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* just copy the remainder of the host, if any */
|
|
|
+ while (*p) {
|
|
|
+ *dest++ = *p++;
|
|
|
+ }
|
|
|
+ *dest = '\0';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ slapi_ch_free_string(&urlescaped);
|
|
|
+#endif
|
|
|
return rc;
|
|
|
}
|
|
|
|