- if (asprintf (&buf, "file:///%c:", path[0]) == -1)
- buf = NULL;
- path += 2;
- }
- else
-#endif
- if (!strncmp (path, "\\\\", 2))
- { /* Windows UNC paths */
-#ifndef WIN32
- /* \\host\share\path -> smb://host/share/path */
- if (strchr (path + 2, '\\') != NULL)
- { /* Convert antislashes to slashes */
- char *dup = strdup (path);
- if (dup == NULL)
- return NULL;
- for (size_t i = 2; dup[i]; i++)
- if (dup[i] == '\\')
- dup[i] = DIR_SEP_CHAR;
-
- char *ret = make_URI (dup);
- free (dup);
- return ret;
- }
-# define SMB_SCHEME "smb"
-#else
- /* \\host\share\path -> file://host/share/path */
-# define SMB_SCHEME "file"
-#endif
- size_t hostlen = strcspn (path + 2, DIR_SEP);
-
- buf = malloc (sizeof (SMB_SCHEME) + 3 + hostlen);
- if (buf != NULL)
- snprintf (buf, sizeof (SMB_SCHEME) + 3 + hostlen,
- SMB_SCHEME"://%s", path + 2);
- path += 2 + hostlen;
- }
- else
- if (path[0] != DIR_SEP_CHAR)
- { /* Relative path: prepend the current working directory */
- char cwd[PATH_MAX];
-
- if (getcwd (cwd, sizeof (cwd)) == NULL) /* FIXME: UTF8? */
- return NULL;
- if (asprintf (&buf, "%s/%s", cwd, path) == -1)
- return NULL;
- char *ret = make_URI (buf);
- free (buf);
- return ret;
- }
- else
- buf = strdup ("file://");
- if (buf == NULL)
- return NULL;
-
- assert (path[0] == DIR_SEP_CHAR);
-
- /* Absolute file path */
- for (const char *ptr = path + 1;; ptr++)
- {
- size_t len = strcspn (ptr, DIR_SEP);
- char *component = encode_URI_bytes (ptr, len);
- if (component == NULL)
- {
- free (buf);
- return NULL;
- }
- char *uri;
- int val = asprintf (&uri, "%s/%s", buf, component);
- free (component);
- free (buf);
- if (val == -1)
- return NULL;
- buf = uri;
- ptr += len;
- if (*ptr == '\0')
- return buf;
- }
-}
-
-/**
- * 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 "://" */
-
- /* 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
- if (*path == DIR_SEP_CHAR)
- return path;
-
- /* Local path disguised as a remote one (MacOS X) */
- if (!strncasecmp (path, "localhost"DIR_SEP, 10))