Example #1
0
File: pipeline.c Project: 2px/curl
static CURLcode addHandleToPipeline(struct Curl_easy *data,
                                    struct curl_llist *pipeline)
{
  if(!Curl_llist_insert_next(pipeline, pipeline->tail, data))
    return CURLE_OUT_OF_MEMORY;
  return CURLE_OK;
}
Example #2
0
/* Insert the data in the hash. If there already was a match in the hash,
 * that data is replaced.
 *
 * @unittest: 1305
 */
void *
Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
{
  struct curl_hash_element  *he;
  struct curl_llist_element *le;
  struct curl_llist *l = FETCH_LIST (h, key, key_len);

  for(le = l->head; le; le = le->next) {
    he = (struct curl_hash_element *) le->ptr;
    if(h->comp_func(he->key, he->key_len, key, key_len)) {
      Curl_llist_remove(l, le, (void *)h);
      --h->size;
      break;
    }
  }

  he = mk_hash_element(key, key_len, p);
  if(he) {
    if(Curl_llist_insert_next(l, l->tail, he)) {
      ++h->size;
      return p; /* return the new entry */
    }
    /*
     * Couldn't insert it, destroy the 'he' element and the key again. We
     * don't call hash_element_dtor() since that would also call the
     * "destructor" for the actual data 'p'. When we fail, we shall not touch
     * that data.
     */
    free(he->key);
    free(he);
  }

  return NULL; /* failure */
}
Example #3
0
/* Return the data in the hash. If there already was a match in the hash,
   that data is returned. */
void *
Curl_hash_add(curl_hash *h, char *key, size_t key_len, void *p)
{
  curl_hash_element  *he;
  curl_llist_element *le;
  curl_llist *l = FETCH_LIST(h, key, key_len);

  for (le = l->head; le; le = le->next) {
    he = (curl_hash_element *) le->ptr;
    if (hash_key_compare(he->key, he->key_len, key, key_len)) {
      h->dtor(p);     /* remove the NEW entry */
      return he->ptr; /* return the EXISTING entry */
    }
  }

  he = mk_hash_element(key, key_len, p);
  if (he) {
    if(Curl_llist_insert_next(l, l->tail, he)) {
      ++h->size;
      return p; /* return the new entry */
    }
    /*
     * Couldn't insert it, destroy the 'he' element and the key again. We
     * don't call hash_element_dtor() since that would also call the
     * "destructor" for the actual data 'p'. When we fail, we shall not touch
     * that data.
     */
    free(he->key);
    free(he);
  }

  return NULL; /* failure */
}
Example #4
0
/* Add a connection to a bundle */
static void bundle_add_conn(struct connectbundle *cb_ptr,
                            struct connectdata *conn)
{
  Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
                         &conn->bundle_node);
  conn->bundle = cb_ptr;
  cb_ptr->num_connections++;
}
Example #5
0
static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
                                    struct curl_fileinfo *finfo)
{
  curl_fnmatch_callback compare;
  struct WildcardData *wc = &conn->data->wildcard;
  struct ftp_wc_tmpdata *tmpdata = wc->tmp;
  struct curl_llist *llist = wc->filelist;
  struct ftp_parselist_data *parser = tmpdata->parser;
  bool add = true;

  /* move finfo pointers to b_data */
  char *str = finfo->b_data;
  finfo->filename       = str + parser->offsets.filename;
  finfo->strings.group  = parser->offsets.group ?
                          str + parser->offsets.group : NULL;
  finfo->strings.perm   = parser->offsets.perm ?
                          str + parser->offsets.perm : NULL;
  finfo->strings.target = parser->offsets.symlink_target ?
                          str + parser->offsets.symlink_target : NULL;
  finfo->strings.time   = str + parser->offsets.time;
  finfo->strings.user   = parser->offsets.user ?
                          str + parser->offsets.user : NULL;

  /* get correct fnmatch callback */
  compare = conn->data->set.fnmatch;
  if(!compare)
    compare = Curl_fnmatch;

  /* filter pattern-corresponding filenames */
  if(compare(conn->data->set.fnmatch_data, wc->pattern,
             finfo->filename) == 0) {
    /* discard symlink which is containing multiple " -> " */
    if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
       (strstr(finfo->strings.target, " -> "))) {
      add = false;
    }
  }
  else {
    add = false;
  }

  if(add) {
    if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
      Curl_fileinfo_dtor(NULL, finfo);
      tmpdata->parser->file_data = NULL;
      return CURLE_OUT_OF_MEMORY;
    }
  }
  else {
    Curl_fileinfo_dtor(NULL, finfo);
  }

  tmpdata->parser->file_data = NULL;
  return CURLE_OK;
}
Example #6
0
/* Add a connection to a bundle */
static CURLcode bundle_add_conn(struct connectbundle *cb_ptr,
                              struct connectdata *conn)
{
  if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn))
    return CURLE_OUT_OF_MEMORY;

  conn->bundle = cb_ptr;

  cb_ptr->num_connections++;
  return CURLE_OK;
}
Example #7
0
CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
                                           struct curl_llist **list_ptr)
{
  struct curl_llist *old_list = *list_ptr;
  struct curl_llist *new_list = NULL;

