]> sjero.net Git - wget/blobdiff - src/url.c
Add support for file names longer than MAX_FILE.
[wget] / src / url.c
index e44dfcd2313282426d68e5b5e8591682d7296df7..4a1c9f101278cadba3e08cf5d5f777e0dee6508d 100644 (file)
--- a/src/url.c
+++ b/src/url.c
@@ -1361,6 +1361,7 @@ UWC,  C,  C,  C,   C,  C,  C,  C,   /* NUL SOH STX ETX  EOT ENQ ACK BEL */
    query, normally '?'.  Since Windows cannot handle '?' as part of
    file name, we use '@' instead there.  */
 #define FN_QUERY_SEP (opt.restrict_files_os != restrict_windows ? '?' : '@')
+#define FN_QUERY_SEP_STR (opt.restrict_files_os != restrict_windows ? "?" : "@")
 
 /* Quote path element, characters in [b, e), as file name, and append
    the quoted string to DEST.  Each character is quoted as per
@@ -1494,22 +1495,28 @@ append_dir_structure (const struct url *u, struct growable *dest)
     }
 }
 
-/* Return a unique file name that matches the given URL as good as
+/* Return a unique file name that matches the given URL as well as
    possible.  Does not create directories on the file system.  */
 
 char *
 url_file_name (const struct url *u, char *replaced_filename)
 {
   struct growable fnres;        /* stands for "file name result" */
+  struct growable temp_fnres;
 
   const char *u_file;
-  char *fname, *unique;
+  char *fname, *unique, *fname_len_check;
   const char *index_filename = "index.html"; /* The default index file is index.html */
+  size_t max_length;
 
   fnres.base = NULL;
   fnres.size = 0;
   fnres.tail = 0;
 
+  temp_fnres.base = NULL;
+  temp_fnres.size = 0;
+  temp_fnres.tail = 0;
+
   /* If an alternative index file was defined, change index_filename */
   if (opt.default_page)
     index_filename = opt.default_page;
@@ -1555,33 +1562,60 @@ url_file_name (const struct url *u, char *replaced_filename)
 
   if (!replaced_filename)
     {
-      /* Add the file name. */
-      if (fnres.tail)
-       append_char ('/', &fnres);
+      /* Create the filename. */
       u_file = *u->file ? u->file : index_filename;
-      append_uri_pathel (u_file, u_file + strlen (u_file), false, &fnres);
 
-      /* Append "?query" to the file name, even if empty */
+      /* Append "?query" to the file name, even if empty,
+       * and create fname_len_check. */
       if (u->query)
-       {
-         append_char (FN_QUERY_SEP, &fnres);
-         append_uri_pathel (u->query, u->query + strlen (u->query),
-                            true, &fnres);
-       }
+        fname_len_check = concat_strings (u_file, FN_QUERY_SEP_STR, u->query, NULL);
+      else
+        fname_len_check = strdupdelim (u_file, u_file + strlen (u_file));
     }
   else
     {
-      if (fnres.tail)
-       append_char ('/', &fnres);
       u_file = replaced_filename;
-      append_uri_pathel (u_file, u_file + strlen (u_file), false, &fnres);
+      fname_len_check = strdupdelim (u_file, u_file + strlen (u_file));
     }
 
+  append_uri_pathel (fname_len_check,
+    fname_len_check + strlen (fname_len_check), false, &temp_fnres);
+
+  /* Zero-terminate the temporary file name. */
+  append_char ('\0', &temp_fnres);
+
+  /* Check that the length of the file name is acceptable. */
+  max_length = get_max_length (fnres.base, fnres.tail, _PC_NAME_MAX) - CHOMP_BUFFER;
+  if (max_length > 0 && strlen (temp_fnres.base) > max_length)
+    {
+      logprintf (LOG_NOTQUIET, "The name is too long, %lu chars total.\n",
+          (unsigned long) strlen (temp_fnres.base));
+      logprintf (LOG_NOTQUIET, "Trying to shorten...\n");
+
+      /* Shorten the file name. */
+      temp_fnres.base[max_length] = '\0';
+
+      logprintf (LOG_NOTQUIET, "New name is %s.\n", temp_fnres.base);
+    }
+
+  free (fname_len_check);
+
+  /* The filename has already been 'cleaned' by append_uri_pathel() above.  So,
+   * just append it. */
+  if (fnres.tail)
+    append_char ('/', &fnres);
+  append_string (temp_fnres.base, &fnres);
+
   /* Zero-terminate the file name. */
   append_char ('\0', &fnres);
 
   fname = fnres.base;
 
+  /* Make a final check that the path length is acceptable? */
+  /* TODO: check fnres.base for path length problem */
+
+  free (temp_fnres.base);
+
   /* Check the cases in which the unique extensions are not used:
      1) Clobbering is turned off (-nc).
      2) Retrieval with regetting.