/* TODO: not a proper URI parser */ int uri_parse(const char *uri, struct uri *parsed, const struct uri *defaults) { const char *pnt, *slash, *colon; parsed->port = -1; parsed->host = NULL; parsed->path = NULL; parsed->scheme = NULL; pnt = strstr(uri, "://"); if (pnt) { parsed->scheme = ne_strndup(uri, pnt - uri); pnt += 3; /* start of hostport segment */ } else { pnt = uri; if (defaults && defaults->scheme != NULL) { parsed->scheme = ne_strdup(defaults->scheme); } } slash = strchr(pnt, '/'); colon = strchr(pnt, ':'); if (slash == NULL) { parsed->path = ne_strdup("/"); if (colon == NULL) { if (defaults) parsed->port = defaults->port; parsed->host = ne_strdup(pnt); } else { parsed->port = atoi(colon+1); parsed->host = ne_strndup(pnt, colon - pnt); } } else { if (colon == NULL || colon > slash) { /* No port segment */ if (defaults) parsed->port = defaults->port; parsed->host = ne_strndup(pnt, slash - pnt); } else { /* Port segment */ parsed->port = atoi(colon + 1); parsed->host = ne_strndup(pnt, colon - pnt); } parsed->path = ne_strdup(slash); } return 0; }
char *ne_path_parent(const char *uri) { size_t len = strlen(uri); const char *pnt = uri + len - 1; /* skip trailing slash (parent of "/foo/" is "/") */ if (pnt >= uri && *pnt == '/') pnt--; /* find previous slash */ while (pnt > uri && *pnt != '/') pnt--; if (pnt < uri || (pnt == uri && *pnt != '/')) return NULL; return ne_strndup(uri, pnt - uri + 1); }
int ne_uri_parse(const char *uri, ne_uri *parsed) { const char *s; #if 1 /*const*/ char *p; //SINA_IMS #else const char *p; #endif memset(parsed, 0, sizeof *parsed); p = s = uri; /* => s = p = URI-reference */ if (uri_lookup(*p) & URI_ALPHA) { while (uri_lookup(*p) & URI_SCHEME) p++; if (*p == ':') { parsed->scheme = ne_strndup(uri, p - s); s = p + 1; } } /* => s = heir-part, or s = relative-part */ if (s[0] == '/' && s[1] == '/') { const char *pa; /* => s = "//" authority path-abempty (from expansion of * either heir-part of relative-part) */ /* authority = [ userinfo "@" ] host [ ":" port ] */ s = pa = s + 2; /* => s = authority */ while (*pa != '/' && *pa != '\0') pa++; /* => pa = path-abempty */ p = s; while (p < pa && uri_lookup(*p) & URI_USERINFO) p++; if (*p == '@') { parsed->userinfo = ne_strndup(s, p - s); s = p + 1; } /* => s = host */ if (s[0] == '[') { p = s + 1; while (*p != ']' && p < pa) p++; if (p == pa || (p + 1 != pa && p[1] != ':')) { /* Ill-formed IP-literal. */ return -1; } p++; /* => p = colon */ } else { /* Find the colon. */ p = pa; while (*p != ':' && p > s) p--; } if (p == s) { p = pa; /* No colon; => p = path-abempty */ } else if (p + 1 != pa) { /* => p = colon */ parsed->port = atoi(p + 1); } parsed->host = ne_strndup(s, p - s); s = pa; if (*s == '\0') { s = "/"; /* FIXME: scheme-specific. */ } } /* => s = path-abempty / path-absolute / path-rootless * / path-empty / path-noscheme */ p = s; while (uri_lookup(*p) & URI_SEGCHAR) p++; /* => p = [ "?" query ] [ "#" fragment ] */ parsed->path = ne_strndup(s, p - s); if (*p != '\0') { s = p++; while (uri_lookup(*p) & URI_QUERY) p++; /* => p = [ "#" fragment ] */ /* => s = [ "?" query ] [ "#" fragment ] */ if (*s == '?') { /*@FIXME: this is ugly hack. some sina service has not yet supported utf8, we have to convert to gbk before url parse, therefore, there may exist character < 0. For this case, treat s as query part */ #ifdef SINA_IMS if( *p < 0 ){ parsed->query = ne_strndup(s + 1,strlen(s) -1 ); *p = '\0'; }else{ parsed->query = ne_strndup(s + 1, p - s - 1); } #else parsed->query = ne_strndup(s + 1, p - s - 1); #endif if (*p != '\0') { s = p++; while (uri_lookup(*p) & URI_FRAGMENT) p++; } } /* => p now points to the next character after the * URI-reference; which should be the NUL byte. */ if (*s == '#') { parsed->fragment = ne_strndup(s + 1, p - s - 1); } else if (*p || *s != '?') { return -1; } } return 0; }
/* Returns a malloc-allocate version of IA5 string AS. Really only * here to prevent char * vs unsigned char * type mismatches without * losing all hope at type-safety. */ static char *dup_ia5string(const ASN1_IA5STRING *as) { unsigned char *data = as->data; return ne_strndup((char *)data, as->length); }