+
+/**
+ * Tries to convert an URI to a local (UTF-8-encoded) file path.
+ * @param url URI to convert
+ * @return NULL on error, a nul-terminated string otherwise
+ * (use free() to release it)
+ */
+char *make_path (const char *url)
+{
+ char *ret = NULL;
+ char *end;
+
+ char *path = strstr (url, "://");
+ if (path == NULL)
+ return NULL; /* unsupported scheme or invalid syntax */
+
+ end = memchr (url, '/', path - url);
+ size_t schemelen = ((end != NULL) ? end : path) - url;
+ path += 3; /* skip "://" */
+
+#ifdef WIN32
+
+ /* skip leading slash before disk drive
+ * when format is file:///C:/path/file.ext
+ */
+ if (schemelen == 4 && !strncasecmp (url, "file", 4))
+ {
+ char* search = strstr (path, ":/");
+ if( search && *path == '/' && search == path+2 )
+ path++;
+ }
+
+#endif
+
+ /* Remove HTML anchor if present */
+ end = strchr (path, '#');
+ if (end)
+ path = strndup (path, end - path);
+ else
+ path = strdup (path);
+ if (unlikely(path == NULL))
+ return NULL; /* boom! */
+
+ /* Decode path */
+ decode_URI (path);
+
+ if (schemelen == 4 && !strncasecmp (url, "file", 4))
+ {
+#if (DIR_SEP_CHAR != '/')
+ for (char *p = strchr (path, '/'); p; p = strchr (p, '/'))
+ *p++ = DIR_SEP_CHAR;
+#endif
+
+#ifdef WIN32
+
+ /* check for disk drive in the form 'C:\...' */
+ char* search = strstr (path, ":"DIR_SEP);
+ if( search && search == path+1 )
+ return path;
+
+ if (*path && asprintf (&ret, "\\\\%s", path) == -1)
+ ret = NULL;
+
+ goto out;
+#else
+ if (*path == DIR_SEP_CHAR)
+ return path;
+
+ /* Local path disguised as a remote one (MacOS X) */
+ if (!strncasecmp (path, "localhost"DIR_SEP, 10))
+ {
+ memmove (path, path + 9, strlen (path + 9) + 1);
+ return path;
+ }
+#endif
+ }
+ else
+ if (schemelen == 2 && !strncasecmp (url, "fd", 2))
+ {
+ int fd = strtol (path, &end, 0);
+
+ if (*end)
+ goto out;
+
+#ifndef WIN32
+ switch (fd)
+ {
+ case 0:
+ ret = strdup ("/dev/stdin");
+ break;
+ case 1:
+ ret = strdup ("/dev/stdout");
+ break;
+ case 2:
+ ret = strdup ("/dev/strerr");
+ break;
+ default:
+ if (asprintf (&ret, "/dev/fd/%d", fd) == -1)
+ ret = NULL;
+ }
+#else
+ if (fd < 2)
+ ret = strdup ("CON");
+ else
+ ret = NULL;
+#endif
+ }
+
+out:
+ free (path);
+ return ret; /* unknown scheme */
+}