Commit 47def320 authored by Karl Heyes's avatar Karl Heyes
Browse files

missed some NULL checks from previous character set commit. Add optional charset

setting on metadata update request and conversion code for it.


svn path=/icecast/trunk/icecast/; revision=13663
parent 7e5604b9
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
</table> </table>
<input type="hidden" name="mount" value="{@mount}"/> <input type="hidden" name="mount" value="{@mount}"/>
<input type="hidden" name="mode" value="updinfo"/> <input type="hidden" name="mode" value="updinfo"/>
<input type="hidden" name="charset" value="UTF-8"/>
</form> </form>
<br /> <br />
......
...@@ -854,7 +854,7 @@ static void command_metadata(client_t *client, source_t *source, ...@@ -854,7 +854,7 @@ static void command_metadata(client_t *client, source_t *source,
int response) int response)
{ {
const char *action; const char *action;
const char *song, *title, *artist; const char *song, *title, *artist, *charset;
format_plugin_t *plugin; format_plugin_t *plugin;
xmlDocPtr doc; xmlDocPtr doc;
xmlNodePtr node; xmlNodePtr node;
...@@ -869,6 +869,7 @@ static void command_metadata(client_t *client, source_t *source, ...@@ -869,6 +869,7 @@ static void command_metadata(client_t *client, source_t *source,
COMMAND_OPTIONAL(client, "song", song); COMMAND_OPTIONAL(client, "song", song);
COMMAND_OPTIONAL(client, "title", title); COMMAND_OPTIONAL(client, "title", title);
COMMAND_OPTIONAL(client, "artist", artist); COMMAND_OPTIONAL(client, "artist", artist);
COMMAND_OPTIONAL(client, "charset", charset);
if (strcmp (action, "updinfo") != 0) if (strcmp (action, "updinfo") != 0)
{ {
...@@ -886,15 +887,15 @@ static void command_metadata(client_t *client, source_t *source, ...@@ -886,15 +887,15 @@ static void command_metadata(client_t *client, source_t *source,
{ {
if (song) if (song)
{ {
plugin->set_tag (plugin, "song", song); plugin->set_tag (plugin, "song", song, charset);
INFO2 ("Metadata on mountpoint %s changed to \"%s\"", source->mount, song); INFO2 ("Metadata on mountpoint %s changed to \"%s\"", source->mount, song);
} }
else else
{ {
if (artist && title) if (artist && title)
{ {
plugin->set_tag (plugin, "title", title); plugin->set_tag (plugin, "title", title, charset);
plugin->set_tag (plugin, "artist", artist); plugin->set_tag (plugin, "artist", artist, charset);
INFO3("Metadata on mountpoint %s changed to \"%s - %s\"", INFO3("Metadata on mountpoint %s changed to \"%s - %s\"",
source->mount, artist, title); source->mount, artist, title);
} }
...@@ -936,7 +937,7 @@ static void command_shoutcast_metadata(client_t *client, source_t *source) ...@@ -936,7 +937,7 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
if (source->format && source->format->set_tag) if (source->format && source->format->set_tag)
{ {
source->format->set_tag (source->format, "title", value); source->format->set_tag (source->format, "title", value, NULL);
DEBUG2("Metadata on mountpoint %s changed to \"%s\"", DEBUG2("Metadata on mountpoint %s changed to \"%s\"",
source->mount, value); source->mount, value);
......
...@@ -48,7 +48,7 @@ typedef struct _format_plugin_tag ...@@ -48,7 +48,7 @@ typedef struct _format_plugin_tag
int (*write_buf_to_client)(client_t *client); int (*write_buf_to_client)(client_t *client);
void (*write_buf_to_file)(struct source_tag *source, refbuf_t *refbuf); void (*write_buf_to_file)(struct source_tag *source, refbuf_t *refbuf);
int (*create_client_data)(struct source_tag *source, client_t *client); int (*create_client_data)(struct source_tag *source, client_t *client);
void (*set_tag)(struct _format_plugin_tag *plugin, const char *tag, const char *value); void (*set_tag)(struct _format_plugin_tag *plugin, const char *tag, const char *value, const char *charset);
void (*free_plugin)(struct _format_plugin_tag *self); void (*free_plugin)(struct _format_plugin_tag *self);
void (*apply_settings)(client_t *client, struct _format_plugin_tag *format, struct _mount_proxy *mount); void (*apply_settings)(client_t *client, struct _format_plugin_tag *format, struct _mount_proxy *mount);
......
...@@ -61,7 +61,7 @@ static int format_mp3_create_client_data (source_t *source, client_t *client); ...@@ -61,7 +61,7 @@ static int format_mp3_create_client_data (source_t *source, client_t *client);
static void free_mp3_client_data (client_t *client); static void free_mp3_client_data (client_t *client);
static int format_mp3_write_buf_to_client(client_t *client); static int format_mp3_write_buf_to_client(client_t *client);
static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf); static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf);
static void mp3_set_tag (format_plugin_t *plugin, const char *tag, const char *value); static void mp3_set_tag (format_plugin_t *plugin, const char *tag, const char *in_value, const char *charset);
static void format_mp3_apply_settings(client_t *client, format_plugin_t *format, mount_proxy *mount); static void format_mp3_apply_settings(client_t *client, format_plugin_t *format, mount_proxy *mount);
...@@ -124,42 +124,43 @@ int format_mp3_get_plugin (source_t *source) ...@@ -124,42 +124,43 @@ int format_mp3_get_plugin (source_t *source)
} }
static void mp3_set_tag (format_plugin_t *plugin, const char *tag, const char *value) static void mp3_set_tag (format_plugin_t *plugin, const char *tag, const char *in_value, const char *charset)
{ {
mp3_state *source_mp3 = plugin->_state; mp3_state *source_mp3 = plugin->_state;
unsigned int len; unsigned int len;
const char meta[] = "StreamTitle='"; const char meta[] = "StreamTitle='";
int size = sizeof (meta) + 1; int size = sizeof (meta) + 1;
char *value;
if (tag==NULL || value == NULL) if (tag==NULL || in_value == NULL)
return; return;
len = strlen (value)+1;
size += len;
/* protect against multiple updaters */ /* protect against multiple updaters */
thread_mutex_lock (&source_mp3->url_lock); thread_mutex_lock (&source_mp3->url_lock);
value = util_conv_string (in_value, charset, plugin->charset);
if (value == NULL)
value = strdup (in_value);
len = strlen (value)+1;
size += len;
if (strcmp (tag, "title") == 0 || strcmp (tag, "song") == 0) if (strcmp (tag, "title") == 0 || strcmp (tag, "song") == 0)
{ {
char *p = strdup (value); free (source_mp3->url_title);
if (p) free (source_mp3->url_artist);
{ source_mp3->url_artist = NULL;
free (source_mp3->url_title); source_mp3->url_title = value;
free (source_mp3->url_artist); source_mp3->update_metadata = 1;
source_mp3->url_artist = NULL;
source_mp3->url_title = p;
source_mp3->update_metadata = 1;
}
} }
else if (strcmp (tag, "artist") == 0) else if (strcmp (tag, "artist") == 0)
{ {
char *p = strdup (value); free (source_mp3->url_artist);
if (p) source_mp3->url_artist = value;
{ source_mp3->update_metadata = 1;
free (source_mp3->url_artist);
source_mp3->url_artist = p;
source_mp3->update_metadata = 1;
}
} }
else
free (value);
thread_mutex_unlock (&source_mp3->url_lock); thread_mutex_unlock (&source_mp3->url_lock);
} }
......
...@@ -67,7 +67,7 @@ static int process_vorbis_headers (ogg_state_t *ogg_info, ogg_codec_t *codec); ...@@ -67,7 +67,7 @@ static int process_vorbis_headers (ogg_state_t *ogg_info, ogg_codec_t *codec);
static refbuf_t *process_vorbis_page (ogg_state_t *ogg_info, static refbuf_t *process_vorbis_page (ogg_state_t *ogg_info,
ogg_codec_t *codec, ogg_page *page); ogg_codec_t *codec, ogg_page *page);
static refbuf_t *process_vorbis (ogg_state_t *ogg_info, ogg_codec_t *codec); static refbuf_t *process_vorbis (ogg_state_t *ogg_info, ogg_codec_t *codec);
static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char *value); static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char *value, const char *charset);
static void free_ogg_packet (ogg_packet *packet) static void free_ogg_packet (ogg_packet *packet)
...@@ -413,12 +413,13 @@ ogg_codec_t *initial_vorbis_page (format_plugin_t *plugin, ogg_page *page) ...@@ -413,12 +413,13 @@ ogg_codec_t *initial_vorbis_page (format_plugin_t *plugin, ogg_page *page)
/* called from the admin interface, here we update the artist/title info /* called from the admin interface, here we update the artist/title info
* and schedule a new set of header pages * and schedule a new set of header pages
*/ */
static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char *value) static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char *in_value, const char *charset)
{ {
ogg_state_t *ogg_info = plugin->_state; ogg_state_t *ogg_info = plugin->_state;
ogg_codec_t *codec = ogg_info->codecs; ogg_codec_t *codec = ogg_info->codecs;
vorbis_codec_t *source_vorbis; vorbis_codec_t *source_vorbis;
int change = 0; int change = 0;
char *value;
/* avoid updating if multiple codecs in use */ /* avoid updating if multiple codecs in use */
if (codec && codec->next == NULL) if (codec && codec->next == NULL)
...@@ -426,43 +427,37 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char ...@@ -426,43 +427,37 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char
else else
return; return;
value = util_conv_string (value, charset, "UTF-8");
if (value == NULL)
value = strdup (in_value);
if (strcmp (tag, "artist") == 0) if (strcmp (tag, "artist") == 0)
{ {
char *p = strdup (value); free (ogg_info->artist);
if (p) ogg_info->artist = value;
{ change = 1;
free (ogg_info->artist);
ogg_info->artist = p;
change = 1;
}
} }
if (strcmp (tag, "title") == 0) if (strcmp (tag, "title") == 0)
{ {
char *p = strdup (value); free (ogg_info->title);
if (p) ogg_info->title = value;
{ change = 1;
free (ogg_info->title);
ogg_info->title = p;
change = 1;
}
} }
if (strcmp (tag, "song") == 0) if (strcmp (tag, "song") == 0)
{ {
char *p = strdup (value); free (ogg_info->artist);
if (p) free (ogg_info->title);
{ ogg_info->artist = NULL;
free (ogg_info->artist); ogg_info->title = value;
free (ogg_info->title); change = 1;
ogg_info->artist = NULL;
ogg_info->title = p;
change = 1;
}
} }
if (change) if (change)
{ {
source_vorbis->stream_notify = 1; source_vorbis->stream_notify = 1;
source_vorbis->rebuild_comment = 1; source_vorbis->rebuild_comment = 1;
} }
else
free (value);
} }
......
...@@ -949,6 +949,10 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo) ...@@ -949,6 +949,10 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
if (source->client) if (source->client)
parser = source->client->parser; parser = source->client->parser;
/* to be done before possible non-utf8 stats */
if (source->format && source->format->apply_settings)
source->format->apply_settings (source->client, source->format, mountinfo);
/* public */ /* public */
if (mountinfo && mountinfo->yp_public >= 0) if (mountinfo && mountinfo->yp_public >= 0)
val = mountinfo->yp_public; val = mountinfo->yp_public;
...@@ -994,7 +998,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo) ...@@ -994,7 +998,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
str = "Unspecified name"; str = "Unspecified name";
} while (0); } while (0);
} }
stats_event_conv (source->mount, "server_name", str, source->format->charset); if (str && source->format)
stats_event_conv (source->mount, "server_name", str, source->format->charset);
/* stream description */ /* stream description */
if (mountinfo && mountinfo->stream_description) if (mountinfo && mountinfo->stream_description)
...@@ -1011,7 +1016,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo) ...@@ -1011,7 +1016,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
str = "Unspecified description"; str = "Unspecified description";
} while (0); } while (0);
} }
stats_event_conv (source->mount, "server_description", str, source->format->charset); if (str && source->format)
stats_event_conv (source->mount, "server_description", str, source->format->charset);
/* stream URL */ /* stream URL */
if (mountinfo && mountinfo->stream_url) if (mountinfo && mountinfo->stream_url)
...@@ -1027,7 +1033,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo) ...@@ -1027,7 +1033,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
if (str) break; if (str) break;
} while (0); } while (0);
} }
stats_event (source->mount, "server_url", str); if (str && source->format)
stats_event_conv (source->mount, "server_url", str, source->format->charset);
/* stream genre */ /* stream genre */
if (mountinfo && mountinfo->stream_genre) if (mountinfo && mountinfo->stream_genre)
...@@ -1044,7 +1051,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo) ...@@ -1044,7 +1051,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
str = "various"; str = "various";
} while (0); } while (0);
} }
stats_event_conv (source->mount, "genre", str, source->format->charset); if (str && source->format)
stats_event_conv (source->mount, "genre", str, source->format->charset);
/* stream bitrate */ /* stream bitrate */
if (mountinfo && mountinfo->bitrate) if (mountinfo && mountinfo->bitrate)
...@@ -1132,8 +1140,6 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo) ...@@ -1132,8 +1140,6 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
if (mountinfo && mountinfo->fallback_when_full) if (mountinfo && mountinfo->fallback_when_full)
source->fallback_when_full = mountinfo->fallback_when_full; source->fallback_when_full = mountinfo->fallback_when_full;
if (source->format && source->format->apply_settings)
source->format->apply_settings (source->client, source->format, mountinfo);
avl_tree_unlock (source->client_tree); avl_tree_unlock (source->client_tree);
} }
......
...@@ -633,3 +633,43 @@ struct tm *localtime_r (const time_t *timep, struct tm *result) ...@@ -633,3 +633,43 @@ struct tm *localtime_r (const time_t *timep, struct tm *result)
return result; return result;
} }
#endif #endif
/* helper function for converting a passed string in one character set to another
* we use libxml2 for this
*/
char *util_conv_string (const char *string, const char *in_charset, const char *out_charset)
{
xmlCharEncodingHandlerPtr in, out;
char *ret = NULL;
if (string == NULL || in_charset == NULL || out_charset == NULL)
return NULL;
in = xmlFindCharEncodingHandler (in_charset);
out = xmlFindCharEncodingHandler (out_charset);
if (in && out)
{
xmlBufferPtr orig = xmlBufferCreate ();
xmlBufferPtr utf8 = xmlBufferCreate ();
xmlBufferPtr conv = xmlBufferCreate ();
INFO2 ("converting metadata from %s to %s", in_charset, out_charset);
xmlBufferCCat (orig, string);
if (xmlCharEncInFunc (in, utf8, orig) > 0)
{
xmlCharEncOutFunc (out, conv, NULL);
if (xmlCharEncOutFunc (out, conv, utf8) >= 0)
ret = strdup ((const char *)xmlBufferContent (conv));
}
xmlBufferFree (orig);
xmlBufferFree (utf8);
xmlBufferFree (conv);
}
xmlCharEncCloseFunc (in);
xmlCharEncCloseFunc (out);
return ret;
}
...@@ -51,5 +51,6 @@ char *util_dict_urlencode(util_dict *dict, char delim); ...@@ -51,5 +51,6 @@ char *util_dict_urlencode(util_dict *dict, char delim);
#ifndef HAVE_LOCALTIME_R #ifndef HAVE_LOCALTIME_R
struct tm *localtime_r (const time_t *timep, struct tm *result); struct tm *localtime_r (const time_t *timep, struct tm *result);
#endif #endif
char *util_conv_string (const char *string, const char *in_charset, const char *out_charset);
#endif /* __UTIL_H__ */ #endif /* __UTIL_H__ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment