opkg: encode archive filenames while constructing download URLs
authorJo-Philipp Wich <jo@mein.io>
Thu, 7 Dec 2017 10:43:02 +0000 (11:43 +0100)
committerJo-Philipp Wich <jo@mein.io>
Thu, 7 Dec 2017 12:02:37 +0000 (13:02 +0100)
Various web servers, namely Amazon S3 ones, have problems handling requests
to URLs with a literal "+" in the path component.

According to the RFC 3986 "+" is a reserved char and its purpose is
delimiting. When used in a file name it should be encoded.

Use the new urlencode_path() helper to encode the path component before
constructing the final download URL.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Tested-by: Rafał Miłecki <rafal@milecki.pl>
libopkg/opkg.c
libopkg/opkg_download.c

index d994bd19888c98aa6e95fbcb1d29b94bad17d1bc..aba6364c8fa1906fb5b25be87052d5453d295760 100644 (file)
@@ -260,7 +260,7 @@ opkg_install_package(const char *package_name,
        /* download package and dependencies */
        for (i = 0; i < deps->len; i++) {
                pkg_t *pkg;
        /* download package and dependencies */
        for (i = 0; i < deps->len; i++) {
                pkg_t *pkg;
-               char *url;
+               char *url, *urlencoded_path;
 
                pkg = deps->pkgs[i];
                if (pkg_get_string(pkg, PKG_LOCAL_FILENAME))
 
                pkg = deps->pkgs[i];
                if (pkg_get_string(pkg, PKG_LOCAL_FILENAME))
@@ -276,8 +276,9 @@ opkg_install_package(const char *package_name,
                }
 
                filename = pkg_get_string(pkg, PKG_FILENAME);
                }
 
                filename = pkg_get_string(pkg, PKG_FILENAME);
-
-               sprintf_alloc(&url, "%s/%s", pkg->src->value, filename);
+               urlencoded_path = urlencode_path(filename);
+               sprintf_alloc(&url, "%s/%s", pkg->src->value, urlencoded_path);
+               free(urlencoded_path);
 
                /* Get the filename part, without any directory */
                stripped_filename = strrchr(filename, '/');
 
                /* Get the filename part, without any directory */
                stripped_filename = strrchr(filename, '/');
index 36db231f30f578a03f54d1899d23d325eeab1184..e57d053a5897c861e671489e0f521e60f7a5925c 100644 (file)
@@ -186,6 +186,7 @@ int opkg_download_pkg(pkg_t * pkg, const char *dir)
        char *url;
        char *local_filename;
        char *stripped_filename;
        char *url;
        char *local_filename;
        char *stripped_filename;
+       char *urlencoded_path;
        char *filename;
 
        if (pkg->src == NULL) {
        char *filename;
 
        if (pkg->src == NULL) {
@@ -204,7 +205,9 @@ int opkg_download_pkg(pkg_t * pkg, const char *dir)
                return -1;
        }
 
                return -1;
        }
 
-       sprintf_alloc(&url, "%s/%s", pkg->src->value, filename);
+       urlencoded_path = urlencode_path(filename);
+       sprintf_alloc(&url, "%s/%s", pkg->src->value, urlencoded_path);
+       free(urlencoded_path);
 
        /* The filename might be something like
           "../../foo.opk". While this is correct, and exactly what we
 
        /* The filename might be something like
           "../../foo.opk". While this is correct, and exactly what we