master uint/parados / server / util.c
  1#include <ctype.h>
  2#include <errno.h>
  3#include <stdio.h>
  4#include <string.h>
  5#include <unistd.h>
  6
  7#include "util.h"
  8
  9static int ci_key_match(const char* a, const char* b, size_t n);
 10
 11/**
 12 * @brief Compare two header keys case-insensitively
 13 *
 14 * @param a Left string
 15 * @param b Right string
 16 * @param n Number of bytes to compare
 17 *
 18 * @return 1=Match, 0=No match
 19 */
 20static int ci_key_match(const char* a, const char* b, size_t n)
 21{
 22	for (size_t i = 0; i < n; i++) {
 23		unsigned char ca = (unsigned char)a[i];
 24		unsigned char cb = (unsigned char)b[i];
 25		if (tolower(ca) != tolower(cb))
 26			return 0;
 27	}
 28	return 1;
 29}
 30
 31const char* cistrstr(const char* hay, const char* nee)
 32{
 33	size_t nl = strlen(nee);
 34	if (nl == 0)
 35		return hay;
 36
 37	for (; *hay; hay++) {
 38		size_t i = 0;
 39
 40		for (;;) {
 41			if (i == nl)
 42				return hay;
 43
 44			unsigned char a = (unsigned char)hay[i];
 45			unsigned char b = (unsigned char)nee[i];
 46
 47			if (a == '\0')
 48				break;
 49
 50			if (tolower(a) != tolower(b))
 51				break;
 52
 53			i++;
 54		}
 55	}
 56
 57	return NULL;
 58}
 59
 60int hdr_get_value(char out[512], const char* hdr, const char* key)
 61{
 62	size_t klen = strlen(key);
 63	if (!hdr || !key || klen == 0)
 64		return -1;
 65
 66	const char* p = hdr;
 67
 68	/* skip request line */
 69	const char* eol = strstr(p, "\r\n");
 70	if (!eol)
 71		return -1;
 72	p = eol + 2;
 73
 74	for (;;) {
 75		if (p[0] == '\r' && p[1] == '\n')
 76			break; /* end of headers */
 77
 78		const char* line_end = strstr(p, "\r\n");
 79		if (!line_end)
 80			break;
 81
 82		const char* colon = memchr(p, ':', (size_t)(line_end - p));
 83		if (colon) {
 84			size_t n = (size_t)(colon - p);
 85
 86			if (n == klen && ci_key_match(p, key, klen)) {
 87				const char* v = colon + 1;
 88				while (*v == ' ' || *v == '\t')
 89					v++;
 90
 91				size_t outn = 0;
 92				while (v < line_end) {
 93					if (outn + 1 >= 512)
 94						return -1;
 95					out[outn++] = *v++;
 96				}
 97				out[outn] = '\0';
 98
 99				if (outn == 0)
100					return -1;
101
102				return 0;
103			}
104		}
105
106		p = line_end + 2;
107	}
108
109	return -1;
110}
111
112int join_path(char* out, size_t outsz, const char* a, const char* b)
113{
114	if (!out || outsz == 0 || !a || !b)
115		return -1;
116
117	if (a[0] == '\0') {
118		int n = snprintf(out, outsz, "%s", b);
119		if (n < 0 || (size_t)n >= outsz)
120			return -1;
121		return 0;
122	}
123
124	if (b[0] == '\0') {
125		int n = snprintf(out, outsz, "%s", a);
126		if (n < 0 || (size_t)n >= outsz)
127			return -1;
128		return 0;
129	}
130
131	size_t al = strlen(a);
132
133	/* avoid double slashes */
134	if (a[al - 1] == '/')
135		return snprintf(out, outsz, "%s%s", a, b) < (int)outsz ? 0 : -1;
136
137	return snprintf(out, outsz, "%s/%s", a, b) < (int)outsz ? 0 : -1;
138}
139
140void secure_bzero(void* p, size_t n)
141{
142	if (!p || n == 0)
143		return;
144
145#if defined(__OpenBSD__)
146	explicit_bzero(p, n);
147#else
148	volatile unsigned char* vp = (volatile unsigned char*)p;
149	while (n--)
150		*vp++ = 0;
151#endif
152}
153
154int write_all(int fd, const void* buf, size_t n)
155{
156	const char* p = buf;
157
158	while (n > 0) {
159		ssize_t w = write(fd, p, n);
160		if (w < 0) {
161			if (errno == EINTR)
162				continue;
163			return -1;
164		}
165
166		p += (size_t)w;
167		n -= (size_t)w;
168	}
169
170	return 0;
171}