  if(sites) {
    new_list = Curl_llist_alloc((curl_llist_dtor) site_blacklist_llist_dtor);
    if(!new_list)
      return CURLM_OUT_OF_MEMORY;

    /* Parse the URLs and populate the list */
    while(*sites) {
      char *hostname;
      char *port;
      struct site_blacklist_entry *entry;

      entry = malloc(sizeof(struct site_blacklist_entry));

      hostname = strdup(*sites);
      if(!hostname)
        return CURLM_OUT_OF_MEMORY;

      port = strchr(hostname, ':');
      if(port) {
        *port = '\0';
        port++;
        entry->port = (unsigned short)strtol(port, NULL, 10);
      }
      else {
        /* Default port number for HTTP */
        entry->port = 80;
      }

      entry->hostname = hostname;

      if(!Curl_llist_insert_next(new_list, new_list->tail, entry))
        return CURLM_OUT_OF_MEMORY;

      sites++;
    }
  }

  /* Free the old list */
  if(old_list) {
    Curl_llist_destroy(old_list, NULL);
  }

  /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
  *list_ptr = new_list;

  return CURLM_OK;
}
Example #8
0
/* Call PK11_CreateGenericObject() with the given obj_class and filename.  If
 * the call succeeds, append the object handle to the list of objects so that
 * the object can be destroyed in Curl_nss_close(). */
static CURLcode nss_create_object(struct ssl_connect_data *ssl,
                                  CK_OBJECT_CLASS obj_class,
                                  const char *filename, bool cacert)
{
  PK11SlotInfo *slot;
  PK11GenericObject *obj;
  CK_BBOOL cktrue = CK_TRUE;
  CK_BBOOL ckfalse = CK_FALSE;
  CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
  int attr_cnt = 0;
  CURLcode err = (cacert)
    ? CURLE_SSL_CACERT_BADFILE
    : CURLE_SSL_CERTPROBLEM;

  const int slot_id = (cacert) ? 0 : 1;
  char *slot_name = aprintf("PEM Token #%d", slot_id);
  if(!slot_name)
    return CURLE_OUT_OF_MEMORY;

  slot = PK11_FindSlotByName(slot_name);
  free(slot_name);
  if(!slot)
    return err;

  PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
  PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
  PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
                strlen(filename) + 1);

  if(CKO_CERTIFICATE == obj_class) {
    CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
    PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
  }

  obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
  PK11_FreeSlot(slot);
  if(!obj)
    return err;

  if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
    PK11_DestroyGenericObject(obj);
    return CURLE_OUT_OF_MEMORY;
  }

  if(!cacert && CKO_CERTIFICATE == obj_class)
    /* store reference to a client certificate */
    ssl->obj_clicert = obj;

  return CURLE_OK;
}
Example #9
0
File: pipeline.c Project: 2px/curl
CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
                                             struct curl_llist **list_ptr)
{
  struct curl_llist *old_list = *list_ptr;
  struct curl_llist *new_list = NULL;

  if(servers) {
    new_list = Curl_llist_alloc((curl_llist_dtor) server_blacklist_llist_dtor);
    if(!new_list)
      return CURLM_OUT_OF_MEMORY;

    /* Parse the URLs and populate the list */
    while(*servers) {
      char *server_name;

      server_name = strdup(*servers);
      if(!server_name) {
        Curl_llist_destroy(new_list, NULL);
        return CURLM_OUT_OF_MEMORY;
      }

      if(!Curl_llist_insert_next(new_list, new_list->tail, server_name)) {
        Curl_llist_destroy(new_list, NULL);
        Curl_safefree(server_name);
        return CURLM_OUT_OF_MEMORY;
      }

      servers++;
    }
  }

  /* Free the old list */
  if(old_list) {
    Curl_llist_destroy(old_list, NULL);
  }

  /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
  *list_ptr = new_list;

