From: Tollef Fog Heen Date: Mon, 12 Oct 2009 08:25:38 +0000 (+0200) Subject: Add utility functions X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3b7ad20996e659957178725a34e119e6d01ee96;p=yubikey-server-c Add utility functions --- diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..94d7793 --- /dev/null +++ b/src/util.c @@ -0,0 +1,172 @@ + +#include +#include +#include +#include +#include +#include +#include "util.h" + +void *ysc_memdup(void *p, size_t len) +{ + void *r; + r = malloc(len); + assert(r != NULL); + memcpy(r, p, len); + return r; +} + +size_t ysc_nstrstr(const char *haystack, const char *needle) +{ + size_t n = 0; + while ((haystack = strstr(haystack, needle)) != NULL) { + n++; + haystack += strlen(needle); + } + return n; +} + + +/* Like strftime, but better, calls strftime under the hood + %N => nanoseconds (not implemented) + %v => milliseconds + + if tv is null, call gettimeofday for you +*/ + +size_t ysc_strftime(char *s, size_t max, const char *format, + const struct timeval *tv) { + struct tm tm; + int i, j, flen; + struct timeval tvv; + /* '%v' is two bytes less than what a %v needs */ + size_t fdup_len = strlen(format) + ysc_nstrstr(format, "%v") * 2; + char *fdup = malloc(fdup_len); /* XXX check failure */ + size_t r; + + if (tv == NULL) + assert(gettimeofday(&tvv, NULL) == 0); + else { + memcpy(&tvv, tv, sizeof(struct timeval)); + } + gmtime_r(&tvv.tv_sec, &tm); + /* Do %N and %v first, then hand off to strftime */ + flen = strlen(format); + for (i = 0, j = 0; i < flen; i++, j++) { + if (format[i] == '%') { + switch (format[i+1]) { +/* case 'N': + break; +*/ + case 'v': + j += snprintf(fdup+j, 4, "%.3zd", + tvv.tv_usec / 1000); + i++; + continue; + break; + default: + fdup[j] = format[i]; + continue; + } + } else { + fdup[j] = format[i]; + } + } + r = strftime(s, max, fdup, &tm); + free(fdup); + return r; +} + +/* Base 64 functions */ + +/* + * AUTHOR: Bob Trower 08/04/01 + * + * COPYRIGHT: Copyright (c) Trantor Standard Systems Inc., 2001 + * + * LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +unsigned char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static void ysc_b64_encodeblock(unsigned char in[3], unsigned char out[4], int len) +{ + out[0] = cb64[in[0] >> 2]; + out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; + out[2] = (unsigned char) (len > 1 ? cb64[((in[1] & 0x0f) << 2) | + ((in[2] & 0xc0) >> 6)] : '='); + out[3] = (unsigned char) (len > 2 ? cb64[in[2] & 0x3f] : '='); +} + +char *ysc_b64_encode(char *s, ssize_t len) +{ + char *r = malloc((len/3+1)*4+1); + char *tmp = r; + unsigned char out[4]; + + while (len > 0) { + ysc_b64_encodeblock((unsigned char*)s, out, len); + memcpy(tmp, out, 4); + tmp += 4; + len -= 3; + s += 3; + } + return r; +} + +static void ysc_b64_decodeblock(unsigned const char in[4], unsigned char out[3]) +{ + out[0] = (unsigned char) ((in[0] - 'A') << 2 | (in[1] - 'A') >> 4); + out[1] = (unsigned char) ((in[1] - 'A') << 4 | (in[2] - 'A') >> 2); + out[2] = (unsigned char) ((((in[2] - 'A') << 6) & 0xc0) | (in[3] - 'A')); +} + +ssize_t ysc_b64_decode(char *s, char **decoded) +{ + ssize_t len = strlen(s); + char *tmp; + unsigned char out[3]; + ssize_t r = 0; + + *decoded = malloc((len/4+1)*3+1); + tmp = *decoded; + if ((len % 4) != 0) { + return 0; + /* XXX free memory */ + } + + while (*s != '\0') { + ysc_b64_decodeblock((unsigned char*)s, out); + memcpy(tmp, out, 3); + tmp += 3; + if (s[2] == '=') { + r += 1; + } else if (s[3] == '=') { + r += 2; + } else { + r += 3; + } + s += 4; + } + return r; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..5a2e8dc --- /dev/null +++ b/src/util.h @@ -0,0 +1,17 @@ + +#ifndef ysc_util_h__ +#define ysc_util_h__ + +#include + +void *ysc_memdup(void *p, size_t len); +size_t ysc_nstrstr(const char *haystack, const char *needle); + +size_t ysc_strftime(char *s, size_t max, const char *format, + const struct timeval *tv); + +char *ysc_b64_encode(char *s, ssize_t len); +ssize_t ysc_b64_decode(char *s, char **r); + + +#endif /* ysc_util_h */