1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-06-23 06:25:24 +00:00
icecast-server/src/metadata_xiph.c

117 lines
2.4 KiB
C

/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2022, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "metadata_xiph.h"
#include "logging.h"
#define CATMODULE "metadata-xiph"
uint32_t metadata_xiph_read_u32be_unaligned(const unsigned char *in)
{
uint32_t ret = 0;
ret += in[0];
ret <<= 8;
ret += in[1];
ret <<= 8;
ret += in[2];
ret <<= 8;
ret += in[3];
return ret;
}
uint32_t metadata_xiph_read_u32le_unaligned(const unsigned char *in)
{
uint32_t ret = 0;
ret += in[3];
ret <<= 8;
ret += in[2];
ret <<= 8;
ret += in[1];
ret <<= 8;
ret += in[0];
return ret;
}
bool metadata_xiph_read_vorbis_comments(vorbis_comment *vc, const void *buffer, size_t len)
{
bool ret = true;
size_t expected_len = 8;
uint32_t vendor_len;
uint32_t count;
uint32_t i;
char *out_buffer = NULL;
size_t out_buffer_len = 0;
if (!vc || !buffer || len < expected_len)
return false;
/* reading vendor tag and discarding it */
vendor_len = metadata_xiph_read_u32le_unaligned(buffer);
expected_len += vendor_len;
if (len < expected_len)
return false;
buffer += 4 + vendor_len;
count = metadata_xiph_read_u32le_unaligned(buffer);
expected_len += count * 4;
if (len < expected_len)
return false;
buffer += 4;
for (i = 0; i < count; i++) {
uint32_t comment_len = metadata_xiph_read_u32le_unaligned(buffer);
buffer += 4;
expected_len += comment_len;
if (len < expected_len) {
ret = false;
break;
}
if (out_buffer_len < comment_len || !out_buffer) {
char *n_out_buffer = realloc(out_buffer, comment_len + 1);
if (!n_out_buffer) {
ret = false;
break;
}
out_buffer = n_out_buffer;
out_buffer_len = comment_len;
}
memcpy(out_buffer, buffer, comment_len);
out_buffer[comment_len] = 0;
buffer += comment_len;
vorbis_comment_add(vc, out_buffer);
}
free(out_buffer);
if (!ret) {
vorbis_comment_clear(vc);
vorbis_comment_init(vc);
}
return ret;
}