1
0
mirror of https://git.kore.io/kore.git synced 2024-11-12 05:10:48 +01:00
kore/src/utils.c

419 lines
7.6 KiB
C
Raw Normal View History

2013-04-17 22:34:27 +02:00
/*
* Copyright (c) 2013 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "kore.h"
static struct {
char *name;
int value;
} month_names[] = {
{ "Jan", 0 },
{ "Feb", 1 },
{ "Mar", 2 },
{ "Apr", 3 },
{ "May", 4 },
{ "Jun", 5 },
{ "Jul", 6 },
{ "Aug", 7 },
{ "Sep", 8 },
{ "Oct", 9 },
{ "Nov", 10 },
{ "Dec", 11 },
{ NULL, 0 },
};
static char b64table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2013-04-17 22:34:27 +02:00
void
kore_debug_internal(char *file, int line, const char *fmt, ...)
2013-04-17 22:34:27 +02:00
{
va_list args;
char buf[2048];
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
2013-06-26 11:18:32 +02:00
printf("[%d] %s:%d - %s\n", kore_pid, file, line, buf);
2013-04-17 22:34:27 +02:00
}
void
kore_log_init(void)
{
openlog("kore", LOG_NDELAY | LOG_PID, LOG_DAEMON);
}
void
kore_log(int prio, const char *fmt, ...)
{
va_list args;
char buf[2048];
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
2013-06-24 09:36:40 +02:00
if (worker != NULL)
syslog(prio, "[wrk %d]: %s", worker->id, buf);
else
syslog(prio, "[parent]: %s", buf);
}
void
kore_strlcpy(char *dst, const char *src, size_t len)
{
char *d = dst;
const char *s = src;
while ((*d++ = *s++) != '\0') {
if (d == (dst + len - 1)) {
*d = '\0';
break;
}
}
}
long long
kore_strtonum(const char *str, int base, long long min, long long max, int *err)
2013-05-01 16:03:48 +02:00
{
long long l;
2013-05-01 16:03:48 +02:00
char *ep;
if (min > max) {
*err = KORE_RESULT_ERROR;
return (0);
}
l = 0;
errno = 0;
l = strtoll(str, &ep, base);
2013-05-01 16:03:48 +02:00
if (errno != 0 || str == ep || *ep != '\0') {
*err = KORE_RESULT_ERROR;
return (0);
}
if (l < min) {
*err = KORE_RESULT_ERROR;
return (0);
}
if (l > max) {
*err = KORE_RESULT_ERROR;
return (0);
}
*err = KORE_RESULT_OK;
return (l);
}
int
kore_split_string(char *input, char *delim, char **out, size_t ele)
{
int count;
char **ap;
count = 0;
for (ap = out; ap < &out[ele - 1] &&
(*ap = strsep(&input, delim)) != NULL;) {
if (**ap != '\0') {
ap++;
count++;
}
}
*ap = NULL;
return (count);
}
void
kore_strip_chars(char *in, char strip, char **out)
{
u_int32_t len;
char *s, *p;
len = strlen(in);
*out = kore_malloc(len + 1);
p = *out;
for (s = in; s < (in + len); s++) {
if (*s == strip)
continue;
*p++ = *s;
}
*p = '\0';
}
time_t
kore_date_to_time(char *http_date)
{
time_t t;
int err, i;
struct tm tm, *ltm;
char *args[7], *tbuf[5], *sdup;
time(&t);
ltm = localtime(&t);
sdup = kore_strdup(http_date);
t = KORE_RESULT_ERROR;
if (kore_split_string(sdup, " ", args, 7) != 6) {
kore_debug("misformed http-date: '%s'", http_date);
goto out;
}
memset(&tm, 0, sizeof(tm));
tm.tm_year = kore_strtonum(args[3], 10, 1900, 2068, &err) - 1900;
if (err == KORE_RESULT_ERROR) {
kore_debug("misformed year in http-date: '%s'", http_date);
goto out;
}
for (i = 0; month_names[i].name != NULL; i++) {
if (!strcmp(month_names[i].name, args[2])) {
tm.tm_mon = month_names[i].value;
break;
}
}
if (month_names[i].name == NULL) {
kore_debug("misformed month in http-date: '%s'", http_date);
goto out;
}
tm.tm_mday = kore_strtonum(args[1], 10, 1, 31, &err);
if (err == KORE_RESULT_ERROR) {
kore_debug("misformed mday in http-date: '%s'", http_date);
goto out;
}
if (kore_split_string(args[4], ":", tbuf, 5) != 3) {
kore_debug("misformed HH:MM:SS in http-date: '%s'", http_date);
goto out;
}
tm.tm_hour = kore_strtonum(tbuf[0], 10, 0, 23, &err);
if (err == KORE_RESULT_ERROR) {
kore_debug("misformed hour in http-date: '%s'", http_date);
goto out;
}
tm.tm_min = kore_strtonum(tbuf[1], 10, 0, 59, &err);
if (err == KORE_RESULT_ERROR) {
kore_debug("misformed minutes in http-date: '%s'", http_date);
goto out;
}
tm.tm_sec = kore_strtonum(tbuf[2], 10, 0, 60, &err);
if (err == KORE_RESULT_ERROR) {
kore_debug("misformed seconds in http-date: '%s'", http_date);
goto out;
}
tm.tm_isdst = ltm->tm_isdst;
t = mktime(&tm) + ltm->tm_gmtoff;
if (t == -1) {
t = 0;
kore_debug("mktime() on '%s' failed", http_date);
}
out:
kore_mem_free(sdup);
return (t);
}
char *
kore_time_to_date(time_t now)
{
struct tm *tm;
static time_t last = 0;
static char tbuf[32];
if (now != last) {
last = now;
tm = gmtime(&now);
if (!strftime(tbuf, sizeof(tbuf), "%a, %d %b %Y %T GMT", tm)) {
kore_debug("strftime() gave us NULL (%ld)", now);
return (NULL);
}
}
return (tbuf);
}
2013-06-24 09:36:40 +02:00
u_int64_t
kore_time_ms(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) == -1)
return (0);
return (tv.tv_sec * 1000 + (tv.tv_usec / 1000));
2013-06-24 09:36:40 +02:00
}
int
kore_base64_encode(u_int8_t *data, u_int32_t len, char **out)
{
struct kore_buf *res;
u_int8_t n, *pdata;
int i, padding;
u_int32_t idx, b, plen;
if ((len % 3) != 0) {
padding = 3 - (len % 3);
plen = len + padding;
pdata = kore_malloc(plen);
memcpy(pdata, data, len);
memset(pdata + len, 0, padding);
} else {
plen = len;
padding = 0;
pdata = data;
}
res = kore_buf_create(plen);
i = 2;
b = 0;
for (idx = 0; idx < plen; idx++) {
b |= (pdata[idx] << (i * 8));
if (i-- == 0) {
for (i = 3; i >= 0; i--) {
n = (b >> (6 * i)) & 0x3f;
if (n >= sizeof(b64table)) {
kore_debug("unable to encode %d", n);
kore_buf_free(res);
return (KORE_RESULT_ERROR);
}
if (idx >= len && i < padding)
break;
2013-08-26 08:52:56 +02:00
kore_buf_append(res, &(b64table[n]), 1);
}
b = 0;
i = 2;
}
}
for (i = 0; i < padding; i++)
kore_buf_append(res, (u_int8_t *)"=", 1);
if (pdata != data)
kore_mem_free(pdata);
pdata = kore_buf_release(res, &plen);
*out = kore_malloc(plen + 1);
kore_strlcpy(*out, (char *)pdata, plen + 1);
kore_mem_free(pdata);
return (KORE_RESULT_OK);
}
int
kore_base64_decode(char *in, u_int8_t **out, u_int32_t *olen)
{
int i;
struct kore_buf *res;
u_int8_t d, n, o;
u_int32_t b, len, idx;
i = 3;
b = 0;
d = 0;
len = strlen(in);
res = kore_buf_create(len);
for (idx = 0; idx < len; idx++) {
if (in[idx] == '=')
break;
for (o = 0; o < sizeof(b64table); o++) {
if (b64table[o] == in[idx]) {
d = o;
break;
}
}
if (o == sizeof(b64table))
fatal("bad b64 character: %c", in[idx]);
b |= (d & 0x3f) << (i * 6);
if (i-- == 0) {
for (i = 2; i >= 0; i--) {
n = (b >> (8 * i));
kore_buf_append(res, &n, 1);
}
b = 0;
i = 3;
}
}
o = len - idx;
if (o > 0) {
for (i = 2; i >= o; i--) {
n = (b >> (8 * i));
kore_buf_append(res, &n, 1);
}
}
*out = kore_buf_release(res, olen);
return (KORE_RESULT_OK);
}
void *
kore_mem_find(void *src, size_t slen, void *needle, u_int32_t len)
{
u_int8_t *p, *end;
end = (u_int8_t *)src + slen;
for (p = src; p < end; p++) {
if (*p != *(u_int8_t *)needle)
continue;
if ((end - p) < len)
return (NULL);
if (!memcmp(p, needle, len))
return (p);
}
return (NULL);
}
2013-04-17 22:34:27 +02:00
void
fatal(const char *fmt, ...)
{
va_list args;
char buf[2048];
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
kore_log(LOG_ERR, "%s", buf);
printf("kore: %s\n", buf);
2013-04-17 22:34:27 +02:00
exit(1);
}