banfunc sscanf
banfunc snprintf
banfunc vsnprint
+banfunc strtoul
+banfunc strtol
splay.c \
strcase.c \
strdup.c \
+ strequal.c \
strerror.c \
strparse.c \
strtok.c \
struct Curl_str srcalpn;
struct Curl_str dstalpn;
struct Curl_str date;
- size_t srcport;
- size_t dstport;
- size_t persist;
- size_t prio;
+ curl_off_t srcport;
+ curl_off_t dstport;
+ curl_off_t persist;
+ curl_off_t prio;
if(Curl_str_word(&line, &srcalpn, MAX_ALTSVC_ALPNLEN) ||
Curl_str_singlespace(&line) ||
memcpy(dbuf, date.str, date.len);
dbuf[date.len] = 0;
expires = Curl_getdate_capped(dbuf);
- as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn, srcport,
- dstport);
+ as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn,
+ (size_t)srcport, (size_t)dstport);
if(as) {
as->expires = expires;
as->prio = 0; /* not supported to just set zero */
return */
static time_t altsvc_debugtime(void *unused)
{
- char *timestr = getenv("CURL_TIME");
+ const char *timestr = getenv("CURL_TIME");
(void)unused;
if(timestr) {
- long val = strtol(timestr, NULL, 10);
+ curl_off_t val;
+ Curl_str_number(×tr, &val, TIME_T_MAX);
return (time_t)val;
}
return time(NULL);
size_t dstlen = 0; /* destination hostname length */
const char *value_ptr;
char option[32];
- size_t num;
+ curl_off_t num;
bool quoted = FALSE;
time_t maxage = 24 * 3600; /* default is 24 hours */
bool persist = FALSE;
dstlen = strlen(srchost);
}
if(*p == ':') {
- size_t port = 0;
+ curl_off_t port = 0;
p++;
if(Curl_str_number(&p, &port, 0xffff) || (*p != '\"')) {
infof(data, "Unknown alt-svc port number, ignoring.");
while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',')
p++;
}
- if(!Curl_str_number(&value_ptr, &num, SIZE_T_MAX)) {
+ if(!Curl_str_number(&value_ptr, &num, TIME_T_MAX)) {
if(strcasecompare("ma", option))
maxage = (time_t)num;
else if(strcasecompare("persist", option) && (num == 1))
Curl_printable_address. The latter returns only numeric scope
IDs and the former returns none at all. So the scope ID, if
present, is known to be numeric */
- size_t scope_id;
+ curl_off_t scope_id;
if(Curl_str_number((const char **)&scope_ptr, &scope_id, UINT_MAX))
return CURLE_UNSUPPORTED_PROTOCOL;
si6->sin6_scope_id = (unsigned int)scope_id;
#ifdef DEBUGBUILD
{
- char *p = getenv("CURL_DBG_SOCK_WBLOCK");
+ const char *p = getenv("CURL_DBG_SOCK_WBLOCK");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0 && l <= 100)
+ curl_off_t l;
+ if(!Curl_str_number(&p, &l, 100))
ctx->wblock_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_WPARTIAL");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0 && l <= 100)
+ curl_off_t l;
+ if(!Curl_str_number(&p, &l, 100))
ctx->wpartial_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_RBLOCK");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0 && l <= 100)
+ curl_off_t l;
+ if(!Curl_str_number(&p, &l, 100))
ctx->rblock_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_RMAX");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0)
+ curl_off_t l;
+ if(!Curl_str_number(&p, &l, SIZE_T_MAX))
ctx->recv_max = (size_t)l;
}
}
#include "progress.h"
#include "select.h"
#include "warnless.h"
+#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
{
/* Allow debug builds to override this logic to force short sends
*/
- char *p = getenv("CURL_SMALLSENDS");
+ const char *p = getenv("CURL_SMALLSENDS");
if(p) {
- size_t altsize = (size_t)strtoul(p, NULL, 10);
- if(altsize)
- write_len = CURLMIN(write_len, altsize);
+ curl_off_t altsize;
+ if(!Curl_str_number(&p, &altsize, SIZE_T_MAX))
+ write_len = CURLMIN(write_len, (size_t)altsize);
}
}
#endif
#include "connect.h"
#include "select.h"
#include "strcase.h"
+#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
/* Just for testing, run graceful shutdown */
#ifdef DEBUGBUILD
{
- char *p = getenv("CURL_GRACEFUL_SHUTDOWN");
+ const char *p = getenv("CURL_GRACEFUL_SHUTDOWN");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l > 0 && l < INT_MAX)
+ curl_off_t l;
+ if(!Curl_str_number(&p, &l, INT_MAX))
timeout_ms = (int)l;
}
}
#include "sendf.h"
#include "slist.h"
#include "share.h"
-#include "strtoofft.h"
#include "strcase.h"
#include "curl_get_line.h"
#include "curl_memrchr.h"
#include "fopen.h"
#include "strdup.h"
#include "llist.h"
+#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
* client should discard the cookie. A value of zero means the
* cookie should be discarded immediately.
*/
- CURLofft offt;
+ int rc;
const char *maxage = valuep;
- offt = curlx_strtoofft((*maxage == '\"') ?
- &maxage[1] : &maxage[0], NULL, 10,
- &co->expires);
- switch(offt) {
- case CURL_OFFT_FLOW:
+ if(*maxage == '\"')
+ maxage++;
+ rc = Curl_str_number(&maxage, &co->expires, CURL_OFF_T_MAX);
+
+ switch(rc) {
+ case STRE_OVERFLOW:
/* overflow, used max value */
co->expires = CURL_OFF_T_MAX;
break;
- case CURL_OFFT_INVAL:
+ default:
/* negative or otherwise bad, expire */
co->expires = 1;
break;
- case CURL_OFFT_OK:
+ case STRE_OK:
if(!co->expires)
/* already expired */
co->expires = 1;
}
break;
case 4:
- {
- char *endp;
- const char *p;
- /* make sure curlx_strtoofft won't read past the current field */
- for(p = ptr; p < &ptr[len] && ISDIGIT(*p); ++p)
- ;
- if(p == ptr || p != &ptr[len] ||
- curlx_strtoofft(ptr, &endp, 10, &co->expires) || endp != &ptr[len])
- return CERR_RANGE;
- }
+ if(Curl_str_number(&ptr, &co->expires, CURL_OFF_T_MAX))
+ return CERR_RANGE;
break;
case 5:
co->name = Curl_memdup0(ptr, len);
#define ISCNTRL(x) (ISLOWCNTRL(x) || IS7F(x))
#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
#define ISXDIGIT(x) (ISDIGIT(x) || ISLOWHEXALHA(x) || ISUPHEXALHA(x))
+#define ISODIGIT(x) (((x) >= '0') && ((x) <= '7'))
#define ISALNUM(x) (ISDIGIT(x) || ISLOWER(x) || ISUPPER(x))
#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
#include <curl/curl.h>
#include "curl_range.h"
#include "sendf.h"
-#include "strtoofft.h"
+#include "strparse.h"
/* Only include this function if one or more of FTP, FILE are enabled. */
#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)
*/
CURLcode Curl_range(struct Curl_easy *data)
{
- curl_off_t from, to;
- char *ptr;
- char *ptr2;
-
if(data->state.use_range && data->state.range) {
- CURLofft from_t;
- CURLofft to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
- if(from_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
- if(to_t == CURL_OFFT_FLOW)
+ curl_off_t from, to;
+ bool first_num = TRUE;
+ const char *p = data->state.range;
+ if(Curl_str_number(&p, &from, CURL_OFF_T_MAX))
+ first_num = FALSE;
+
+ if(Curl_str_single(&p, '-'))
+ /* no leading dash or after the first number is an error */
return CURLE_RANGE_ERROR;
- if((to_t == CURL_OFFT_INVAL) && !from_t) {
+
+ if(Curl_str_number(&p, &to, CURL_OFF_T_MAX)) {
+ /* no second number */
/* X - */
data->state.resume_from = from;
DEBUGF(infof(data, "RANGE %" FMT_OFF_T " to end of file", from));
}
- else if((from_t == CURL_OFFT_INVAL) && !to_t) {
+ else if(!first_num) {
/* -Y */
+ if(!to)
+ /* "-0" is just wrong */
+ return CURLE_RANGE_ERROR;
+
data->req.maxdownload = to;
data->state.resume_from = -to;
DEBUGF(infof(data, "RANGE the last %" FMT_OFF_T " bytes", to));
#include "ftplistparser.h"
#include "curl_range.h"
#include "curl_krb5.h"
-#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "cfilters.h"
r += pp->nfinal;
if(LASTLINE(r)) {
- size_t status;
+ curl_off_t status;
if(!Curl_str_number(&r, &status, 999) && (status == 226)) {
/* funny timing situation where we get the final message on the
control connection before traffic on the data connection has been
static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
const char *line, size_t len, int *code)
{
- size_t status;
+ curl_off_t status;
(void)data;
(void)conn;
if(ip_end) {
const char *portp = strchr(ip_end, ':');
if(portp) {
- size_t start;
- size_t end;
+ curl_off_t start;
+ curl_off_t end;
portp++;
if(!Curl_str_number(&portp, &start, 0xffff)) {
/* got the first number */
{
int i;
for(i = 0; i < 6; i++) {
- size_t num;
+ curl_off_t num;
if(i) {
if(*p != ',')
return FALSE;
ptr++;
/* |||12345| */
sep = ptr[0];
- /* the ISDIGIT() check here is because strtoul() accepts leading minus
- etc */
if((ptr[1] == sep) && (ptr[2] == sep) && ISDIGIT(ptr[3])) {
const char *p = &ptr[3];
- size_t num;
+ curl_off_t num;
if(Curl_str_number(&p, &num, 0xffff) || (*p != sep)) {
failf(data, "Illegal port number in EPSV reply");
return CURLE_FTP_WEIRD_PASV_REPLY;
for all the digits at the end of the response and parse only those as a
number. */
char *start = &buf[4];
- char *fdigit = memchr(start, '\r', len);
+ const char *fdigit = memchr(start, '\r', len);
if(fdigit) {
fdigit--;
if(*fdigit == '\n')
}
else
fdigit = start;
- /* ignores parsing errors, which will make the size remain unknown */
- (void)curlx_strtoofft(fdigit, NULL, 10, &filesize);
-
+ if(Curl_str_number(&fdigit, &filesize, CURL_OFF_T_MAX))
+ filesize = -1; /* size remain unknown */
}
else if(ftpcode == 550) { /* "No such file or directory" */
/* allow a SIZE failure for (resumed) uploads, when probing what command
* those cases only confuses us.
*
* Example D above makes this parsing a little tricky */
- char *bytes;
+ const char *bytes;
char *buf = Curl_dyn_ptr(&conn->proto.ftpc.pp.recvbuf);
bytes = strstr(buf, " bytes");
if(bytes) {
if(bytes) {
++bytes;
/* get the number! */
- (void)curlx_strtoofft(bytes, NULL, 10, &size);
+ if(Curl_str_number(&bytes, &size, CURL_OFF_T_MAX))
+ size = 1;
}
}
}
parser->item_length ++;
if(c == ' ') {
const char *p = &mem[parser->item_offset];
- size_t hlinks;
+ curl_off_t hlinks;
mem[parser->item_offset + parser->item_length - 1] = 0;
if(!Curl_str_number(&p, &hlinks, LONG_MAX)) {
#include "urldata.h"
#include "getinfo.h"
-
#include "vtls/vtls.h"
#include "connect.h" /* Curl_getconnectinfo() */
#include "progress.h"
+#include "strparse.h"
/* The last #include files should be: */
#include "curl_memory.h"
} lptr;
#ifdef DEBUGBUILD
- char *timestr = getenv("CURL_TIME");
+ const char *timestr = getenv("CURL_TIME");
if(timestr) {
- unsigned long val = strtoul(timestr, NULL, 10);
+ curl_off_t val;
+ Curl_str_number(×tr, &val, TIME_T_MAX);
switch(info) {
case CURLINFO_LOCAL_PORT:
*param_longp = (long)val;
/* use another variable for this to allow different values */
timestr = getenv("CURL_DEBUG_SIZE");
if(timestr) {
- unsigned long val = strtoul(timestr, NULL, 10);
+ curl_off_t val;
+ Curl_str_number(×tr, &val, LONG_MAX);
switch(info) {
case CURLINFO_HEADER_SIZE:
case CURLINFO_REQUEST_SIZE:
curl_off_t *param_offt)
{
#ifdef DEBUGBUILD
- char *timestr = getenv("CURL_TIME");
+ const char *timestr = getenv("CURL_TIME");
if(timestr) {
- unsigned long val = strtoul(timestr, NULL, 10);
+ curl_off_t val;
+ Curl_str_number(×tr, &val, CURL_OFF_T_MAX);
+
switch(info) {
case CURLINFO_TOTAL_TIME_T:
case CURLINFO_NAMELOOKUP_TIME_T:
double *param_doublep)
{
#ifdef DEBUGBUILD
- char *timestr = getenv("CURL_TIME");
+ const char *timestr = getenv("CURL_TIME");
if(timestr) {
- unsigned long val = strtoul(timestr, NULL, 10);
+ curl_off_t val;
+ Curl_str_number(×tr, &val, CURL_OFF_T_MAX);
+
switch(info) {
case CURLINFO_TOTAL_TIME:
case CURLINFO_NAMELOOKUP_TIME:
if(!hostp->data)
continue;
if(hostp->data[0] == '-') {
- size_t num = 0;
+ curl_off_t num = 0;
size_t entry_len;
size_t hlen = 0;
host_end = strchr(&hostp->data[1], ':');
const char *addr_begin;
const char *addr_end;
const char *port_ptr;
- size_t port = 0;
+ curl_off_t port = 0;
const char *end_ptr;
bool permanent = TRUE;
bool error = TRUE;
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
if(dns) {
- infof(data, "RESOLVE %.*s:%zd - old addresses discarded",
- (int)hlen, host_begin, port);
+ infof(data, "RESOLVE %.*s:%" CURL_FORMAT_CURL_OFF_T
+ " - old addresses discarded", (int)hlen, host_begin, port);
/* delete old entry, there are two reasons for this
1. old entry may have different addresses.
2. even if entry with correct addresses is already in the cache,
return CURLE_OUT_OF_MEMORY;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- infof(data, "Added %.*s:%zd:%s to DNS cache%s",
+ infof(data, "Added %.*s:%" CURL_FORMAT_CURL_OFF_T ":%s to DNS cache%s",
(int)hlen, host_begin, port, addresses,
permanent ? "" : " (non-permanent)");
#endif
/* Wildcard hostname */
if((hlen == 1) && (host_begin[0] == '*')) {
- infof(data, "RESOLVE *:%zd using wildcard", port);
+ infof(data, "RESOLVE *:%" CURL_FORMAT_CURL_OFF_T " using wildcard",
+ port);
data->state.wildcard_resolve = TRUE;
}
}
#include "curl_get_line.h"
#include "strcase.h"
#include "sendf.h"
-#include "strtoofft.h"
#include "parsedate.h"
#include "fopen.h"
#include "rename.h"
time_t deltatime; /* allow for "adjustments" for unit test purposes */
static time_t hsts_debugtime(void *unused)
{
- char *timestr = getenv("CURL_TIME");
+ const char *timestr = getenv("CURL_TIME");
(void)unused;
if(timestr) {
curl_off_t val;
- (void)curlx_strtoofft(timestr, NULL, 10, &val);
-
- val += (curl_off_t)deltatime;
+ if(!Curl_str_number(×tr, &val, TIME_T_MAX))
+ val += (curl_off_t)deltatime;
return (time_t)val;
}
return time(NULL);
p++;
if(strncasecompare("max-age", p, 7)) {
bool quoted = FALSE;
- CURLofft offt;
- char *endp;
+ int rc;
if(gotma)
return CURLE_BAD_FUNCTION_ARGUMENT;
p++;
quoted = TRUE;
}
- offt = curlx_strtoofft(p, &endp, 10, &expires);
- if(offt == CURL_OFFT_FLOW)
+ rc = Curl_str_number(&p, &expires, TIME_T_MAX);
+ if(rc == STRE_OVERFLOW)
expires = CURL_OFF_T_MAX;
- else if(offt)
+ else if(rc)
/* invalid max-age */
return CURLE_BAD_FUNCTION_ARGUMENT;
- p = endp;
+
if(quoted) {
if(*p != '\"')
return CURLE_BAD_FUNCTION_ARGUMENT;
#include "hsts.h"
#include "ws.h"
#include "curl_ctype.h"
+#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
/* if it truly stopped on a digit */
if(ISDIGIT(*ptr)) {
- if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
- if(data->state.resume_from == k->offset)
- /* we asked for a resume and we got it */
- k->content_range = TRUE;
- }
+ if(!Curl_str_number(&ptr, &k->offset, CURL_OFF_T_MAX) &&
+ (data->state.resume_from == k->offset))
+ /* we asked for a resume and we got it */
+ k->content_range = TRUE;
}
else if(k->httpcode < 300)
data->state.resume_from = 0; /* get everything */
#include "socks.h"
#include "imap.h"
#include "mime.h"
-#include "strtoofft.h"
+#include "strparse.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "cfilters.h"
the continuation data contained within the curly brackets */
ptr = memchr(ptr, '{', len);
if(ptr) {
- char *endptr;
- if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size) &&
- (endptr - ptr > 1 && *endptr == '}'))
+ ptr++;
+ if(!Curl_str_number(&ptr, &size, CURL_OFF_T_MAX) &&
+ !Curl_str_single(&ptr, '}'))
parsed = TRUE;
}
if(do_trace == -1) {
const char *env = getenv("CURL_TRACE");
- do_trace = (env && strtol(env, NULL, 10) > 0);
+ curl_off_t e = 0;
+ if(!Curl_str_number(&env, &e, INT_MAX))
+ do_trace = e > 0;
}
if(!do_trace)
return;
#ifdef CURL_OPENLDAP_DEBUG
if(do_trace < 0) {
const char *env = getenv("CURL_OPENLDAP_TRACE");
- do_trace = (env && strtol(env, NULL, 10) > 0);
+ curl_off_t e = 0;
+ if(!Curl_str_number(&env, &e, INT_MAX))
+ do_trace = e > 0;
}
if(do_trace)
ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace);
date = end;
}
else {
- size_t lval;
+ curl_off_t lval;
int num_digits = 0;
const char *p = date;
if(Curl_str_number(&p, &lval, 99999999))
#include "sendf.h"
#include "transfer.h"
#include "url.h"
+#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
/* Allow debug builds to override this logic to force short initial
sends */
size_t body_len = blen - hds_len;
- char *p = getenv("CURL_SMALLREQSEND");
+ const char *p = getenv("CURL_SMALLREQSEND");
if(p) {
- size_t body_small = (size_t)strtoul(p, NULL, 10);
- if(body_small && body_small < body_len)
- blen = hds_len + body_small;
+ curl_off_t body_small;
+ if(!Curl_str_number(&p, &body_small, body_len))
+ blen = hds_len + (size_t)body_small;
}
}
#endif
CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header)
{
if(checkprefix("CSeq:", header)) {
- size_t CSeq = 0;
+ curl_off_t CSeq = 0;
struct RTSP *rtsp = data->req.p.rtsp;
const char *p = &header[5];
while(ISBLANK(*p))
start++;
end = strchr(start, ';');
if(checkprefix("interleaved=", start)) {
- size_t chan1, chan2, chan;
+ curl_off_t chan1, chan2, chan;
const char *p = start + 12;
if(!Curl_str_number(&p, &chan1, 255)) {
unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
only send the response code instead as per Section 4.2. */
if(line[3] == ' ' || len == 5) {
char tmpline[6];
- size_t code;
+ curl_off_t code;
const char *p = tmpline;
result = TRUE;
memcpy(tmpline, line, (len == 5 ? 5 : 3));
return (char)tolowermap[(unsigned char) in];
}
-/*
- * curl_strequal() is for doing "raw" case insensitive strings. This is meant
- * to be locale independent and only compare strings we know are safe for
- * this. See https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
- * further explanations as to why this function is necessary.
- */
-
-static int casecompare(const char *first, const char *second)
-{
- while(*first) {
- if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
- /* get out of the loop as soon as they do not match */
- return 0;
- first++;
- second++;
- }
- /* If we are here either the strings are the same or the length is different.
- We can just test if the "current" character is non-zero for one and zero
- for the other. Note that the characters may not be exactly the same even
- if they match, we only want to compare zero-ness. */
- return !*first == !*second;
-}
-
-/* --- public function --- */
-int curl_strequal(const char *first, const char *second)
-{
- if(first && second)
- /* both pointers point to something then compare them */
- return casecompare(first, second);
-
- /* if both pointers are NULL then treat them as equal */
- return NULL == first && NULL == second;
-}
-
-static int ncasecompare(const char *first, const char *second, size_t max)
-{
- while(*first && max) {
- if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
- return 0;
- max--;
- first++;
- second++;
- }
- if(0 == max)
- return 1; /* they are equal this far */
-
- return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
-}
-
-/* --- public function --- */
-int curl_strnequal(const char *first, const char *second, size_t max)
-{
- if(first && second)
- /* both pointers point to something then compare them */
- return ncasecompare(first, second, max);
-
- /* if both pointers are NULL then treat them as equal if max is non-zero */
- return NULL == first && NULL == second && max;
-}
/* Copy an upper case version of the string from src to dest. The
* strings may overlap. No more than n characters of the string are copied
* (including any NUL) and the destination string will NOT be
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "strcase.h"
+
+/*
+ * curl_strequal() is for doing "raw" case insensitive strings. This is meant
+ * to be locale independent and only compare strings we know are safe for
+ * this. See https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
+ * further explanations as to why this function is necessary.
+ */
+
+static int casecompare(const char *first, const char *second)
+{
+ while(*first) {
+ if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
+ /* get out of the loop as soon as they do not match */
+ return 0;
+ first++;
+ second++;
+ }
+ /* If we are here either the strings are the same or the length is different.
+ We can just test if the "current" character is non-zero for one and zero
+ for the other. Note that the characters may not be exactly the same even
+ if they match, we only want to compare zero-ness. */
+ return !*first == !*second;
+}
+
+static int ncasecompare(const char *first, const char *second, size_t max)
+{
+ while(*first && max) {
+ if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
+ return 0;
+ max--;
+ first++;
+ second++;
+ }
+ if(0 == max)
+ return 1; /* they are equal this far */
+
+ return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
+}
+
+/* --- public function --- */
+int curl_strequal(const char *first, const char *second)
+{
+ if(first && second)
+ /* both pointers point to something then compare them */
+ return casecompare(first, second);
+
+ /* if both pointers are NULL then treat them as equal */
+ return NULL == first && NULL == second;
+}
+
+/* --- public function --- */
+int curl_strnequal(const char *first, const char *second, size_t max)
+{
+ if(first && second)
+ /* both pointers point to something then compare them */
+ return ncasecompare(first, second, max);
+
+ /* if both pointers are NULL then treat them as equal if max is non-zero */
+ return NULL == first && NULL == second && max;
+}
***************************************************************************/
#include "strparse.h"
+#include "strcase.h"
/* Get a word until the first DELIM or end of string. At least one byte long.
return non-zero on error */
return Curl_str_single(linep, ' ');
}
-/* Get an unsigned number. Leading zeroes are accepted.
- return non-zero on error */
-int Curl_str_number(const char **linep, size_t *nump, size_t max)
+/* given an ASCII hexadecimal character, return the value */
+#define HEXDIGIT2NUM(x) \
+ (((x) > '9') ? Curl_raw_tolower(x) - 'a' + 10 : x - '0')
+
+/* given an ASCII character and a given base, return TRUE if valid */
+#define valid_digit(digit, base) \
+ (((base == 10) && ISDIGIT(digit)) || \
+ ((base == 16) && ISXDIGIT(digit)) || \
+ ((base == 8) && ISODIGIT(digit)))
+
+/* given an ASCII character and a given base, return the value */
+#define num_digit(digit, base) \
+ ((base != 16) ? digit - '0' : HEXDIGIT2NUM(digit))
+
+/* no support for 0x prefix nor leading spaces */
+static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
+ int base) /* 8, 10 or 16, nothing else */
{
- size_t num = 0;
+ curl_off_t num = 0;
DEBUGASSERT(linep && *linep && nump);
+ DEBUGASSERT((base == 8) || (base == 10) || (base == 16));
*nump = 0;
- if(!ISDIGIT(**linep))
+ if(!valid_digit(**linep, base))
return STRE_NO_NUM;
do {
- int n = **linep - '0';
- if(num > ((SIZE_T_MAX - n) / 10))
+ int n = num_digit(**linep, base);
+ if(num > ((CURL_OFF_T_MAX - n) / base))
return STRE_OVERFLOW;
- num = num * 10 + n;
+ num = num * base + n;
if(num > max)
return STRE_BIG; /** too big */
(*linep)++;
- } while(ISDIGIT(**linep));
+ } while(valid_digit(**linep, base));
*nump = num;
return STRE_OK;
}
+/* Get an unsigned decimal number with no leading space or minus. Leading
+ zeroes are accepted. return non-zero on error */
+int Curl_str_number(const char **linep, curl_off_t *nump, curl_off_t max)
+{
+ return str_num_base(linep, nump, max, 10);
+}
+
+/* Get an unsigned hexadecimal number with no leading space or minus and no
+ "0x" support. Leading zeroes are accepted. return non-zero on error */
+int Curl_str_hex(const char **linep, curl_off_t *nump, curl_off_t max)
+{
+ return str_num_base(linep, nump, max, 16);
+}
+
+/* Get an unsigned octal number with no leading space or minus and no "0"
+ prefix support. Leading zeroes are accepted. return non-zero on error */
+int Curl_str_octal(const char **linep, curl_off_t *nump, curl_off_t max)
+{
+ return str_num_base(linep, nump, max, 8);
+}
+
/* CR or LF
return non-zero on error */
int Curl_str_newline(const char **linep)
return non-zero on error */
int Curl_str_singlespace(const char **linep);
-/* Get an unsigned number
- return non-zero on error */
-int Curl_str_number(const char **linep, size_t *nump, size_t max);
+/* Get an unsigned decimal number. Return non-zero on error */
+int Curl_str_number(const char **linep, curl_off_t *nump, curl_off_t max);
+
+/* Get an unsigned hexadecimal number. Return non-zero on error */
+int Curl_str_hex(const char **linep, curl_off_t *nump, curl_off_t max);
+
+/* Get an unsigned octal number. Return non-zero on error */
+int Curl_str_octal(const char **linep, curl_off_t *nump, curl_off_t max);
/* Check for CR or LF
return non-zero on error */
*
***************************************************************************/
-#include <errno.h>
#include "curl_setup.h"
#include "strtoofft.h"
+#include "strparse.h"
/*
- * NOTE:
- *
- * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we
- * could use in case strtoll() does not exist... See
- * https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
- */
-
-#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
-# ifdef HAVE_STRTOLL
-# define strtooff strtoll
-# else
-# if defined(_MSC_VER) && (_MSC_VER >= 1300)
-# if defined(_SAL_VERSION)
- _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
- _In_z_ const char *_String,
- _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
-# else
- _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
- char **_EndPtr, int _Radix);
-# endif
-# define strtooff _strtoi64
-# else
-# define PRIVATE_STRTOOFF 1
-# endif
-# endif
-#else
-# define strtooff strtol
-#endif
-
-#ifdef PRIVATE_STRTOOFF
-
-/* Range tests can be used for alphanum decoding if characters are consecutive,
- like in ASCII. Else an array is scanned. Determine this condition now. */
-
-#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
-
-#define NO_RANGE_TEST
-
-static const char valchars[] =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-#endif
-
-static int get_char(char c, int base);
-
-/**
- * Custom version of the strtooff function. This extracts a curl_off_t
- * value from the given input string and returns it.
- */
-static curl_off_t strtooff(const char *nptr, char **endptr, int base)
-{
- char *end;
- bool is_negative = FALSE;
- bool overflow = FALSE;
- int i;
- curl_off_t value = 0;
-
- /* Skip leading whitespace. */
- end = (char *)nptr;
- while(ISBLANK(end[0])) {
- end++;
- }
-
- /* Handle the sign, if any. */
- if(end[0] == '-') {
- is_negative = TRUE;
- end++;
- }
- else if(end[0] == '+') {
- end++;
- }
- else if(end[0] == '\0') {
- /* We had nothing but perhaps some whitespace -- there was no number. */
- if(endptr) {
- *endptr = end;
- }
- return 0;
- }
-
- /* Handle special beginnings, if present and allowed. */
- if(end[0] == '0' && end[1] == 'x') {
- if(base == 16 || base == 0) {
- end += 2;
- base = 16;
- }
- }
- else if(end[0] == '0') {
- if(base == 8 || base == 0) {
- end++;
- base = 8;
- }
- }
-
- /* Matching strtol, if the base is 0 and it does not look like
- * the number is octal or hex, we assume it is base 10.
- */
- if(base == 0) {
- base = 10;
- }
-
- /* Loop handling digits. */
- for(i = get_char(end[0], base);
- i != -1;
- end++, i = get_char(end[0], base)) {
-
- if(value > (CURL_OFF_T_MAX - i) / base) {
- overflow = TRUE;
- break;
- }
- value = base * value + i;
- }
-
- if(!overflow) {
- if(is_negative) {
- /* Fix the sign. */
- value *= -1;
- }
- }
- else {
- if(is_negative)
- value = CURL_OFF_T_MIN;
- else
- value = CURL_OFF_T_MAX;
-
- errno = ERANGE;
- }
-
- if(endptr)
- *endptr = end;
-
- return value;
-}
-
-/**
- * Returns the value of c in the given base, or -1 if c cannot
- * be interpreted properly in that base (i.e., is out of range,
- * is a null, etc.).
- *
- * @param c the character to interpret according to base
- * @param base the base in which to interpret c
- *
- * @return the value of c in base, or -1 if c is not in range
- */
-static int get_char(char c, int base)
-{
-#ifndef NO_RANGE_TEST
- int value = -1;
- if(c <= '9' && c >= '0') {
- value = c - '0';
- }
- else if(c <= 'Z' && c >= 'A') {
- value = c - 'A' + 10;
- }
- else if(c <= 'z' && c >= 'a') {
- value = c - 'a' + 10;
- }
-#else
- const char *cp;
- int value;
-
- cp = memchr(valchars, c, 10 + 26 + 26);
-
- if(!cp)
- return -1;
-
- value = cp - valchars;
-
- if(value >= 10 + 26)
- value -= 26; /* Lowercase. */
-#endif
-
- if(value >= base) {
- value = -1;
- }
-
- return value;
-}
-#endif /* Only present if we need strtoll, but do not have it. */
-
-/*
- * Parse a *positive* up to 64-bit number written in ASCII.
+ * Parse a positive number up to 63-bit number written in ASCII. Skip leading
+ * blanks. No support for prefixes.
*/
CURLofft curlx_strtoofft(const char *str, char **endp, int base,
curl_off_t *num)
{
- char *end = NULL;
curl_off_t number;
- errno = 0;
+ int rc;
*num = 0; /* clear by default */
- DEBUGASSERT(base); /* starting now, avoid base zero */
+ DEBUGASSERT((base == 10) || (base == 16));
while(*str && ISBLANK(*str))
str++;
- if(('-' == *str) || (ISSPACE(*str))) {
- if(endp)
- *endp = (char *)str; /* did not actually move */
- return CURL_OFFT_INVAL; /* nothing parsed */
- }
- number = strtooff(str, &end, base);
+
+ rc = base == 10 ?
+ Curl_str_number(&str, &number, CURL_OFF_T_MAX) :
+ Curl_str_hex(&str, &number, CURL_OFF_T_MAX);
+
if(endp)
- *endp = end;
- if(errno == ERANGE)
- /* overflow/underflow */
+ *endp = (char *)str;
+ if(rc == STRE_OVERFLOW)
+ /* overflow */
return CURL_OFFT_FLOW;
- else if(str == end)
+ else if(rc)
/* nothing parsed */
return CURL_OFFT_INVAL;
#include "curl_setup.h"
-/*
- * Determine which string to integral data type conversion function we use
- * to implement string conversion to our curl_off_t integral data type.
- *
- * Notice that curl_off_t might be 64 or 32 bits wide, and that it might use
- * an underlying data type which might be 'long', 'int64_t', 'long long' or
- * '__int64' and more remotely other data types.
- *
- * On systems where the size of curl_off_t is greater than the size of 'long'
- * the conversion function to use is strtoll() if it is available, otherwise,
- * we emulate its functionality with our own clone.
- *
- * On systems where the size of curl_off_t is smaller or equal than the size
- * of 'long' the conversion function to use is strtol().
- */
-
typedef enum {
CURL_OFFT_OK, /* parsed fine */
CURL_OFFT_FLOW, /* over or underflow */
/* Window Size */
if(strncasecompare(option, "WS", 2)) {
const char *p = arg;
- size_t x = 0;
- size_t y = 0;
+ curl_off_t x = 0;
+ curl_off_t y = 0;
if(Curl_str_number(&p, &x, 0xffff) ||
Curl_str_single(&p, 'x') ||
Curl_str_number(&p, &y, 0xffff)) {
infof(data, "got option=(%s) value=(%s)", option, value);
if(checkprefix(TFTP_OPTION_BLKSIZE, option)) {
- size_t blksize;
+ curl_off_t blksize;
if(Curl_str_number(&value, &blksize, TFTP_BLKSIZE_MAX)) {
failf(data, "%s (%d)", "blksize is larger than max supported",
TFTP_BLKSIZE_MAX);
/* could realloc pkt buffers here, but the spec does not call out
* support for the server requesting a bigger blksize than the client
* requests */
- failf(data, "server requested blksize larger than allocated (%zd)",
- blksize);
+ failf(data, "server requested blksize larger than allocated (%"
+ CURL_FORMAT_CURL_OFF_T ")", blksize);
return CURLE_TFTP_ILLEGAL;
}
state->blksize, state->requested_blksize);
}
else if(checkprefix(TFTP_OPTION_TSIZE, option)) {
- size_t tsize = 0;
+ curl_off_t tsize = 0;
/* tsize should be ignored on upload: Who cares about the size of the
remote file? */
if(!data->state.upload &&
- !Curl_str_number(&value, &tsize, SIZE_T_MAX)) {
+ !Curl_str_number(&value, &tsize, CURL_OFF_T_MAX)) {
if(!tsize) {
failf(data, "invalid tsize -:%s:- value in OACK packet", value);
return CURLE_TFTP_ILLEGAL;
}
- infof(data, "tsize parsed from OACK (%zd)", tsize);
+ infof(data, "tsize parsed from OACK (%" CURL_FORMAT_CURL_OFF_T ")",
+ tsize);
Curl_pgrsSetDownloadSize(data, tsize);
}
}
if(!uc && zoneid) {
const char *p = zoneid;
- size_t scope;
+ curl_off_t scope;
if(!Curl_str_number(&p, &scope, UINT_MAX))
/* A plain number, use it directly as a scope id. */
conn->scope_id = (unsigned int)scope;
return CURLE_OUT_OF_MEMORY;
}
else {
- size_t port;
+ curl_off_t port;
bool valid = TRUE;
if(data->set.use_port && data->state.allow_port)
port = data->set.use_port;
(void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
if(portptr) {
- size_t num;
+ curl_off_t num;
const char *p = portptr;
if(!Curl_str_number(&p, &num, 0xffff))
port = (int)num;
*host_portno = '\0'; /* cut off number from hostname */
host_portno++;
if(*host_portno) {
- size_t portparse;
+ curl_off_t portparse;
const char *p = host_portno;
if(Curl_str_number(&p, &portparse, 0xffff)) {
failf(data, "No valid port number in connect to host string (%s)",
/* check whether the URL's port matches */
char *ptr_next = strchr(ptr, ':');
if(ptr_next) {
- size_t port_to_match;
+ curl_off_t port_to_match;
if(!Curl_str_number(&ptr, &port_to_match, 0xffff) &&
- (port_to_match == (size_t)conn->remote_port))
+ (port_to_match == (curl_off_t)conn->remote_port))
port_match = TRUE;
ptr = ptr_next + 1;
}
portptr = strchr(hostname, ':');
if(portptr) {
- size_t port;
+ curl_off_t port;
size_t keep = portptr - hostname;
/* Browser behavior adaptation. If there is a colon with no digits after,
u->portnum = (unsigned short) port;
/* generate a new port number string to get rid of leading zeroes etc */
free(u->port);
- u->port = aprintf("%zd", port);
+ u->port = aprintf("%" CURL_FORMAT_CURL_OFF_T, port);
if(!u->port)
return CURLUE_OUT_OF_MEMORY;
}
bool done = FALSE;
int n = 0;
const char *c = Curl_dyn_ptr(host);
- unsigned long parts[4] = {0, 0, 0, 0};
+ unsigned int parts[4] = {0, 0, 0, 0};
CURLcode result = CURLE_OK;
if(*c == '[')
errno = 0; /* for strtoul */
while(!done) {
- char *endp = NULL;
- unsigned long l;
- if(!ISDIGIT(*c))
- /* most importantly this does not allow a leading plus or minus */
- return HOST_NAME;
- l = strtoul(c, &endp, 0);
- if(errno)
- return HOST_NAME;
-#if SIZEOF_LONG > 4
- /* a value larger than 32 bits */
- if(l > UINT_MAX)
+ int rc;
+ curl_off_t l;
+ if(*c == '0') {
+ c++;
+ if(*c == 'x') {
+ c++; /* skip the prefix */
+ rc = Curl_str_hex(&c, &l, UINT_MAX);
+ }
+ else
+ rc = Curl_str_octal(&c, &l, UINT_MAX);
+ }
+ else
+ rc = Curl_str_number(&c, &l, UINT_MAX);
+
+ if(rc)
return HOST_NAME;
-#endif
- parts[n] = l;
- c = endp;
+ parts[n] = (unsigned int)l;
switch(*c) {
case '.':
Curl_dyn_reset(host);
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- (unsigned int)(parts[0] >> 24),
- (unsigned int)((parts[0] >> 16) & 0xff),
- (unsigned int)((parts[0] >> 8) & 0xff),
- (unsigned int)(parts[0] & 0xff));
+ (parts[0] >> 24),
+ ((parts[0] >> 16) & 0xff),
+ ((parts[0] >> 8) & 0xff),
+ (parts[0] & 0xff));
break;
case 1: /* a.b -- 8.24 bits */
if((parts[0] > 0xff) || (parts[1] > 0xffffff))
return HOST_NAME;
Curl_dyn_reset(host);
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- (unsigned int)(parts[0]),
- (unsigned int)((parts[1] >> 16) & 0xff),
- (unsigned int)((parts[1] >> 8) & 0xff),
- (unsigned int)(parts[1] & 0xff));
+ (parts[0]),
+ ((parts[1] >> 16) & 0xff),
+ ((parts[1] >> 8) & 0xff),
+ (parts[1] & 0xff));
break;
case 2: /* a.b.c -- 8.8.16 bits */
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff))
return HOST_NAME;
Curl_dyn_reset(host);
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- (unsigned int)(parts[0]),
- (unsigned int)(parts[1]),
- (unsigned int)((parts[2] >> 8) & 0xff),
- (unsigned int)(parts[2] & 0xff));
+ (parts[0]),
+ (parts[1]),
+ ((parts[2] >> 8) & 0xff),
+ (parts[2] & 0xff));
break;
case 3: /* a.b.c.d -- 8.8.8.8 bits */
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) ||
return HOST_NAME;
Curl_dyn_reset(host);
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- (unsigned int)(parts[0]),
- (unsigned int)(parts[1]),
- (unsigned int)(parts[2]),
- (unsigned int)(parts[3]));
+ (parts[0]),
+ (parts[1]),
+ (parts[2]),
+ (parts[3]));
break;
}
if(result)
return CURLUE_BAD_PORT_NUMBER;
else {
char *tmp;
- size_t port;
+ curl_off_t port;
if(Curl_str_number(&part, &port, 0xffff) || *part)
/* weirdly provided number, not good! */
return CURLUE_BAD_PORT_NUMBER;
- tmp = aprintf("%zd", port);
+ tmp = aprintf("%" CURL_FORMAT_CURL_OFF_T, port);
if(!tmp)
return CURLUE_OUT_OF_MEMORY;
free(u->port);
banfunc strerror
banfunc strncpy
banfunc sscanf
+banfunc strtoul
+banfunc strtol
#endif
#ifdef DEBUGBUILD
{
- char *p = getenv("CURL_DBG_QUIC_WBLOCK");
+ const char *p = getenv("CURL_DBG_QUIC_WBLOCK");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0 && l <= 100)
+ curl_off_t l;
+ if(!Curl_str_number(&p, &l, 100))
qctx->wblock_percent = (int)l;
}
}
/* Now set the new attributes... */
if(strncasecompare(cmd, "chgrp", 5)) {
- sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
+ const char *p = sshc->quote_path1;
+ curl_off_t gid;
+ (void)Curl_str_number(&p, &gid, UINT_MAX);
+ sshc->quote_attrs->gid = (uint32_t)gid;
if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
- !sshc->acceptfail) {
+ !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chgrp gid not a number");
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
}
else if(strncasecompare(cmd, "chmod", 5)) {
- mode_t perms;
- perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
- /* permissions are octal */
- if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) {
+ curl_off_t perms;
+ const char *p = sshc->quote_path1;
+ if(Curl_str_octal(&p, &perms, 07777)) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
}
- sshc->quote_attrs->permissions = perms;
+ sshc->quote_attrs->permissions = (mode_t)perms;
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
}
else if(strncasecompare(cmd, "chown", 5)) {
- sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
+ const char *p = sshc->quote_path1;
+ curl_off_t uid;
+ (void)Curl_str_number(&p, &uid, UINT_MAX);
if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
- !sshc->acceptfail) {
+ !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chown uid not a number");
#include "select.h"
#include "warnless.h"
#include "curl_path.h"
-
+#include "strparse.h"
#include <curl_base64.h> /* for base64 encoding/decoding */
#include <curl_sha256.h>
/* Now set the new attributes... */
if(strncasecompare(cmd, "chgrp", 5)) {
- sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
+ const char *p = sshc->quote_path1;
+ curl_off_t gid;
+ (void)Curl_str_number(&p, &gid, ULONG_MAX);
+ sshp->quote_attrs.gid = (unsigned long)gid;
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
}
}
else if(strncasecompare(cmd, "chmod", 5)) {
- sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
- sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+ curl_off_t perms;
+ const char *p = sshc->quote_path1;
/* permissions are octal */
- if(sshp->quote_attrs.permissions == 0 &&
- !ISDIGIT(sshc->quote_path1[0])) {
+ if(Curl_str_octal(&p, &perms, 07777)) {
failf(data, "Syntax error: chmod permissions not a number");
goto fail;
}
+
+ sshp->quote_attrs.permissions = (unsigned long)perms;
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
}
else if(strncasecompare(cmd, "chown", 5)) {
- sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
+ const char *p = sshc->quote_path1;
+ curl_off_t uid;
+ (void)Curl_str_number(&p, &uid, ULONG_MAX);
+ sshp->quote_attrs.uid = (unsigned long)uid;
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
#include "sendf.h"
#include "progress.h"
#include "curl_path.h"
-#include "strtoofft.h"
#include "transfer.h"
#include "speedcheck.h"
#include "select.h"
banfunc strerror
banfunc strncpy
banfunc sscanf
+banfunc strtoul
+banfunc strtol
#include "multiif.h"
#include "version_win32.h"
#include "rand.h"
+#include "strparse.h"
/* The last #include file should be: */
#include "curl_memory.h"
};
static int
-get_alg_id_by_name(char *name)
+get_alg_id_by_name(const char *name)
{
- char *nameEnd = strchr(name, ':');
+ const char *nameEnd = strchr(name, ':');
size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name);
int i;
set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
ALG_ID *algIds)
{
- char *startCur = ciphers;
+ const char *startCur = ciphers;
int algCount = 0;
while(startCur && (0 != *startCur) && (algCount < NUM_CIPHERS)) {
- long alg = strtol(startCur, 0, 0);
- if(!alg)
+ curl_off_t alg;
+ if(Curl_str_number(&startCur, &alg, INT_MAX) || !alg)
alg = get_alg_id_by_name(startCur);
+
if(alg)
algIds[algCount++] = (ALG_ID)alg;
else if(!strncmp(startCur, "USE_STRONG_CRYPTO",
#include "transfer.h"
#include "select.h"
#include "nonblock.h"
+#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
data->conn->proto.ws = ws;
#ifdef DEBUGBUILD
{
- char *p = getenv("CURL_WS_CHUNK_SIZE");
+ const char *p = getenv("CURL_WS_CHUNK_SIZE");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l > 0 && l <= (1*1024*1024)) {
+ curl_off_t l;
+ if(!Curl_str_number(&p, &l, 1*1024*1024))
chunk_size = (size_t)l;
- }
}
}
#endif
/* Simulate a blocking send after this chunk has been sent */
bool eagain_next = FALSE;
size_t chunk_egain = 0;
- char *p = getenv("CURL_WS_CHUNK_EAGAIN");
+ const char *p = getenv("CURL_WS_CHUNK_EAGAIN");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l > 0 && l <= (1*1024*1024)) {
+ curl_off_t l;
+ if(!Curl_str_number(&p, &l, 1*1024*1024))
chunk_egain = (size_t)l;
- }
}
#endif
for /f "delims=" %%r in ('dir /b ..\src\*.rc') do call :element %1 src "%%r" %3
) else if "!var!" == "CURL_SRC_X_C_FILES" (
call :element %1 lib "strtoofft.c" %3
+ call :element %1 lib "strparse.c" %3
+ call :element %1 lib "strcase.c" %3
call :element %1 lib "timediff.c" %3
call :element %1 lib "nonblock.c" %3
call :element %1 lib "warnless.c" %3
call :element %1 lib "config-win32.h" %3
call :element %1 lib "curl_setup.h" %3
call :element %1 lib "strtoofft.h" %3
+ call :element %1 lib "strparse.h" %3
+ call :element %1 lib "strcase.h" %3
call :element %1 lib "timediff.h" %3
call :element %1 lib "nonblock.h" %3
call :element %1 lib "warnless.h" %3
../lib/dynbuf.c \
../lib/nonblock.c \
../lib/strtoofft.c \
+ ../lib/strparse.c \
+ ../lib/strcase.c \
../lib/timediff.c \
../lib/version_win32.c \
../lib/warnless.c
../lib/dynbuf.h \
../lib/nonblock.h \
../lib/strtoofft.h \
+ ../lib/strparse.h \
+ ../lib/strcase.h \
../lib/timediff.h \
../lib/version_win32.h \
../lib/warnless.h
10: (" 123") 8, [0] line 0
11: ("") 8, [0] line 0
Curl_str_number / max
-0: ("9223372036854775808") 0, [9223372036854775808] line 19
-1: ("9223372036854775809") 0, [9223372036854775809] line 19
-2: ("18446744073709551615") 0, [18446744073709551615] line 20
+0: ("9223372036854775807") 0, [9223372036854775807] line 19
+1: ("9223372036854775808") 7, [0] line 18
+2: ("18446744073709551615") 7, [0] line 19
3: ("18446744073709551616") 7, [0] line 19
4: ("18446744073709551617") 7, [0] line 19
Curl_str_newline
8: ("\r
") 0, line 1
9: ("") 6, line 0
+Curl_str_hex
+0: ("1") 0, [1] line 1
+1: ("1000") 0, [4096] line 4
+2: ("1234") 0, [4660] line 4
+3: ("1235") 0, [4661] line 4
+4: ("1236") 1, [0] line 3
+5: ("01234") 0, [4660] line 5
+6: ("00000000000000000000000000001234") 0, [4660] line 32
+7: ("0123 345") 0, [291] line 4
+8: ("0123O345") 0, [291] line 4
+9: ("-12") 8, [0] line 0
+10: (" 123") 8, [0] line 0
+11: ("") 8, [0] line 0
+Curl_str_octal
+0: ("1") 0, [1] line 1
+1: ("1000") 0, [512] line 4
+2: ("1234") 0, [668] line 4
+3: ("1235") 0, [669] line 4
+4: ("1236") 1, [0] line 3
+5: ("01234") 0, [668] line 5
+6: ("00000000000000000000000000001234") 0, [668] line 32
+7: ("0123 345") 0, [83] line 4
+8: ("0123O345") 0, [83] line 4
+9: ("-12") 8, [0] line 0
+10: (" 123") 8, [0] line 0
+11: ("") 8, [0] line 0
+Curl_str_octal / max
+0: ("777777777777777777777") 0, [9223372036854775807] line 21
+1: ("1000000000000000000000") 7, [0] line 21
+Curl_str_hex / max
+0: ("7FFFFFFFFFFFFFFF") 0, [9223372036854775807] line 16
+1: ("8000000000000000") 7, [0] line 15
</stdout>
</verify>
</testcase>
../../lib/mprintf.c \
../../lib/nonblock.c \
../../lib/strtoofft.c \
+ ../../lib/strparse.c \
+ ../../lib/strequal.c \
../../lib/warnless.c \
../../lib/timediff.c \
../../lib/dynbuf.c \
../../lib/curlx.h \
../../lib/nonblock.h \
../../lib/strtoofft.h \
+ ../../lib/strcase.h \
../../lib/warnless.h \
../../lib/timediff.h \
../../lib/curl_ctype.h \
../../lib/dynbuf.h \
+ ../../lib/strcase.h \
../../lib/strdup.h \
../../lib/curl_get_line.h \
../../lib/curl_multibyte.h
};
printf("Curl_str_number\n");
for(i = 0; nums[i]; i++) {
- size_t num;
+ curl_off_t num;
const char *line = nums[i];
const char *orgline = line;
int rc = Curl_str_number(&line, &num, 1235);
}
{
- /* SIZE_T_MAX is typically 18446744073709551615 */
+ /* CURL_OFF_T is typically 9223372036854775807 */
static const char *nums[] = {
- "9223372036854775808", /* 2^63 */
- "9223372036854775809", /* 2^63 + 1 */
+ "9223372036854775807", /* 2^63 -1 */
+ "9223372036854775808", /* 2^63 */
"18446744073709551615", /* 2^64 - 1 */
"18446744073709551616", /* 2^64 */
"18446744073709551617", /* 2^64 + 1 */
};
printf("Curl_str_number / max\n");
for(i = 0; nums[i]; i++) {
- size_t num;
+ curl_off_t num;
const char *line = nums[i];
const char *orgline = line;
- int rc = Curl_str_number(&line, &num, SIZE_T_MAX);
- printf("%u: (\"%s\") %d, [%zu] line %d\n",
+ int rc = Curl_str_number(&line, &num, CURL_OFF_T_MAX);
+ printf("%u: (\"%s\") %d, [%" CURL_FORMAT_CURL_OFF_T "] line %d\n",
i, orgline, rc, num, (int)(line - orgline));
}
}
}
}
+ {
+ static const char *nums[] = {
+ "1",
+ "1000",
+ "1234",
+ "1235",
+ "1236",
+ "01234",
+ "00000000000000000000000000001234",
+ "0123 345",
+ "0123O345",
+ "-12",
+ " 123",
+ "",
+ NULL
+ };
+ printf("Curl_str_hex\n");
+ for(i = 0; nums[i]; i++) {
+ curl_off_t num;
+ const char *line = nums[i];
+ const char *orgline = line;
+ int rc = Curl_str_hex(&line, &num, 0x1235);
+ printf("%u: (\"%s\") %d, [%u] line %d\n",
+ i, orgline, rc, (int)num, (int)(line - orgline));
+ }
+ }
+
+ {
+ static const char *nums[] = {
+ "1",
+ "1000",
+ "1234",
+ "1235",
+ "1236",
+ "01234",
+ "00000000000000000000000000001234",
+ "0123 345",
+ "0123O345",
+ "-12",
+ " 123",
+ "",
+ NULL
+ };
+ printf("Curl_str_octal\n");
+ for(i = 0; nums[i]; i++) {
+ curl_off_t num;
+ const char *line = nums[i];
+ const char *orgline = line;
+ int rc = Curl_str_octal(&line, &num, 01235);
+ printf("%u: (\"%s\") %d, [%u] line %d\n",
+ i, orgline, rc, (int)num, (int)(line - orgline));
+ }
+ }
+
+ {
+ /* CURL_OFF_T is typically 2^63-1 */
+ static const char *nums[] = {
+ "777777777777777777777", /* 2^63 -1 */
+ "1000000000000000000000", /* 2^63 */
+ NULL
+ };
+ printf("Curl_str_octal / max\n");
+ for(i = 0; nums[i]; i++) {
+ curl_off_t num;
+ const char *line = nums[i];
+ const char *orgline = line;
+ int rc = Curl_str_octal(&line, &num, CURL_OFF_T_MAX);
+ printf("%u: (\"%s\") %d, [%" CURL_FORMAT_CURL_OFF_T "] line %d\n",
+ i, orgline, rc, num, (int)(line - orgline));
+ }
+ }
+
+ {
+ /* CURL_OFF_T is typically 2^63-1 */
+ static const char *nums[] = {
+ "7FFFFFFFFFFFFFFF", /* 2^63 -1 */
+ "8000000000000000", /* 2^63 */
+ NULL
+ };
+ printf("Curl_str_hex / max\n");
+ for(i = 0; nums[i]; i++) {
+ curl_off_t num;
+ const char *line = nums[i];
+ const char *orgline = line;
+ int rc = Curl_str_hex(&line, &num, CURL_OFF_T_MAX);
+ printf("%u: (\"%s\") %d, [%" CURL_FORMAT_CURL_OFF_T "] line %d\n",
+ i, orgline, rc, num, (int)(line - orgline));
+ }
+ }
+
}
UNITTEST_STOP
CURL_FROM_LIBCURL=\
$(CURL_DIROBJ)\nonblock.obj \
$(CURL_DIROBJ)\strtoofft.obj \
+ $(CURL_DIROBJ)\strparse.obj \
+ $(CURL_DIROBJ)\strcase.obj \
$(CURL_DIROBJ)\warnless.obj \
$(CURL_DIROBJ)\curl_get_line.obj \
$(CURL_DIROBJ)\curl_multibyte.obj \
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/nonblock.c
$(CURL_DIROBJ)\strtoofft.obj: ../lib/strtoofft.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/strtoofft.c
+$(CURL_DIROBJ)\strparse.obj: ../lib/strparse.c
+ $(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/strparse.c
+$(CURL_DIROBJ)\strcase.obj: ../lib/strcase.c
+ $(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/strcase.c
$(CURL_DIROBJ)\warnless.obj: ../lib/warnless.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/warnless.c
$(CURL_DIROBJ)\curl_get_line.obj: ../lib/curl_get_line.c