/* ** OSSP l2 - Flexible Logging ** Copyright (c) 2001-2005 Cable & Wireless ** Copyright (c) 2001-2005 The OSSP Project ** Copyright (c) 2001-2005 Ralf S. Engelschall ** ** This file is part of OSSP l2, a flexible logging library which ** can be found at http://www.ossp.org/pkg/lib/l2/. ** ** 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. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** l2_format.c: extra formatters */ #include #include "l2.h" #include l2_result_t l2_util_fmt_string( l2_context_t *ctx, const char id, const char *param, char *bufptr, size_t bufsize, size_t *buflen, va_list *ap) { char *cpStr; size_t nStr; cpStr = va_arg(*ap, char *); nStr = (size_t)va_arg(*ap, int); if (cpStr == NULL) return L2_ERR_ARG; if (nStr > bufsize) return L2_ERR_MEM; memcpy(bufptr, cpStr, nStr); *buflen = nStr; return L2_OK; } l2_result_t l2_util_fmt_dump( l2_context_t *ctx, const char id, const char *param, char *bufptr, size_t bufsize, size_t *buflen, va_list *ap) { static const char hex_table[] = "0123456789abcdef"; static const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; unsigned char base64_in[3]; unsigned char base64_out[4]; size_t nData; unsigned char *ucpData; unsigned char uc; unsigned char *cpO; unsigned char *cpI; int i; int n; /* fetch data pointer and data size from argument list */ ucpData = va_arg(*ap, unsigned char *); nData = (size_t)va_arg(*ap, int); /* argument sanity check */ if (ucpData == NULL) return L2_ERR_ARG; /* * textual dumping: "foo\1bar" -> "foo\x01bar" */ if (strcmp(param, "text") == 0 || param[0] == '\0') { cpI = ucpData; cpO = (unsigned char *)bufptr; while (cpI < (ucpData+nData)) { uc = *cpI++; if (isprint((int)uc)) { if ((char *)cpO >= (bufptr+bufsize)) return L2_ERR_MEM; *cpO++ = uc; } else if (uc == '\\') { if ((char *)(cpO+1) >= (bufptr+bufsize)) return L2_ERR_MEM; *cpO++ = '\\'; *cpO++ = '\\'; } else if (uc == '\t' || uc == '\r' || uc == '\n') { if ((char *)(cpO+1) >= (bufptr+bufsize)) return L2_ERR_MEM; *cpO++ = '\\'; switch ((int)uc) { case '\t': *cpO++ = 't'; break; case '\r': *cpO++ = 'r'; break; case '\n': *cpO++ = 'n'; break; default: break; } } else { if ((char *)(cpO+3) >= (bufptr+bufsize)) return L2_ERR_MEM; *cpO++ = '\\'; *cpO++ = 'x'; *cpO++ = hex_table[(uc >> 4) & 0xf]; *cpO++ = hex_table[uc & 0xf]; } } *buflen = ((char *)cpO - bufptr); } /* * hexadecimal dumping: "foo\1bar" -> "66:6f:6f:01:62:61:72" */ else if (strcmp(param, "hex") == 0) { if (((nData * 3) - 1) > bufsize) return L2_ERR_MEM; cpO = (unsigned char *)bufptr; for (i = 0; i < nData; i++) { uc = *ucpData++; *cpO++ = hex_table[(uc >> 4) & 0xf]; *cpO++ = hex_table[uc & 0xf]; if (i < (nData - 1)) *cpO++ = ':'; } *buflen = (nData * 3) - 1; } /* * Base64 dumping: "foo\1bar" -> "Zm9vAWJhcg==" */ else if (strcmp(param, "base64") == 0) { /* bulk encoding */ n = 0; while (nData >= 3) { base64_in[0] = *ucpData++; base64_in[1] = *ucpData++; base64_in[2] = *ucpData++; nData -= 3; base64_out[0] = ( base64_in[0] >> 2); base64_out[1] = ((base64_in[0] & 0x03) << 4) + (base64_in[1] >> 4); base64_out[2] = ((base64_in[1] & 0x0f) << 2) + (base64_in[2] >> 6); base64_out[3] = ( base64_in[2] & 0x3f); if (n + 4 > bufsize) return L2_ERR_MEM; bufptr[n++] = base64_table[base64_out[0]]; bufptr[n++] = base64_table[base64_out[1]]; bufptr[n++] = base64_table[base64_out[2]]; bufptr[n++] = base64_table[base64_out[3]]; } /* now worry about padding with remaining 1 or 2 bytes */ if (nData != 0) { base64_in[0] = base64_in[1] = base64_in[2] = '\0'; for (i = 0; i < nData; i++) base64_in[i] = *ucpData++; base64_out[0] = ( base64_in[0] >> 2); base64_out[1] = ((base64_in[0] & 0x03) << 4) + (base64_in[1] >> 4); base64_out[2] = ((base64_in[1] & 0x0f) << 2) + (base64_in[2] >> 6); if (n + 4 > bufsize) return L2_ERR_MEM; bufptr[n++] = base64_table[base64_out[0]]; bufptr[n++] = base64_table[base64_out[1]]; if (nData == 1) bufptr[n++] = '='; else bufptr[n++] = base64_table[base64_out[2]]; bufptr[n++] = '='; } if (n >= bufsize) return L2_ERR_MEM; *buflen = n; } /* anything else is an unknown dumping method... */ else return L2_ERR_ARG; return L2_OK; } l2_result_t l2_util_fmt_errno( l2_context_t *ctx, const char id, const char *param, char *bufptr, size_t bufsize, size_t *buflen, va_list *ap) { sprintf(bufptr, "(%d) %s", errno, strerror(errno)); *buflen = strlen(bufptr); return L2_OK; }