mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 23:25:56 -05:00
[misc] Change b64_* to wrap ffmpeg's base64 encoder/decoder
Using ffmpeg's is probably better than having our own, plus it provides us with decoded length, which we will need to support artwork via pipe.
This commit is contained in:
parent
e654276262
commit
1752901529
@ -1555,7 +1555,7 @@ httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passw
|
||||
|
||||
auth += strlen("Basic ");
|
||||
|
||||
authuser = b64_decode(auth);
|
||||
authuser = (char *)b64_decode(NULL, auth);
|
||||
if (!authuser)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not decode Authentication header\n");
|
||||
|
@ -285,7 +285,7 @@ dmapval(const char s[4])
|
||||
}
|
||||
|
||||
static void
|
||||
parse_progress(struct input_metadata *m, char *progress)
|
||||
handle_progress(struct input_metadata *m, char *progress)
|
||||
{
|
||||
char *s;
|
||||
char *ptr;
|
||||
@ -315,7 +315,7 @@ parse_progress(struct input_metadata *m, char *progress)
|
||||
}
|
||||
|
||||
static void
|
||||
parse_volume(const char *volume)
|
||||
handle_volume(const char *volume)
|
||||
{
|
||||
char *volume_next;
|
||||
float airplay_volume;
|
||||
@ -355,7 +355,7 @@ parse_volume(const char *volume)
|
||||
|
||||
// returns 1 on metadata found, 0 on nothing, -1 on error
|
||||
static int
|
||||
parse_item(struct input_metadata *m, const char *item)
|
||||
handle_item(struct input_metadata *m, const char *item)
|
||||
{
|
||||
mxml_node_t *xml;
|
||||
mxml_node_t *haystack;
|
||||
@ -363,9 +363,11 @@ parse_item(struct input_metadata *m, const char *item)
|
||||
const char *s;
|
||||
uint32_t type;
|
||||
uint32_t code;
|
||||
char **dstptr;
|
||||
char *progress;
|
||||
char *volume;
|
||||
char **data;
|
||||
uint8_t *data;
|
||||
int data_len;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
@ -399,17 +401,17 @@ parse_item(struct input_metadata *m, const char *item)
|
||||
}
|
||||
|
||||
if (code == dmapval("asal"))
|
||||
data = &m->album;
|
||||
dstptr = &m->album;
|
||||
else if (code == dmapval("asar"))
|
||||
data = &m->artist;
|
||||
dstptr = &m->artist;
|
||||
else if (code == dmapval("minm"))
|
||||
data = &m->title;
|
||||
dstptr = &m->title;
|
||||
else if (code == dmapval("asgn"))
|
||||
data = &m->genre;
|
||||
dstptr = &m->genre;
|
||||
else if (code == dmapval("prgr"))
|
||||
data = &progress;
|
||||
dstptr = &progress;
|
||||
else if (code == dmapval("pvol"))
|
||||
data = &volume;
|
||||
dstptr = &volume;
|
||||
else
|
||||
goto out_nothing;
|
||||
|
||||
@ -418,11 +420,8 @@ parse_item(struct input_metadata *m, const char *item)
|
||||
{
|
||||
pthread_mutex_lock(&pipe_metadata_lock);
|
||||
|
||||
if (data != &progress && data != &volume)
|
||||
free(*data);
|
||||
|
||||
*data = b64_decode(s);
|
||||
if (!*data)
|
||||
data = b64_decode(&data_len, s);
|
||||
if (!data)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Base64 decode of '%s' failed\n", s);
|
||||
|
||||
@ -430,17 +429,24 @@ parse_item(struct input_metadata *m, const char *item)
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG, L_PLAYER, "Read Shairport metadata (type=%8x, code=%8x): '%s'\n", type, code, *data);
|
||||
DPRINTF(E_DBG, L_PLAYER, "Read Shairport metadata (type=%8x, code=%8x, len=%d): '%s'\n", type, code, data_len, (char *)data);
|
||||
|
||||
if (data == &progress)
|
||||
if (dstptr == &progress)
|
||||
{
|
||||
parse_progress(m, progress);
|
||||
free(*data);
|
||||
progress = (char *)data;
|
||||
handle_progress(m, progress);
|
||||
free(data);
|
||||
}
|
||||
else if (data == &volume)
|
||||
else if (dstptr == &volume)
|
||||
{
|
||||
parse_volume(volume);
|
||||
free(*data);
|
||||
volume = (char *)data;
|
||||
handle_volume(volume);
|
||||
free(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(*dstptr); // If m->x is already set, free it
|
||||
*dstptr = (char *)data;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&pipe_metadata_lock);
|
||||
@ -480,7 +486,7 @@ extract_item(struct evbuffer *evbuf)
|
||||
}
|
||||
|
||||
static int
|
||||
pipe_metadata_parse(struct input_metadata *m, struct evbuffer *evbuf)
|
||||
pipe_metadata_handle(struct input_metadata *m, struct evbuffer *evbuf)
|
||||
{
|
||||
char *item;
|
||||
int found;
|
||||
@ -489,7 +495,7 @@ pipe_metadata_parse(struct input_metadata *m, struct evbuffer *evbuf)
|
||||
found = 0;
|
||||
while ((item = extract_item(evbuf)))
|
||||
{
|
||||
ret = parse_item(m, item);
|
||||
ret = handle_item(m, item);
|
||||
free(item);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -662,7 +668,7 @@ pipe_metadata_read_cb(evutil_socket_t fd, short event, void *arg)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = pipe_metadata_parse(&pipe_metadata_parsed, pipe_metadata_buf);
|
||||
ret = pipe_metadata_handle(&pipe_metadata_parsed, pipe_metadata_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
pipe_metadata_watch_del(NULL);
|
||||
|
163
src/misc.c
163
src/misc.c
@ -43,6 +43,8 @@
|
||||
#include <unistr.h>
|
||||
#include <uniconv.h>
|
||||
|
||||
#include <libavutil/base64.h>
|
||||
|
||||
#include "logger.h"
|
||||
#include "conffile.h"
|
||||
#include "misc.h"
|
||||
@ -771,161 +773,52 @@ two_str_hash(const char *a, const char *b)
|
||||
return hash;
|
||||
}
|
||||
|
||||
static unsigned char b64_decode_table[256];
|
||||
|
||||
char *
|
||||
b64_decode(const char *b64)
|
||||
uint8_t *
|
||||
b64_decode(int *dstlen, const char *src)
|
||||
{
|
||||
char *str;
|
||||
const unsigned char *iptr;
|
||||
unsigned char *optr;
|
||||
unsigned char c;
|
||||
uint8_t *out;
|
||||
int len;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (b64_decode_table[0] == 0)
|
||||
len = AV_BASE64_DECODE_SIZE(strlen(src));
|
||||
|
||||
CHECK_NULL(L_MISC, out = calloc(1, len));
|
||||
|
||||
ret = av_base64_decode(out, src, len);
|
||||
if (ret < 0)
|
||||
{
|
||||
memset(b64_decode_table, 0xff, sizeof(b64_decode_table));
|
||||
|
||||
/* Base64 encoding: A-Za-z0-9+/ */
|
||||
for (i = 0; i < 26; i++)
|
||||
{
|
||||
b64_decode_table['A' + i] = i;
|
||||
b64_decode_table['a' + i] = i + 26;
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
b64_decode_table['0' + i] = i + 52;
|
||||
|
||||
b64_decode_table['+'] = 62;
|
||||
b64_decode_table['/'] = 63;
|
||||
|
||||
/* Stop on '=' */
|
||||
b64_decode_table['='] = 100; /* > 63 */
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen(b64);
|
||||
if (dstlen)
|
||||
*dstlen = ret;
|
||||
|
||||
CHECK_NULL(L_MISC, str = malloc(len));
|
||||
|
||||
memset(str, 0, len);
|
||||
|
||||
iptr = (const unsigned char *)b64;
|
||||
optr = (unsigned char *)str;
|
||||
i = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
if (*iptr == '=')
|
||||
break;
|
||||
|
||||
c = b64_decode_table[*iptr];
|
||||
if (c > 63)
|
||||
{
|
||||
iptr++;
|
||||
len--;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
optr[0] = c << 2;
|
||||
break;
|
||||
case 1:
|
||||
optr[0] |= c >> 4;
|
||||
optr[1] = c << 4;
|
||||
break;
|
||||
case 2:
|
||||
optr[1] |= c >> 2;
|
||||
optr[2] = c << 6;
|
||||
break;
|
||||
case 3:
|
||||
optr[2] |= c;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
if (i == 4)
|
||||
{
|
||||
optr += 3;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
len--;
|
||||
iptr++;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static const char b64_encode_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static void
|
||||
b64_encode_block(const uint8_t *in, char *out, int len)
|
||||
{
|
||||
out[0] = b64_encode_table[in[0] >> 2];
|
||||
|
||||
out[2] = out[3] = '=';
|
||||
|
||||
if (len == 1)
|
||||
out[1] = b64_encode_table[((in[0] & 0x03) << 4)];
|
||||
else
|
||||
{
|
||||
out[1] = b64_encode_table[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)];
|
||||
|
||||
if (len == 2)
|
||||
out[2] = b64_encode_table[((in[1] & 0x0f) << 2)];
|
||||
else
|
||||
{
|
||||
out[2] = b64_encode_table[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)];
|
||||
out[3] = b64_encode_table[in[2] & 0x3f];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
b64_encode_full_block(const uint8_t *in, char *out)
|
||||
{
|
||||
out[0] = b64_encode_table[in[0] >> 2];
|
||||
out[1] = b64_encode_table[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)];
|
||||
out[2] = b64_encode_table[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)];
|
||||
out[3] = b64_encode_table[in[2] & 0x3f];
|
||||
return out;
|
||||
}
|
||||
|
||||
char *
|
||||
b64_encode(const uint8_t *in, size_t len)
|
||||
b64_encode(const uint8_t *src, int srclen)
|
||||
{
|
||||
char *encoded;
|
||||
char *out;
|
||||
int len;
|
||||
char *ret;
|
||||
|
||||
/* 3 in chars -> 4 out chars */
|
||||
encoded = (char *)malloc(len + (len / 3) + 4 + 1);
|
||||
if (!encoded)
|
||||
return NULL;
|
||||
len = AV_BASE64_SIZE(srclen);
|
||||
|
||||
out = encoded;
|
||||
CHECK_NULL(L_MISC, out = calloc(1, len));
|
||||
|
||||
while (len >= 3)
|
||||
ret = av_base64_encode(out, len, src, srclen);
|
||||
if (!ret)
|
||||
{
|
||||
b64_encode_full_block(in, out);
|
||||
|
||||
len -= 3;
|
||||
in += 3;
|
||||
out += 4;
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
b64_encode_block(in, out, len);
|
||||
out += 4;
|
||||
}
|
||||
|
||||
out[0] = '\0';
|
||||
|
||||
return encoded;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MurmurHash2, 64-bit versions, by Austin Appleby
|
||||
*
|
||||
|
@ -133,11 +133,11 @@ djb_hash(const void *data, size_t len);
|
||||
int64_t
|
||||
two_str_hash(const char *a, const char *b);
|
||||
|
||||
char *
|
||||
b64_decode(const char *b64);
|
||||
uint8_t *
|
||||
b64_decode(int *dstlen, const char *src);
|
||||
|
||||
char *
|
||||
b64_encode(const uint8_t *in, size_t len);
|
||||
b64_encode(const uint8_t *src, int srclen);
|
||||
|
||||
uint64_t
|
||||
murmur_hash64(const void *key, int len, uint32_t seed);
|
||||
|
Loading…
Reference in New Issue
Block a user