Skip to content
Snippets Groups Projects
main.c 99.8 KiB
Newer Older
      curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE);
      curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd);
      curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
      curl_easy_setopt(curl, CURLOPT_RANGE, config->range);
      curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
      curl_easy_setopt(curl, CURLOPT_TIMEOUT, config->timeout);
      curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config->postfields);
      /* new in libcurl 7.2: */
      curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, config->postfieldsize);
      curl_easy_setopt(curl, CURLOPT_REFERER, config->referer);
      curl_easy_setopt(curl, CURLOPT_AUTOREFERER,
                       config->conf&CONF_AUTO_REFERER);
      curl_easy_setopt(curl, CURLOPT_USERAGENT, config->useragent);
      curl_easy_setopt(curl, CURLOPT_FTPPORT, config->ftpport);
      curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
      curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
      curl_easy_setopt(curl, CURLOPT_RESUME_FROM,
                       config->use_resume?config->resume_from:0);
      curl_easy_setopt(curl, CURLOPT_COOKIE, config->cookie);
      curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config->headers);
      curl_easy_setopt(curl, CURLOPT_HTTPPOST, config->httppost);
      curl_easy_setopt(curl, CURLOPT_SSLCERT, config->cert);
      curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
      curl_easy_setopt(curl, CURLOPT_SSLKEY, config->key);
      curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type);
      curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, config->key_passwd);
      /* default to strict verifyhost */
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
      if(config->cacert || config->capath) {
        if (config->cacert)
          curl_easy_setopt(curl, CURLOPT_CAINFO, config->cacert);

        if (config->capath)
          curl_easy_setopt(curl, CURLOPT_CAPATH, config->capath);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE);
      }
          /* new stuff needed for libcurl 7.10 */
          curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
          curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
        }
      if((config->conf&CONF_NOBODY) ||
         config->remote_time) {
        /* no body or use remote time */
        curl_easy_setopt(curl, CURLOPT_FILETIME, TRUE);
      }
      
      if (config->maxredirs) 
        curl_easy_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs); 
      else 
        curl_easy_setopt(curl, CURLOPT_MAXREDIRS, DEFAULT_MAXREDIRS); 
      curl_easy_setopt(curl, CURLOPT_CRLF, config->crlf);
      curl_easy_setopt(curl, CURLOPT_QUOTE, config->quote);
      curl_easy_setopt(curl, CURLOPT_POSTQUOTE, config->postquote);
      curl_easy_setopt(curl, CURLOPT_WRITEHEADER,
                       config->headerfile?&heads:NULL);
      curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config->cookiefile);
      /* cookie jar was added in 7.9 */
      if(config->cookiejar)
        curl_easy_setopt(curl, CURLOPT_COOKIEJAR, config->cookiejar);
      /* cookie session added in 7.9.7 */
      curl_easy_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession);

      curl_easy_setopt(curl, CURLOPT_SSLVERSION, config->ssl_version);
      curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config->timecond);
      curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
      curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
      curl_easy_setopt(curl, CURLOPT_STDERR, config->errors);
      /* three new ones in libcurl 7.3: */
      curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
      curl_easy_setopt(curl, CURLOPT_INTERFACE, config->iface);
      curl_easy_setopt(curl, CURLOPT_KRB4LEVEL, config->krb4level);
      
      if((config->progressmode == CURL_PROGRESS_BAR) &&
         !(config->conf&(CONF_NOPROGRESS|CONF_MUTE))) {
        /* we want the alternative style, then we have to implement it
           ourselves! */
        progressbarinit(&progressbar, config);
        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, myprogress);
        curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
      }
      /* new in libcurl 7.6.2: */
      curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);

      /* new in libcurl 7.7: */
      curl_easy_setopt(curl, CURLOPT_RANDOM_FILE, config->random_file);
      curl_easy_setopt(curl, CURLOPT_EGDSOCKET, config->egd_file);
      curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, config->connecttimeout);

      if(config->cipher_list)
        curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);

      if(config->httpversion)
        curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, config->httpversion);
Daniel Stenberg's avatar
Daniel Stenberg committed

      /* new in libcurl 7.9.2: */
      if(config->disable_epsv)
        /* disable it */
        curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, FALSE);
Daniel Stenberg's avatar
Daniel Stenberg committed
      /* new in libcurl 7.10.5 */
      if(config->disable_eprt)
        /* disable it */
        curl_easy_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE);
      /* new in libcurl 7.10.6 (default is Basic) */
      if(config->authtype)
        curl_easy_setopt(curl, CURLOPT_HTTPAUTH, config->authtype);
      /* new in curl 7.9.7 */
      if(config->trace_dump) {
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
        curl_easy_setopt(curl, CURLOPT_DEBUGDATA, config);
        config->conf |= CONF_VERBOSE; /* force verbose */
      curl_easy_setopt(curl, CURLOPT_VERBOSE, config->conf&CONF_VERBOSE);
      /* new in curl 7.10 */
      curl_easy_setopt(curl, CURLOPT_ENCODING, 
                       (config->encoding) ? "" : NULL);
      /* new in curl 7.10.7 */
      curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
                       config->ftp_create_dirs);
Daniel Stenberg's avatar
Daniel Stenberg committed
      if(config->proxyntlm)
        curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
      res = curl_easy_perform(curl);
      if((config->progressmode == CURL_PROGRESS_BAR) &&
         progressbar.calls) {
        /* if the custom progress bar has been displayed, we output a
           newline here */
        fputs("\n", progressbar.out);
      }

      if(config->writeout) {
        ourWriteOut(curl, config->writeout);
#ifdef USE_ENVIRONMENT
      if (config->writeenv)
        ourWriteEnv(curl);
#endif
Daniel Stenberg's avatar
Daniel Stenberg committed
#ifdef	VMS
      if (!config->showerror)  {
        vms_show = VMSSTS_HIDE;
      }
Daniel Stenberg's avatar
Daniel Stenberg committed
#else
      if((res!=CURLE_OK) && config->showerror) {
        if(CURLE_SSL_CACERT == res) {
          fprintf(config->errors, "curl: (%d) %s\n\n", res, errorbuffer);
#define CURL_CA_CERT_ERRORMSG1 \
"More details here: http://curl.haxx.se/docs/sslcerts.html\n\n" \
"curl performs SSL certificate verification by default, using a \"bundle\"\n" \
" of Certificate Authority (CA) public keys (CA certs). The default\n" \
" bundle is named curl-ca-bundle.crt; you can specify an alternate file\n" \
" using the --cacert option.\n"

#define CURL_CA_CERT_ERRORMSG2 \
"If this HTTPS server uses a certificate signed by a CA represented in\n" \
" the bundle, the certificate verification probably failed due to a\n" \
" problem with the certificate (it might be expired, or the name might\n" \
" not match the domain name in the URL).\n" \
"If you'd like to turn off curl's verification of the certificate, use\n" \
" the -k (or --insecure) option.\n"

          fprintf(config->errors, "%s%s",
                  CURL_CA_CERT_ERRORMSG1,
                  CURL_CA_CERT_ERRORMSG2 );
        }
        else
          fprintf(config->errors, "curl: (%d) %s\n", res, errorbuffer);
      }
Daniel Stenberg's avatar
Daniel Stenberg committed
#endif
Daniel Stenberg's avatar
Daniel Stenberg committed

      if (outfile && !curl_strequal(outfile, "-") && outs.stream)
        fclose(outs.stream);

#ifdef HAVE_UTIME
      /* Important that we set the time _after_ the file has been 
         closed, as is done above here */
      if(config->remote_time && outs.filename) {
        /* as libcurl if we got a time. Pretty please */
        long filetime;
        curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
        if(filetime >= 0) {
          struct utimbuf times;
          times.actime = filetime;
          times.modtime = filetime;
          utime(outs.filename, &times); /* set the time we got */
        }
      }
#endif

      if (config->infile)
        fclose(infd);
      if(headerfilep)
        fclose(headerfilep);
      
      if(url)
        free(url);
Daniel Stenberg's avatar
Daniel Stenberg committed

      if(outfile)
        free(outfile);
    if(outfiles)
      free(outfiles);
    if(urls)
      /* cleanup memory used for URL globbing patterns */
      glob_cleanup(urls);
Daniel Stenberg's avatar
Daniel Stenberg committed

    /* empty this urlnode struct */
    if(urlnode->url)
      free(urlnode->url);
    if(urlnode->outfile)
      free(urlnode->outfile);
    /* move on to the next URL */
    nextnode=urlnode->next;
    free(urlnode); /* free the node */
    urlnode = nextnode;
Daniel Stenberg's avatar
Daniel Stenberg committed

  } /* while-loop through all URLs */