  return CURLM_OK;
}
Example #10
0
File: altsvc.c Project: curl/curl
/* only returns SERIOUS errors */
static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
{
  /* Example line:
     h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1
   */
  char srchost[MAX_ALTSVC_HOSTLEN + 1];
  char dsthost[MAX_ALTSVC_HOSTLEN + 1];
  char srcalpn[MAX_ALTSVC_ALPNLEN + 1];
  char dstalpn[MAX_ALTSVC_ALPNLEN + 1];
  char date[MAX_ALTSVC_DATELEN + 1];
  unsigned int srcport;
  unsigned int dstport;
  unsigned int prio;
  unsigned int persist;
  int rc;

  rc = sscanf(line,
              "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
              "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
              "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u",
              srcalpn, srchost, &srcport,
              dstalpn, dsthost, &dstport,
              date, &persist, &prio);
  if(9 == rc) {
    struct altsvc *as;
    time_t expires = curl_getdate(date, NULL);
    as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
    if(as) {
      as->expires = expires;
      as->prio = prio;
      as->persist = persist ? 1 : 0;
      Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
      asi->num++; /* one more entry */
    }
  }

  return CURLE_OK;
}
Example #11
0
File: altsvc.c Project: curl/curl
/*
 * Curl_altsvc_parse() takes an incoming alt-svc response header and stores
 * the data correctly in the cache.
 *
 * 'value' points to the header *value*. That's contents to the right of the
 * header name.
 */
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
                           struct altsvcinfo *asi, const char *value,
                           enum alpnid srcalpnid, const char *srchost,
                           unsigned short srcport)
{
  const char *p = value;
  size_t len;
  enum alpnid dstalpnid = srcalpnid; /* the same by default */
  char namebuf[MAX_ALTSVC_HOSTLEN] = "";
  char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
  struct altsvc *as;
  unsigned short dstport = srcport; /* the same by default */
  const char *semip;
  time_t maxage = 24 * 3600; /* default is 24 hours */
  bool persist = FALSE;
  CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
  if(result)
    return result;

  DEBUGASSERT(asi);

  /* Flush all cached alternatives for this source origin, if any */
  altsvc_flush(asi, srcalpnid, srchost, srcport);

  /* "clear" is a magic keyword */
  if(strcasecompare(alpnbuf, "clear")) {
    /* TODO: clear whatever it is it should clear */
    return CURLE_OK;
  }

  /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives
     but are set after the list on the line. Scan for the semicolons and get
     those fields first! */
  semip = p;
  do {
    semip = strchr(semip, ';');
    if(semip) {
      char option[32];
      unsigned long num;
      char *end_ptr;
      semip++; /* pass the semicolon */
      result = getalnum(&semip, option, sizeof(option));
      if(result)
        break;
      while(*semip && ISBLANK(*semip))
        semip++;
      if(*semip != '=')
        continue;
      semip++;
      num = strtoul(semip, &end_ptr, 10);
      if(num < ULONG_MAX) {
        if(strcasecompare("ma", option))
          maxage = num;
        else if(strcasecompare("persist", option) && (num == 1))
          persist = TRUE;
      }
      semip = end_ptr;
    }
  } while(semip);

  do {
    if(*p == '=') {
      /* [protocol]="[host][:port]" */
      dstalpnid = alpn2alpnid(alpnbuf);
      if(!dstalpnid) {
        infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
        return CURLE_OK;
      }
      p++;
      if(*p == '\"') {
        const char *dsthost;
        p++;
        if(*p != ':') {
          /* host name starts here */
          const char *hostp = p;
          while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
            p++;
          len = p - hostp;
          if(!len || (len >= MAX_ALTSVC_HOSTLEN))
            return CURLE_BAD_FUNCTION_ARGUMENT; /* TODO: improve error code */
          memcpy(namebuf, hostp, len);
          namebuf[len] = 0;
          dsthost = namebuf;
        }
        else {
          /* no destination name, use source host */
          dsthost = srchost;
        }
        if(*p == ':') {
          /* a port number */
          char *end_ptr;
          unsigned long port = strtoul(++p, &end_ptr, 10);
          if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
            infof(data, "Unknown alt-svc port number, ignoring...\n");
            return CURLE_OK;
          }
          p = end_ptr;
          dstport = curlx_ultous(port);
        }
        if(*p++ != '\"')
          return CURLE_BAD_FUNCTION_ARGUMENT;
        as = altsvc_createid(srchost, dsthost,
                             srcalpnid, dstalpnid,
                             srcport, dstport);
        if(as) {
          /* TODO: the expires time also needs to take the Age: value (if any)
             into account. [See RFC 7838 section 3.1] */
          as->expires = maxage + time(NULL);
          as->persist = persist;
          Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
          asi->num++; /* one more entry */
          infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
                Curl_alpnid2str(dstalpnid));
        }
      }
      /* after the double quote there can be a comma if there's another
         string or a semicolon if no more */
      if(*p == ',') {
        /* comma means another alternative is presented */
        p++;
        result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
        if(result)
          /* failed to parse, but since we already did at least one host we
             return OK */
          return CURLE_OK;
      }
    }
  } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));

  return CURLE_OK;
}
Example #12
0
  fail_unless(llist->head == NULL, "list head should initiate to NULL");
  fail_unless(llist->tail == NULL, "list tail should intiate to NULL");
  fail_unless(llist->dtor == test_curl_llist_dtor,
               "list dtor shold initiate to test_curl_llist_dtor");

  /**
   * testing Curl_llist_insert_next
   * case 1:
   * list is empty
   * @assumptions:
   * 1: list size will be 1
   * 2: list head will hold the data "unusedData_case1"
   * 3: list tail will be the same as list head
   */

  curlErrCode = Curl_llist_insert_next(llist, llist->head, &unusedData_case1);
  if(curlErrCode == 1) {
    fail_unless(Curl_llist_count(llist) == 1,
                 "List size should be 1 after adding a new element");
    /*test that the list head data holds my unusedData */
    fail_unless(llist->head->ptr == &unusedData_case1,
                 "List size should be 1 after adding a new element");
    /*same goes for the list tail */
    fail_unless(llist->tail == llist->head,
                 "List size should be 1 after adding a new element");

    /**
     * testing Curl_llist_insert_next
     * case 2:
     * list has 1 element, adding one element after the head
     * @assumptions: