mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-18 02:39:44 +00:00
Improve str.h functions
Add strn_startswith() and strncase_startswith(). Make all str*_startswith() functions take const char * arguments, to make it possible to do safe programming with consts.
This commit is contained in:
parent
0e435683f7
commit
c84b7e5db4
@ -593,7 +593,7 @@ int rhizome_direct_parse_http_request(rhizome_http_request *r)
|
||||
char *content = NULL;
|
||||
int contentlen = 0;
|
||||
char *p;
|
||||
if ((str_startswith(verb, "GET", &p) || str_startswith(verb, "POST", &p)) && isspace(*p)) {
|
||||
if ((str_startswith(verb, "GET", (const char **)&p) || str_startswith(verb, "POST", (const char **)&p)) && isspace(*p)) {
|
||||
*p++ = '\0';
|
||||
path = p;
|
||||
while (p < request_end && !isspace(*p))
|
||||
@ -602,9 +602,9 @@ int rhizome_direct_parse_http_request(rhizome_http_request *r)
|
||||
pathlen = p - path;
|
||||
*p++ = '\0';
|
||||
proto = p;
|
||||
if ( str_startswith(p, "HTTP/1.", &p)
|
||||
&& (str_startswith(p, "0", &p) || str_startswith(p, "1", &p))
|
||||
&& (str_startswith(p, "\r\n", &headers) || str_startswith(p, "\n", &headers))
|
||||
if ( str_startswith(p, "HTTP/1.", (const char **)&p)
|
||||
&& (str_startswith(p, "0", (const char **)&p) || str_startswith(p, "1", (const char **)&p))
|
||||
&& (str_startswith(p, "\r\n", (const char **)&headers) || str_startswith(p, "\n", (const char **)&headers))
|
||||
) {
|
||||
*p = '\0';
|
||||
char *eoh = str_str(headers, "\r\n\r\n", request_end - p);
|
||||
|
@ -1140,7 +1140,7 @@ int unpack_http_response(char *response, struct http_response_parts *parts)
|
||||
parts->content_length = -1;
|
||||
parts->content_start = NULL;
|
||||
char *p = NULL;
|
||||
if (!str_startswith(response, "HTTP/1.0 ", &p)) {
|
||||
if (!str_startswith(response, "HTTP/1.0 ", (const char **)&p)) {
|
||||
if (debug&DEBUG_RHIZOME_RX)
|
||||
DEBUGF("Malformed HTTP reply: missing HTTP/1.0 preamble");
|
||||
return -1;
|
||||
@ -1160,7 +1160,7 @@ int unpack_http_response(char *response, struct http_response_parts *parts)
|
||||
*p++ = '\0';
|
||||
// Iterate over header lines until the last blank line.
|
||||
while (!(p[0] == '\n' || (p[0] == '\r' && p[1] == '\n'))) {
|
||||
if (strcase_startswith(p, "Content-Length:", &p)) {
|
||||
if (strcase_startswith(p, "Content-Length:", (const char **)&p)) {
|
||||
while (*p == ' ')
|
||||
++p;
|
||||
parts->content_length = 0;
|
||||
|
@ -501,10 +501,10 @@ int rhizome_server_parse_http_request(rhizome_http_request *r)
|
||||
// Parse the HTTP "GET" line.
|
||||
char *path = NULL;
|
||||
size_t pathlen = 0;
|
||||
if (str_startswith(r->request, "POST ", &path)) {
|
||||
if (str_startswith(r->request, "POST ", (const char **)&path)) {
|
||||
return rhizome_direct_parse_http_request(r);
|
||||
} else if (str_startswith(r->request, "GET ", &path)) {
|
||||
char *p;
|
||||
} else if (str_startswith(r->request, "GET ", (const char **)&path)) {
|
||||
const char *p;
|
||||
// This loop is guaranteed to terminate before the end of the buffer, because we know that the
|
||||
// buffer contains at least "\n\n" and maybe "\r\n\r\n" at the end of the header block.
|
||||
for (p = path; !isspace(*p); ++p)
|
||||
@ -533,7 +533,7 @@ int rhizome_server_parse_http_request(rhizome_http_request *r)
|
||||
} else if (strcmp(path, "/rhizome/bars") == 0) {
|
||||
/* Return the list of known BARs */
|
||||
rhizome_server_sql_query_http_response(r, "bar", "manifests", "from manifests", 32, 0);
|
||||
} else if (str_startswith(path, "/rhizome/file/", &id)) {
|
||||
} else if (str_startswith(path, "/rhizome/file/", (const char **)&id)) {
|
||||
/* Stream the specified payload */
|
||||
if (!rhizome_str_is_file_hash(id)) {
|
||||
rhizome_server_simple_http_response(r, 400, "<html><h1>Invalid payload ID</h1></html>\r\n");
|
||||
@ -553,10 +553,10 @@ int rhizome_server_parse_http_request(rhizome_http_request *r)
|
||||
r->request_type |= RHIZOME_HTTP_REQUEST_BLOB;
|
||||
}
|
||||
}
|
||||
} else if (str_startswith(path, "/rhizome/manifest/", &id)) {
|
||||
} else if (str_startswith(path, "/rhizome/manifest/", (const char **)&id)) {
|
||||
// TODO: Stream the specified manifest
|
||||
rhizome_server_simple_http_response(r, 500, "<html><h1>Not implemented</h1></html>\r\n");
|
||||
} else if (str_startswith(path, "/rhizome/manifestbyprefix/", &id)) {
|
||||
} else if (str_startswith(path, "/rhizome/manifestbyprefix/", (const char **)&id)) {
|
||||
/* Manifest by prefix */
|
||||
char bid_low[RHIZOME_MANIFEST_ID_STRLEN+1];
|
||||
char bid_high[RHIZOME_MANIFEST_ID_STRLEN+1];
|
||||
|
28
str.c
28
str.c
@ -85,7 +85,7 @@ char *str_toupper_inplace(char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
int str_startswith(char *str, const char *substring, char **afterp)
|
||||
int str_startswith(const char *str, const char *substring, const char **afterp)
|
||||
{
|
||||
while (*substring && *substring == *str)
|
||||
++substring, ++str;
|
||||
@ -96,7 +96,18 @@ int str_startswith(char *str, const char *substring, char **afterp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int strcase_startswith(char *str, const char *substring, char **afterp)
|
||||
int strn_startswith(const char *str, size_t len, const char *substring, const char **afterp)
|
||||
{
|
||||
while (len && *substring && *substring == *str)
|
||||
--len, ++substring, ++str;
|
||||
if (*substring)
|
||||
return 0;
|
||||
if (afterp)
|
||||
*afterp = str;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int strcase_startswith(const char *str, const char *substring, const char **afterp)
|
||||
{
|
||||
while (*substring && *str && toupper(*substring) == toupper(*str))
|
||||
++substring, ++str;
|
||||
@ -107,6 +118,17 @@ int strcase_startswith(char *str, const char *substring, char **afterp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int strncase_startswith(const char *str, size_t len, const char *substring, const char **afterp)
|
||||
{
|
||||
while (len && *substring && toupper(*substring) == toupper(*str))
|
||||
--len, ++substring, ++str;
|
||||
if (*substring)
|
||||
return 0;
|
||||
if (afterp)
|
||||
*afterp = str;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_argv(char *cmdline, char delim, char **argv, int max_argv)
|
||||
{
|
||||
int argc=0;
|
||||
@ -139,7 +161,7 @@ char *str_str(char *haystack, const char *needle, int haystack_len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int str_to_ll_scaled(const char *str, int base, long long *result, char **afterp)
|
||||
int str_to_ll_scaled(const char *str, int base, long long *result, const char **afterp)
|
||||
{
|
||||
if (!(isdigit(*str) || *str == '-' || *str == '+'))
|
||||
return 0;
|
||||
|
26
str.h
26
str.h
@ -82,9 +82,9 @@ size_t str_fromprint(unsigned char *dst, const char *src);
|
||||
#define alloca_toprint(dstlen,buf,len) toprint((char *)alloca((dstlen) == -1 ? toprint_len((const char *)(buf),(len), "``") + 1 : (dstlen)), (dstlen), (const char *)(buf), (len), "``")
|
||||
#define alloca_str_toprint(str) toprint_str((char *)alloca(toprint_str_len(str, "``") + 1), -1, (str), "``")
|
||||
|
||||
/* Check if a given string starts with a given sub-string. If so, return 1 and, if afterp is not
|
||||
* NULL, set *afterp to point to the character immediately following the substring. Otherwise
|
||||
* return 0.
|
||||
/* Check if a given nul-terminated string 'str' starts with a given nul-terminated sub-string. If
|
||||
* so, return 1 and, if afterp is not NULL, set *afterp to point to the character in 'str'
|
||||
* immediately following the substring. Otherwise return 0.
|
||||
*
|
||||
* This function is used to parse HTTP headers and responses, which are typically not
|
||||
* nul-terminated, but are held in a buffer which has an associated length. To avoid this function
|
||||
@ -95,11 +95,25 @@ size_t str_fromprint(unsigned char *dst, const char *src);
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int str_startswith(char *str, const char *substring, char **afterp);
|
||||
int str_startswith(const char *str, const char *substring, const char **afterp);
|
||||
|
||||
/* Check if a given string 'str' of a given length 'len' starts with a given nul-terminated
|
||||
* sub-string. If so, return 1 and, if afterp is not NULL, set *afterp to point to the character
|
||||
* immediately following the substring. Otherwise return 0.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int strn_startswith(const char *str, size_t len, const char *substring, const char **afterp);
|
||||
|
||||
/* Case-insensitive form of str_startswith().
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int strcase_startswith(char *str, const char *substring, char **afterp);
|
||||
int strcase_startswith(const char *str, const char *substring, const char **afterp);
|
||||
|
||||
/* Case-insensitive form of strn_startswith().
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int strncase_startswith(const char *str, size_t len, const char *substring, const char **afterp);
|
||||
|
||||
/* like strstr(3), but doesn't depend on null termination.
|
||||
*
|
||||
@ -122,7 +136,7 @@ char *str_str(char *haystack, const char *needle, int haystack_len);
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int str_to_ll_scaled(const char *str, int base, long long *result, char **afterp);
|
||||
int str_to_ll_scaled(const char *str, int base, long long *result, const char **afterp);
|
||||
|
||||
|
||||
int parse_argv(char *cmdline, char delim, char **argv, int max_argv);
|
||||
|
@ -53,7 +53,7 @@ int main(int argc, char **argv)
|
||||
const char *label = "";
|
||||
int i;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
char *arg = argv[i];
|
||||
const char *arg = argv[i];
|
||||
if (str_startswith(arg, "--size=", &arg)) {
|
||||
if (!str_to_ll_scaled(arg, 10, &size, NULL) || size < 0)
|
||||
fatal("illegal --size= argument: %s", arg);
|
||||
|
Loading…
Reference in New Issue
Block a user