Daniel Stenberg's avatar
Daniel Stenberg committed

  if(config->headerfile && !headerfilep && heads.stream)
    fclose(heads.stream);

  if(config->trace_fopened)
  if(allocuseragent)
    free(config->useragent);
  /* cleanup the curl handle! */
  curl_easy_cleanup(curl);

  struct Configurable config;
  memset(&config, 0, sizeof(struct Configurable));
  res = operate(&config, argc, argv);
Daniel Stenberg's avatar
Daniel Stenberg committed

Daniel Stenberg's avatar
Daniel Stenberg committed
#ifdef	VMS
  if (res > 52) res = 53;		/* MAXMSG, porting helper */
Daniel Stenberg's avatar
Daniel Stenberg committed
  return (vms_cond[res]|vms_show);
#else
  return res;
Daniel Stenberg's avatar
Daniel Stenberg committed
#endif
Daniel Stenberg's avatar
Daniel Stenberg committed
}

static char *my_get_line(FILE *fp)
{
   char buf[4096];
   char *nl = NULL;
   char *retval = NULL;

   do {
     if (NULL == fgets(buf, sizeof(buf), fp))
       break;
     if (NULL == retval)
       retval = strdup(buf);
     else {
       if (NULL == (retval = realloc(retval,
                                     strlen(retval) + strlen(buf) + 1)))
   }
   while (NULL == (nl = strchr(retval, '\n')));

   if (NULL != nl)
     *nl = '\0';

   return retval;
}


/* Create the needed directory hierarchy recursively in order to save
   multi-GETs in file output, ie:
   curl "http://my.site/dir[1-5]/file[1-5].txt" -o "dir#1/file#2.txt"
   should create all the dir* automagically
*/
static int create_dir_hierarchy(char *outfile)
{
  char *tempdir;
  char *tempdir2;
  char *outdup;
  char *dirbuildup;
  int result=0;
  
  outdup = strdup(outfile);
  dirbuildup = malloc(sizeof(char) * strlen(outfile));
  if(!dirbuildup)
    return -1;
  dirbuildup[0] = '\0';

  tempdir = strtok(outdup, DIR_CHAR);

  while (tempdir != NULL) {
    tempdir2 = strtok(NULL, DIR_CHAR);
    /* since strtok returns a token for the last word even
       if not ending with DIR_CHAR, we need to prune it */
    if (tempdir2 != NULL) {
      if (strlen(dirbuildup) > 0)
        sprintf(dirbuildup,"%s%s%s",dirbuildup, DIR_CHAR, tempdir);
      else {
        if (0 != strncmp(outdup, DIR_CHAR, 1))
          sprintf(dirbuildup,"%s",tempdir);
        else
          sprintf(dirbuildup,"%s%s", DIR_CHAR, tempdir);
      }
Daniel Stenberg's avatar
Daniel Stenberg committed
      if (access(dirbuildup, F_OK) == -1) {
        result = mkdir(dirbuildup,(mode_t)0000750);
        if (-1 == result) {
          switch (errno) {
#ifdef EACCES
          case EACCES:
            fprintf(stderr,"You don't have permission to create %s.\n",
                    dirbuildup);
            break;
#endif
#ifdef ENAMETOOLONG
          case ENAMETOOLONG:
            fprintf(stderr,"The directory name %s is too long.\n",
                    dirbuildup);
            break;
#endif
#ifdef EROFS
          case EROFS:
            fprintf(stderr,"%s resides on a read-only file system.\n",
                    dirbuildup);
            break;
#endif
#ifdef ENOSPC
          case ENOSPC:
            fprintf(stderr,"No space left on the file system that will "
                    "contain the directory %s.\n", dirbuildup);
            break;
#endif
#ifdef EDQUOT
          case EDQUOT:
            fprintf(stderr,"Cannot create directory %s because you "
                    "exceeded your quota.\n", dirbuildup);
            break;
#endif
          default :
            fprintf(stderr,"Error creating directory %s.\n", dirbuildup);
            break;
          }
          break; /* get out of loop */
        }
      }
    }
    tempdir = tempdir2;
  }
  free(dirbuildup);
  free(outdup);

  return result; /* 0 is fine, -1 is badness */
}

#ifdef __DJGPP__
/* The following functions are taken with modification from the DJGPP
 * port of tar 1.12. They use algorithms originally from DJTAR. */

char *
msdosify (char *file_name)
{
  static char dos_name[PATH_MAX];
  static char illegal_chars_dos[] = ".+, ;=[]|<>\\\":?*";
  static char *illegal_chars_w95 = &illegal_chars_dos[8];
  int idx, dot_idx;
  char *s = file_name, *d = dos_name;
  char *illegal_aliens = illegal_chars_dos;
  size_t len = sizeof (illegal_chars_dos) - 1;
  int lfn = 0;

  /* Support for Windows 9X VFAT systems, when available.  */
  if (_use_lfn (file_name))
    lfn = 1;
  if (lfn) {
    illegal_aliens = illegal_chars_w95;
    len -= (illegal_chars_w95 - illegal_chars_dos);
  }
  
  /* Get past the drive letter, if any. */
  if (s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') {
    *d++ = *s++;
    *d++ = *s++;
  }

  for (idx = 0, dot_idx = -1; *s; s++, d++) {
    if (memchr (illegal_aliens, *s, len)) {
      /* Dots are special: DOS doesn't allow them as the leading character,
         and a file name cannot have more than a single dot.  We leave the
         first non-leading dot alone, unless it comes too close to the
         beginning of the name: we want sh.lex.c to become sh_lex.c, not
         sh.lex-c.  */
      if (*s == '.') {
        if (idx == 0 && (s[1] == '/' || (s[1] == '.' && s[2] == '/'))) {
          /* Copy "./" and "../" verbatim.  */
          *d++ = *s++;
          if (*s == '.')
            *d++ = *s++;
          *d = *s;
        }
        else if (idx == 0)
          *d = '_';
        else if (dot_idx >= 0) {
          if (dot_idx < 5) { /* 5 is a heuristic ad-hoc'ery */
            d[dot_idx - idx] = '_'; /* replace previous dot */
            *d = '.';
          }
          else
            *d = '-';
        }
        else
          *d = '.';

        if (*s == '.')
          dot_idx = idx;
      }
      else if (*s == '+' && s[1] == '+') {
        if (idx - 2 == dot_idx) { /* .c++, .h++ etc. */
          *d++ = 'x';
          *d   = 'x';
        }
        else {
          /* libg++ etc.  */
          memcpy (d, "plus", 4);
          d += 3;
        }
        s++;
        idx++;
      }
      else
        *d = '_';
    }
    else
      *d = *s;
    if (*s == '/') {
      idx = 0;
      dot_idx = -1;
    }
    else
      idx++;
  }

  *d = '\0';
  return dos_name;
}

char *
rename_if_dos_device_name (char *file_name)
{
  /* We could have a file whose name is a device on MS-DOS.  Trying to
   * retrieve such a file would fail at best and wedge us at worst.  We need
   * to rename such files. */
  extern char *basename (const char *);
  char *base;
  struct stat st_buf;
  char fname[PATH_MAX];

  strcpy (fname, file_name);
  base = basename (fname);
  if (((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) {
    size_t blen = strlen (base);

    /* Prepend a '_'.  */
    memmove (base + 1, base, blen + 1);
    base[0] = '_';
    strcpy (file_name, fname);
  }
  return file_name;
}

#endif /* __DJGPP__ */