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; }
/* 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 */ }
/* 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 */ }
/* 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++; }
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; }
/* 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; }
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; }
/* 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; }
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; }
/* 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; }
/* * 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; }
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: