Commit 12bb308c authored by Dan Fandrich's avatar Dan Fandrich
Browse files

Factored out some code into a few independent functions

parent 733f794c
Loading
Loading
Loading
Loading
+105 −75
Original line number Diff line number Diff line
@@ -168,6 +168,7 @@ static int vms_show = 0;

static const char *msdosify(const char *);
static char *rename_if_dos_device_name(char *);
static char *sanitize_dos_name(char *);

#ifndef S_ISCHR
#  ifdef S_IFCHR
@@ -4091,6 +4092,83 @@ static bool stdin_upload(const char *uploadfile)
                curlx_strequal(uploadfile, "."));
}

/* Adds the file name to the URL if it doesn't already have one.
 * url will be freed before return if the returned pointer is different
 */
static char *add_file_name_to_url(CURL *curl, char *url, const char *filename)
{
  /* If no file name part is given in the URL, we add this file name */
  char *ptr=strstr(url, "://");
  if(ptr)
    ptr+=3;
  else
    ptr=url;
  ptr = strrchr(ptr, '/');
  if(!ptr || !strlen(++ptr)) {
    /* The URL has no file name part, add the local file name. In order
       to be able to do so, we have to create a new URL in another
       buffer.*/

    /* We only want the part of the local path that is on the right
       side of the rightmost slash and backslash. */
    const char *filep = strrchr(filename, '/');
    char *file2 = strrchr(filep?filep:filename, '\\');
    char *encfile;

    if(file2)
      filep = file2+1;
    else if(filep)
      filep++;
    else
      filep = filename;

    /* URL encode the file name */
    encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
    if(encfile) {
      char *urlbuffer = malloc(strlen(url) + strlen(encfile) + 3);
      if(!urlbuffer) {
        free(url);
        return NULL;
      }
      if(ptr)
        /* there is a trailing slash on the URL */
        sprintf(urlbuffer, "%s%s", url, encfile);
      else
        /* there is no trailing slash on the URL */
        sprintf(urlbuffer, "%s/%s", url, encfile);

      curl_free(encfile);

      free(url);
      url = urlbuffer; /* use our new URL instead! */
    }
  }
  return url;
}

/* Extracts the name portion of the URL.
 * Returns a heap-allocated string, or NULL if no name part
 */
static char *get_url_file_name(const char *url)
{
  char *fn = NULL;

  /* Find and get the remote file name */
  const char * pc =strstr(url, "://");
  if(pc)
    pc+=3;
  else
    pc=url;
  pc = strrchr(pc, '/');

  if(pc) {
    /* duplicate the string beyond the slash */
    pc++;
    fn = *pc ? strdup(pc): NULL;
  }
  return fn;
}

static char*
parse_filename(char *ptr, int len)
{
@@ -4539,19 +4617,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
           */

          if(!outfile) {
            /* Find and get the remote file name */
            char * pc =strstr(url, "://");
            if(pc)
              pc+=3;
            else
              pc=url;
            pc = strrchr(pc, '/');

            if(pc) {
              /* duplicate the string beyond the slash */
              pc++;
              outfile = *pc ? strdup(pc): NULL;
            }
            /* extract the file name from the URL */
            outfile = get_url_file_name(url);
            if((!outfile || !*outfile) && !config->content_disposition) {
              helpf(config->errors, "Remote file name has no length!\n");
              res = CURLE_WRITE_ERROR;
@@ -4559,21 +4626,13 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
              break;
            }
#if defined(MSDOS) || defined(WIN32)
            {
            /* For DOS and WIN32, we do some major replacing of
             bad characters in the file name before using it */
              char file1[PATH_MAX];
              if(strlen(outfile) >= PATH_MAX)
                outfile[PATH_MAX-1]=0; /* cut it */
              strcpy(file1, msdosify(outfile));
              free(outfile);

              outfile = strdup(rename_if_dos_device_name(file1));
            outfile = sanitize_dos_name(outfile);
            if(!outfile) {
              res = CURLE_OUT_OF_MEMORY;
              break;
            }
            }
#endif /* MSDOS || WIN32 */
          }
          else if(urls) {
@@ -4639,54 +4698,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
           */
          struct_stat fileinfo;

          /* If no file name part is given in the URL, we add this file name */
          char *ptr=strstr(url, "://");
          if(ptr)
            ptr+=3;
          else
            ptr=url;
          ptr = strrchr(ptr, '/');
          if(!ptr || !strlen(++ptr)) {
            /* The URL has no file name part, add the local file name. In order
               to be able to do so, we have to create a new URL in another
               buffer.*/

            /* We only want the part of the local path that is on the right
               side of the rightmost slash and backslash. */
            char *filep = strrchr(uploadfile, '/');
            char *file2 = strrchr(filep?filep:uploadfile, '\\');

            if(file2)
              filep = file2+1;
            else if(filep)
              filep++;
            else
              filep = uploadfile;

            /* URL encode the file name */
            filep = curl_easy_escape(curl, filep, 0 /* use strlen */);

            if(filep) {
              char *urlbuffer = malloc(strlen(url) + strlen(filep) + 3);
              if(!urlbuffer) {
          url = add_file_name_to_url(curl, url, uploadfile);
          if(!url) {
            helpf(config->errors, "out of memory\n");
                free(url);
            res = CURLE_OUT_OF_MEMORY;
            break;
          }
              if(ptr)
                /* there is a trailing slash on the URL */
                sprintf(urlbuffer, "%s%s", url, filep);
              else
                /* there is no trailing slash on the URL */
                sprintf(urlbuffer, "%s/%s", url, filep);

              curl_free(filep);

              free(url);
              url = urlbuffer; /* use our new URL instead! */
            }
          }
          /* VMS Note:
           *
           * Reading binary from files can be a problem...  Only FIXED, VAR
@@ -5798,4 +5815,17 @@ rename_if_dos_device_name (char *file_name)
  }
  return file_name;
}

/* Replace bad characters in the file name before using it.
 * fn will always be freed before return
 * The returned pointer must be freed by the caller if not NULL
 */
static char *sanitize_dos_name(char *fn)
{
  char tmpfn[PATH_MAX];
  fn[PATH_MAX-1]=0; /* ensure fn is not too long by possibly truncating it */
  strcpy(tmpfn, msdosify(fn));
  free(fn);
  return strdup(rename_if_dos_device_name(tmpfn));
}
#endif /* MSDOS || WIN32 */