/* $Id: cddb_util.c,v 1.7 2006/10/15 06:52:50 airborne Exp $ Copyright (C) 2004, 2005 Kris Verbeeck This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "cddb/cddb_ni.h" #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_STRING_H #include #endif int cddb_str_iconv(iconv_t cd, ICONV_CONST char *in, char **out) { #ifdef HAVE_ICONV_H size_t inlen, outlen; int buflen, rc; int len; /* number of chars in buffer */ char *buf; inlen = strlen(in); buflen = 0; buf = NULL; do { outlen = inlen * 2; buflen += outlen; /* iconv() below changes the buf pointer: * - decrement to point at beginning of buffer before realloc * - re-increment to point at first free position after realloc */ len = buflen - outlen; buf = (char*)realloc(buf - len, buflen) + len; if (buf == NULL) { /* XXX: report out of memory error */ return FALSE; } rc = iconv(cd, &in, &inlen, &buf, &outlen); if ((rc == -1) && (errno != E2BIG)) { free(buf); return FALSE; /* conversion failed */ } } while (inlen != 0); len = buflen - outlen; buf -= len; /* reposition at begin of buffer */ /* make a copy just big enough for the result */ *out = malloc(len + 1); memcpy(*out, buf, len); *(*out + len) = '\0'; free(buf); #endif return TRUE; } /* Base64 decoder ring */ static char b64_vec[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; /* This routine will not check for buffer overflows. Make sure the * output buffer is big enough. */ void cddb_b64_encode(char *dst, const char *src) { unsigned int triplet = 0; int i = 0; while (*src) { triplet = (triplet << 8) | *src++; i++; if (i < 3) { continue; } *dst++ = b64_vec[(triplet >> 18)]; *dst++ = b64_vec[(triplet >> 12) & 0x3f]; *dst++ = b64_vec[(triplet >> 6) & 0x3f]; *dst++ = b64_vec[(triplet >> 0) & 0x3f]; i = 0; triplet = 0; } switch (i) { case 1: *dst++ = b64_vec[(triplet >> 2)]; *dst++ = b64_vec[(triplet << 4) & 0x3f]; *(unsigned short *)dst = 0x3d3d; /* add == */ dst += 2; break; case 2: *dst++ = b64_vec[(triplet >> 10)]; *dst++ = b64_vec[(triplet >> 4) & 0x3f]; *dst++ = b64_vec[(triplet << 2) & 0x3f]; *dst++ = '='; break; } *dst = '\0'; }