Don't leave the silly debugging malloc enabled
[xiph/unicode.git] / ezstream / src / util.c
blobe3eff6cce0624ab1909e65d453ee5a71a7db7244
1 /*
2 * ezstream - source client for Icecast with external en-/decoder support
3 * Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
4 * Copyright (C) 2007 Moritz Grimm <mdgrimm@gmx.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * This file contains utility functions, as well as a few other unexciting
22 * but verbose functions outsourced from ezstream.c to make it more readable.
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32 #ifdef HAVE_SYS_TIME_H
33 # include <sys/time.h>
34 #else
35 # include <time.h>
36 #endif
38 #include <ctype.h>
39 #include <errno.h>
40 #ifdef HAVE_LANGINFO_H
41 # include <langinfo.h>
42 #endif
43 #ifdef HAVE_LOCALE_H
44 # include <locale.h>
45 #endif
46 #include <stdio.h>
47 #include <string.h>
49 #ifdef HAVE_ICONV
50 # include <iconv.h>
51 #endif
52 #include <shout/shout.h>
54 #include "compat.h"
55 #include "util.h"
56 #include "configfile.h"
57 #include "xalloc.h"
59 #ifndef BUFSIZ
60 # define BUFSIZ 1024
61 #endif
63 extern EZCONFIG *pezConfig;
64 extern char *__progname;
66 char * iconvert(const char *, const char *, const char *, int);
68 int
69 strrcmp(const char *s, const char *sub)
71 size_t slen = strlen(s);
72 size_t sublen = strlen(sub);
74 if (sublen > slen)
75 return (1);
77 return (memcmp(s + slen - sublen, sub, sublen));
80 int
81 strrcasecmp(const char *s, const char *sub)
83 char *s_cpy = xstrdup(s);
84 char *sub_cpy = xstrdup(sub);
85 char *p;
86 int ret;
88 for (p = s_cpy; *p != '\0'; p++)
89 *p = tolower((int)*p);
91 for (p = sub_cpy; *p != '\0'; p++)
92 *p = tolower((int)*p);
94 ret = strrcmp(s_cpy, sub_cpy);
96 xfree(s_cpy);
97 xfree(sub_cpy);
99 return (ret);
102 shout_t *
103 stream_setup(const char *host, const int port, const char *mount)
105 shout_t *shout = NULL;
107 if ((shout = shout_new()) == NULL) {
108 printf("%s: shout_new(): %s", __progname, strerror(ENOMEM));
109 return (NULL);
112 if (shout_set_host(shout, host) != SHOUTERR_SUCCESS) {
113 printf("%s: shout_set_host(): %s\n", __progname,
114 shout_get_error(shout));
115 shout_free(shout);
116 return (NULL);
118 if (shout_set_protocol(shout, SHOUT_PROTOCOL_HTTP) != SHOUTERR_SUCCESS) {
119 printf("%s: shout_set_protocol(): %s\n", __progname,
120 shout_get_error(shout));
121 shout_free(shout);
122 return (NULL);
124 if (shout_set_port(shout, port) != SHOUTERR_SUCCESS) {
125 printf("%s: shout_set_port: %s\n", __progname,
126 shout_get_error(shout));
127 shout_free(shout);
128 return (NULL);
130 if (shout_set_password(shout, pezConfig->password) != SHOUTERR_SUCCESS) {
131 printf("%s: shout_set_password(): %s\n", __progname,
132 shout_get_error(shout));
133 shout_free(shout);
134 return (NULL);
136 if (shout_set_mount(shout, mount) != SHOUTERR_SUCCESS) {
137 printf("%s: shout_set_mount(): %s\n", __progname,
138 shout_get_error(shout));
139 shout_free(shout);
140 return (NULL);
142 if (shout_set_user(shout, "source") != SHOUTERR_SUCCESS) {
143 printf("%s: shout_set_user(): %s\n", __progname,
144 shout_get_error(shout));
145 shout_free(shout);
146 return (NULL);
149 if (!strcmp(pezConfig->format, MP3_FORMAT) &&
150 shout_set_format(shout, SHOUT_FORMAT_MP3) != SHOUTERR_SUCCESS) {
151 printf("%s: shout_set_format(MP3): %s\n",
152 __progname, shout_get_error(shout));
153 shout_free(shout);
154 return (NULL);
156 if ((!strcmp(pezConfig->format, VORBIS_FORMAT) ||
157 !strcmp(pezConfig->format, THEORA_FORMAT)) &&
158 shout_set_format(shout, SHOUT_FORMAT_OGG) != SHOUTERR_SUCCESS) {
159 printf("%s: shout_set_format(OGG): %s\n",
160 __progname, shout_get_error(shout));
161 shout_free(shout);
162 return (NULL);
165 if (pezConfig->serverName &&
166 shout_set_name(shout, pezConfig->serverName) != SHOUTERR_SUCCESS) {
167 printf("%s: shout_set_name(): %s\n",
168 __progname, shout_get_error(shout));
169 shout_free(shout);
170 return (NULL);
172 if (pezConfig->serverURL &&
173 shout_set_url(shout, pezConfig->serverURL) != SHOUTERR_SUCCESS) {
174 printf("%s: shout_set_url(): %s\n",
175 __progname, shout_get_error(shout));
176 shout_free(shout);
177 return (NULL);
179 if (pezConfig->serverGenre &&
180 shout_set_genre(shout, pezConfig->serverGenre) != SHOUTERR_SUCCESS) {
181 printf("%s: shout_set_genre(): %s\n",
182 __progname, shout_get_error(shout));
183 shout_free(shout);
184 return (NULL);
186 if (pezConfig->serverDescription &&
187 shout_set_description(shout, pezConfig->serverDescription) != SHOUTERR_SUCCESS) {
188 printf("%s: shout_set_description(): %s\n",
189 __progname, shout_get_error(shout));
190 shout_free(shout);
191 return (NULL);
193 if (pezConfig->serverBitrate &&
194 shout_set_audio_info(shout, SHOUT_AI_BITRATE, pezConfig->serverBitrate) != SHOUTERR_SUCCESS) {
195 printf("%s: shout_set_audio_info(AI_BITRATE): %s\n",
196 __progname, shout_get_error(shout));
197 shout_free(shout);
198 return (NULL);
200 if (pezConfig->serverChannels &&
201 shout_set_audio_info(shout, SHOUT_AI_CHANNELS, pezConfig->serverChannels) != SHOUTERR_SUCCESS) {
202 printf("%s: shout_set_audio_info(AI_CHANNELS): %s\n",
203 __progname, shout_get_error(shout));
204 shout_free(shout);
205 return (NULL);
207 if (pezConfig->serverSamplerate &&
208 shout_set_audio_info(shout, SHOUT_AI_SAMPLERATE, pezConfig->serverSamplerate) != SHOUTERR_SUCCESS) {
209 printf("%s: shout_set_audio_info(AI_SAMPLERATE): %s\n",
210 __progname, shout_get_error(shout));
211 shout_free(shout);
212 return (NULL);
214 if (pezConfig->serverQuality &&
215 shout_set_audio_info(shout, SHOUT_AI_QUALITY, pezConfig->serverQuality) != SHOUTERR_SUCCESS) {
216 printf("%s: shout_set_audio_info(AI_QUALITY): %s\n",
217 __progname, shout_get_error(shout));
218 shout_free(shout);
219 return (NULL);
222 if (shout_set_public(shout, pezConfig->serverPublic) != SHOUTERR_SUCCESS) {
223 printf("%s: shout_set_public(): %s\n",
224 __progname, shout_get_error(shout));
225 shout_free(shout);
226 return (NULL);
229 return (shout);
232 char *
233 CHARtoUTF8(const char *in_str, int mode)
235 #ifndef WIN32
236 char *codeset;
238 # if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE) && defined(CODESET)
239 setlocale(LC_CTYPE, "");
240 codeset = nl_langinfo(CODESET);
241 setlocale(LC_CTYPE, "C");
242 # else
243 codeset = (char *)"";
244 # endif /* HAVE_NL_LANGINFO && HAVE_SETLOCALE && CODESET */
245 #else
246 char codeset[24];
248 snprintf(codeset, sizeof(codeset), "CP%u", GetACP());
249 #endif /* !WIN32 */
251 if (in_str == NULL || strlen(in_str) == 0)
252 return (NULL);
254 return (iconvert(in_str, codeset, "UTF-8", mode));
257 char *
258 UTF8toCHAR(const char *in_str, int mode)
260 #ifndef WIN32
261 char *codeset;
263 # if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE) && defined(CODESET)
264 setlocale(LC_CTYPE, "");
265 codeset = nl_langinfo(CODESET);
266 setlocale(LC_CTYPE, "C");
267 # else
268 codeset = (char *)"";
269 # endif /* HAVE_NL_LANGINFO && HAVE_SETLOCALE && CODESET */
270 #else
271 char codeset[24];
273 snprintf(codeset, sizeof(codeset), "CP%u", GetACP());
274 #endif /* !WIN32 */
276 if (in_str == NULL || strlen(in_str) == 0)
277 return (NULL);
279 return (iconvert(in_str, "UTF-8", codeset, mode));
282 char *
283 iconvert(const char *in_str, const char *from, const char *to, int mode)
285 #ifdef HAVE_ICONV
286 iconv_t cd;
287 ICONV_CONST char *input, *ip;
288 size_t input_len;
289 char *output;
290 size_t output_size;
291 char buf[BUFSIZ], *bp;
292 size_t bufavail;
293 size_t out_pos;
294 char *tocode;
296 switch (mode) {
297 size_t siz;
299 case ICONV_TRANSLIT:
300 siz = strlen(to) + strlen("//TRANSLIT") + 1;
301 tocode = xcalloc(siz, sizeof(char));
302 snprintf(tocode, siz, "%s//TRANSLIT", to);
303 break;
304 case ICONV_IGNORE:
305 siz = strlen(to) + strlen("//IGNORE") + 1;
306 tocode = xcalloc(siz, sizeof(char));
307 snprintf(tocode, siz, "%s//IGNORE", to);
308 break;
309 case ICONV_REPLACE:
310 /* FALLTHROUGH */
311 default:
312 tocode = xstrdup(to);
313 break;
316 if ((cd = iconv_open(tocode, from)) == (iconv_t)-1 &&
317 (cd = iconv_open("", from)) == (iconv_t)-1 &&
318 (cd = iconv_open(tocode, "")) == (iconv_t)-1) {
319 xfree(tocode);
320 printf("%s: iconv_open(): %s\n", __progname, strerror(errno));
321 return (NULL);
324 ip = input = (ICONV_CONST char *)in_str;
325 input_len = strlen(input);
326 output_size = 1;
327 output = xcalloc(output_size, sizeof(char));
328 out_pos = 0;
329 output[out_pos] = '\0';
330 while (input_len > 0) {
331 char *op;
332 size_t count;
334 buf[0] = '\0';
335 bp = buf;
336 bufavail = sizeof(buf) - 1;
338 if (iconv(cd, &ip, &input_len, &bp, &bufavail) == (size_t)-1 &&
339 errno != E2BIG) {
340 *bp++ = '?';
341 ip++;
342 input_len--;
343 bufavail--;
345 *bp = '\0';
347 count = sizeof(buf) - bufavail - 1;
349 output_size += count;
350 op = output = xrealloc(output, output_size, sizeof(char));
351 op += out_pos;
352 memcpy(op, buf, count);
353 out_pos += count;
354 op += count;
355 *op = '\0';
358 if (iconv_close(cd) == -1) {
359 printf("%s: iconv_close(): %s\n", __progname, strerror(errno));
360 xfree(output);
361 xfree(tocode);
362 return (NULL);
365 xfree(tocode);
366 return (output);
367 #else
368 return (xstrdup(in_str));
369 #endif /* HAVE_ICONV */
373 ez_gettimeofday(void *tp_arg)
375 struct timeval *tp = (struct timeval *)tp_arg;
376 int ret = -1;
378 #ifdef HAVE_GETTIMEOFDAY
379 ret = gettimeofday(tp, NULL);
380 #else /* HAVE_GETTIMEOFDAY */
381 # ifdef WIN32
383 * Idea for this way of implementing gettimeofday()-like functionality
384 * on Windows taken from cURL, (C) 1998 - 2007 Daniel Steinberg, et al.
385 * http://curl.haxx.se/docs/copyright.html
387 SYSTEMTIME st;
388 struct tm tm;
390 GetLocalTime(&st);
391 tm.tm_sec = st.wSecond;
392 tm.tm_min = st.wMinute;
393 tm.tm_hour = st.wHour;
394 tm.tm_mday = st.wDay;
395 tm.tm_mon = st.wMonth - 1;
396 tm.tm_year = st.wYear - 1900;
397 tm.tm_isdst = -1;
398 tp->tv_sec = (long)mktime(&tm);
399 tp->tv_usec = st.wMilliseconds * 1000;
400 ret = 0;
401 # else /* WIN32 */
402 /* Fallback to time(): */
403 tp->tv_sec = (long)time(NULL);
404 tp->tv_usec = 0;
405 ret = 0;
406 # endif /* WIN32 */
407 #endif /* HAVE_GETTIMEOFDAY */
409 return (ret);