return ret;
}
+static void
+rspamd_url_shift (struct rspamd_url *uri, gsize nlen,
+ enum http_parser_url_fields field)
+{
+ guint old_shift, shift = 0;
+
+ /* Shift remaining data */
+ switch (field) {
+ case UF_SCHEMA:
+ if (nlen >= uri->protocollen) {
+ return;
+ }
+ else {
+ shift = uri->protocollen - nlen;
+ }
+
+ old_shift = uri->protocollen;
+ uri->protocollen -= shift;
+ memmove (uri->string + uri->protocollen, uri->string + old_shift,
+ uri->urllen - uri->protocollen);
+ break;
+ case UF_HOST:
+ if (nlen >= uri->hostlen) {
+ return;
+ }
+ else {
+ shift = uri->hostlen - nlen;
+ }
+
+ old_shift = uri->hostlen;
+ uri->hostlen -= shift;
+ memmove (uri->host + uri->hostlen, uri->host + old_shift,
+ uri->datalen + uri->querylen + uri->fragmentlen);
+ break;
+ case UF_PATH:
+ if (nlen >= uri->datalen) {
+ return;
+ }
+ else {
+ shift = uri->datalen - nlen;
+ }
+
+ old_shift = uri->datalen;
+ uri->datalen -= shift;
+ memmove (uri->data + uri->datalen, uri->data + old_shift,
+ uri->querylen + uri->fragmentlen);
+ break;
+ case UF_QUERY:
+ if (nlen >= uri->querylen) {
+ return;
+ }
+ else {
+ shift = uri->querylen - nlen;
+ }
+
+ old_shift = uri->querylen;
+ uri->querylen -= shift;
+ memmove (uri->query + uri->querylen, uri->query + old_shift,
+ uri->fragmentlen);
+ break;
+ case UF_FRAGMENT:
+ if (nlen >= uri->fragmentlen) {
+ return;
+ }
+ else {
+ shift = uri->fragmentlen - nlen;
+ }
+
+ uri->fragmentlen -= shift;
+ break;
+ default:
+ break;
+ }
+
+ /* Now adjust lengths and offsets */
+ switch (field) {
+ case UF_SCHEMA:
+ if (uri->userlen > 0) {
+ uri->user -= shift;
+ uri->userlen -= shift;
+ }
+ if (uri->hostlen > 0) {
+ uri->host -= shift;
+ uri->hostlen -= shift;
+ }
+ /* Go forward */
+ case UF_HOST:
+ if (uri->datalen > 0) {
+ uri->data -= shift;
+ uri->datalen -= shift;
+ }
+ /* Go forward */
+ case UF_PATH:
+ if (uri->querylen > 0) {
+ uri->query -= shift;
+ uri->querylen -= shift;
+ }
+ /* Go forward */
+ case UF_QUERY:
+ if (uri->fragmentlen > 0) {
+ uri->fragment -= shift;
+ uri->fragmentlen -= shift;
+ }
+ /* Go forward */
+ case UF_FRAGMENT:
+ default:
+ uri->urllen -= shift;
+ break;
+ }
+}
+
enum uri_errno
rspamd_url_parse (struct rspamd_url *uri, gchar *uristring, gsize len,
rspamd_mempool_t *pool)
gchar *p, *comp;
const gchar *end;
guint i, complen, ret;
+ gsize unquoted_len = 0;
gint state = 0;
const struct {
uri->string = p;
uri->urllen = len;
- if (uri->userlen == 0) {
- rspamd_decode_url (uri->string, uri->string, len);
- }
- else {
- rspamd_decode_url (uri->string, uri->string, uri->protocollen);
- rspamd_decode_url (uri->host, uri->host, uri->hostlen);
-
- if (uri->datalen) {
- rspamd_decode_url (uri->data, uri->data, uri->datalen);
- }
- if (uri->querylen) {
- rspamd_decode_url (uri->query, uri->query, uri->querylen);
- }
- if (uri->fragmentlen) {
- rspamd_decode_url (uri->fragment, uri->fragment, uri->fragmentlen);
- }
+ unquoted_len = rspamd_decode_url (uri->string,
+ uri->string,
+ uri->protocollen);
+ rspamd_url_shift (uri, unquoted_len, UF_SCHEMA);
+ unquoted_len = rspamd_decode_url (uri->host, uri->host, uri->hostlen);
+ rspamd_url_shift (uri, unquoted_len, UF_HOST);
+
+ if (uri->datalen) {
+ unquoted_len = rspamd_decode_url (uri->data, uri->data, uri->datalen);
+ rspamd_url_shift (uri, unquoted_len, UF_PATH);
+ }
+ if (uri->querylen) {
+ unquoted_len = rspamd_decode_url (uri->query,
+ uri->query,
+ uri->querylen);
+ rspamd_url_shift (uri, unquoted_len, UF_QUERY);
+ }
+ if (uri->fragmentlen) {
+ unquoted_len = rspamd_decode_url (uri->fragment,
+ uri->fragment,
+ uri->fragmentlen);
+ rspamd_url_shift (uri, unquoted_len, UF_FRAGMENT);
}
rspamd_str_lc (uri->string, uri->protocollen);