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

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 @@
</table>
<input type="hidden" name="mount" value="{@mount}"/>
<input type="hidden" name="mode" value="updinfo"/>
<input type="hidden" name="charset" value="UTF-8"/>
</form>
<br />
......
......@@ -854,7 +854,7 @@ static void command_metadata(client_t *client, source_t *source,
int response)
{
const char *action;
const char *song, *title, *artist;
const char *song, *title, *artist, *charset;
format_plugin_t *plugin;
xmlDocPtr doc;
xmlNodePtr node;
......@@ -869,6 +869,7 @@ static void command_metadata(client_t *client, source_t *source,
COMMAND_OPTIONAL(client, "song", song);
COMMAND_OPTIONAL(client, "title", title);
COMMAND_OPTIONAL(client, "artist", artist);
COMMAND_OPTIONAL(client, "charset", charset);
if (strcmp (action, "updinfo") != 0)
{
......@@ -886,15 +887,15 @@ static void command_metadata(client_t *client, source_t *source,
{
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);
}
else
{
if (artist && title)
{
plugin->set_tag (plugin, "title", title);
plugin->set_tag (plugin, "artist", artist);
plugin->set_tag (plugin, "title", title, charset);
plugin->set_tag (plugin, "artist", artist, charset);
INFO3("Metadata on mountpoint %s changed to \"%s - %s\"",
source->mount, artist, title);
}
......@@ -936,7 +937,7 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
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\"",
source->mount, value);
......
......@@ -48,7 +48,7 @@ typedef struct _format_plugin_tag
int (*write_buf_to_client)(client_t *client);
void (*write_buf_to_file)(struct source_tag *source, refbuf_t *refbuf);
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 (*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);
static void free_mp3_client_data (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 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);
......@@ -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;
unsigned int len;
const char meta[] = "StreamTitle='";
int size = sizeof (meta) + 1;
char *value;
if (tag==NULL || value == NULL)
if (tag==NULL || in_value == NULL)
return;
len = strlen (value)+1;
size += len;
/* protect against multiple updaters */
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)
{
char *p = strdup (value);
if (p)
{
free (source_mp3->url_title);
free (source_mp3->url_artist);
source_mp3->url_artist = NULL;
source_mp3->url_title = p;
source_mp3->update_metadata = 1;
}
free (source_mp3->url_title);
free (source_mp3->url_artist);
source_mp3->url_artist = NULL;
source_mp3->url_title = value;
source_mp3->update_metadata = 1;
}
else if (strcmp (tag, "artist") == 0)
{
char *p = strdup (value);
if (p)
{
free (source_mp3->url_artist);
source_mp3->url_artist = p;
source_mp3->update_metadata = 1;
}
free (source_mp3->url_artist);
source_mp3->url_artist = value;
source_mp3->update_metadata = 1;
}
else
free (value);
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);
static refbuf_t *process_vorbis_page (ogg_state_t *ogg_info,
ogg_codec_t *codec, ogg_page *page);
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)
......@@ -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
* 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_codec_t *codec = ogg_info->codecs;
vorbis_codec_t *source_vorbis;
int change = 0;
char *value;
/* avoid updating if multiple codecs in use */
if (codec && codec->next == NULL)
......@@ -426,43 +427,37 @@ static void vorbis_set_tag (format_plugin_t *plugin, const char *tag, const char
else
return;
value = util_conv_string (value, charset, "UTF-8");
if (value == NULL)
value = strdup (in_value);
if (strcmp (tag, "artist") == 0)
{
char *p = strdup (value);
if (p)
{
free (ogg_info->artist);
ogg_info->artist = p;
change = 1;
}
free (ogg_info->artist);
ogg_info->artist = value;
change = 1;
}
if (strcmp (tag, "title") == 0)
{
char *p = strdup (value);
if (p)
{
free (ogg_info->title);
ogg_info->title = p;
change = 1;
}
free (ogg_info->title);
ogg_info->title = value;
change = 1;
}
if (strcmp (tag, "song") == 0)
{
char *p = strdup (value);
if (p)
{
free (ogg_info->artist);
free (ogg_info->title);
ogg_info->artist = NULL;
ogg_info->title = p;
change = 1;
}
free (ogg_info->artist);
free (ogg_info->title);
ogg_info->artist = NULL;
ogg_info->title = value;
change = 1;
}
if (change)
{
source_vorbis->stream_notify = 1;
source_vorbis->rebuild_comment = 1;
}
else
free (value);
}
......
......@@ -949,6 +949,10 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
if (source->client)
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 */
if (mountinfo && mountinfo->yp_public >= 0)
val = mountinfo->yp_public;
......@@ -994,7 +998,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
str = "Unspecified name";
} 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 */
if (mountinfo && mountinfo->stream_description)
......@@ -1011,7 +1016,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
str = "Unspecified description";
} 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 */
if (mountinfo && mountinfo->stream_url)
......@@ -1027,7 +1033,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
if (str) break;
} 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 */
if (mountinfo && mountinfo->stream_genre)
......@@ -1044,7 +1051,8 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
str = "various";
} 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 */
if (mountinfo && mountinfo->bitrate)
......@@ -1132,8 +1140,6 @@ static void source_apply_mount (source_t *source, mount_proxy *mountinfo)
if (mountinfo && 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);
}
......
......@@ -633,3 +633,43 @@ struct tm *localtime_r (const time_t *timep, struct tm *result)
return result;
}
#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);
#ifndef HAVE_LOCALTIME_R
struct tm *localtime_r (const time_t *timep, struct tm *result);
#endif
char *util_conv_string (const char *string, const char *in_charset, const char *out_charset);
#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