diff --git a/src/uri.c b/src/uri.c
index 4a2c61a421d56021ef45b969a518a0e5e06fff9e..926dbd429317e83eea1a988eef58a5c91620b482 100644
--- a/src/uri.c
+++ b/src/uri.c
@@ -9,21 +9,18 @@
 #include <errno.h>
 #include <limits.h>
 
-bool
-lkt_uri_from(struct lkt_uri *ret, char *const str)
+static inline char *
+__prefix(char *str, struct lkt_uri *ret)
 {
-    char *val, *endptr;
+    char *val;
     size_t len;
-    long id;
-
-    if (ret == NULL || str == NULL)
-        return false;
 
-    len = strlen(str);
+    if (!str || !ret)
+        return NULL;
 
-    // The minimal uri is id://1 which is a 6 characters long
-    if (len <= 5 * sizeof(char))
-        return false;
+    /* The minimal uri is id://1 which is a 6 characters long */
+    if ((len = strlen(str)) <= 5)
+        return NULL;
 
     if (STR_NMATCH(str, "id", 2)) {
         ret->type = uri_id;
@@ -47,35 +44,70 @@ lkt_uri_from(struct lkt_uri *ret, char *const str)
         ret->type = uri_query;
         val = str + 5;
     } else
-        return false;
+        return NULL;
 
-    // No place for the '://' separator
+    /* No place for the '://' separator */
     if (len - (val - str) < 3)
-        return false;
+        return NULL;
 
     val += 3;
+    ret->value = val;
+    return val;
+}
 
-    if (ret->type == uri_id) {
-        id = strtol(val, &endptr, 10);
+bool
+lkt_uri_from(struct lkt_uri *ret, char *const str)
+{
+    if (NULL == __prefix(str, ret))
+        return false;
 
-        if ((errno == ERANGE && (id == LONG_MAX || id == LONG_MIN))
-            || (errno != 0 && id == 0) || endptr == str)
+    if (ret->type == uri_id) {
+        errno = 0;
+        ret->id = strtol(ret->value, NULL, 10);  /* Override */
+        if (errno != 0)
             return false;
+    }
 
-        ret->value = calloc(1, sizeof(int));
+    ret->_allocated = false;
+    return true;
+}
 
-        if (ret->value == NULL)
-            return false;
+bool
+lkt_uri_from_list(struct lkt_uri *ret, char **list)
+{
+    int i;
+    if (!list || !list[0])
+        return false;
 
-        *(int *) ret->value = id;
-        ret->_allocated = true;
-    }
+    if (!list[1])
+        return lkt_uri_from(ret, list[0]);
+
+    if (NULL == __prefix(list[0], ret))
+        return false;
+
+    /* Nothing after the separator */
+    if ('\0' == * (char *) ret->value)
+        return false;
+
+    char *buffer = (char *) malloc(sizeof(char) * (strlen(ret->value) + 1));
+    if (NULL == buffer)
+        return false;
+    strcpy(buffer, ret->value);
+
+    for (i = 1; list[i]; ++i) {
+        char *new = realloc(buffer, strlen(buffer) + 1 + strlen(list[i]) + 1);
+        if (NULL == new) {
+            free(buffer);
+            return false;
+        }
 
-    else {
-        ret->_allocated = false;
-        ret->value = val;
+        buffer = new;
+        strcat(buffer, " ");
+        strcat(buffer, list[i]);
     }
 
+    ret->value = buffer;
+    ret->_allocated = true;
     return true;
 }
 
@@ -110,8 +142,8 @@ __lkt_to_str(struct lkt_uri *uri, char *ret, size_t len)
         safe_snprintf(ret, len, "search=%s", (char *) uri->value);
         break;
     default:
-        LOG_ERROR("URI", "type %d may not be supported by kurisu, "
-                  "generate an error", uri->type);
+        LOG_WARN("URI", "type %d may not be supported by kurisu, "
+                 "generate an error", uri->type);
         return 1;
     }