mirror of
https://github.com/SuperBFG7/ympd
synced 2025-11-05 00:03:00 +00:00
fixed firefox websocket bug, added assets
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
#include <libwebsockets.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "http_server.h"
|
||||
#include "mpd_client.h"
|
||||
|
||||
char *resource_path = LOCAL_RESOURCE_PATH;
|
||||
|
||||
@@ -26,30 +30,117 @@ static const struct serveable whitelist[] = {
|
||||
{ "/fonts/glyphicons-halflings-regular.ttf", "application/x-font-ttf"},
|
||||
{ "/fonts/glyphicons-halflings-regular.eot", "application/vnd.ms-fontobject"},
|
||||
|
||||
{ "assets/favicon.ico", "image/vnd.microsoft.icon" },
|
||||
|
||||
/* last one is the default served if no match */
|
||||
{ "/index.html", "text/html" },
|
||||
};
|
||||
|
||||
/* Converts a hex character to its integer value */
|
||||
char from_hex(char ch) {
|
||||
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
|
||||
}
|
||||
|
||||
/* Converts an integer value to its hex character*/
|
||||
char to_hex(char code) {
|
||||
static char hex[] = "0123456789abcdef";
|
||||
return hex[code & 15];
|
||||
}
|
||||
|
||||
/* Returns a url-decoded version of str */
|
||||
/* IMPORTANT: be sure to free() the returned string after use */
|
||||
char *url_decode(char *str) {
|
||||
char *pstr = str, *buf = malloc(strlen(str) + 1), *pbuf = buf;
|
||||
while (*pstr) {
|
||||
if (*pstr == '%') {
|
||||
if (pstr[1] && pstr[2]) {
|
||||
*pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
|
||||
pstr += 2;
|
||||
}
|
||||
} else if (*pstr == '+') {
|
||||
*pbuf++ = ' ';
|
||||
} else {
|
||||
*pbuf++ = *pstr;
|
||||
}
|
||||
pstr++;
|
||||
}
|
||||
*pbuf = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
int callback_http(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len)
|
||||
{
|
||||
char buf[256];
|
||||
size_t n;
|
||||
char buf[256], *response_buffer, *p;
|
||||
size_t n, response_size;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_HTTP:
|
||||
for (n = 0; n < (sizeof(whitelist) / sizeof(whitelist[0]) - 1); n++)
|
||||
if(in && strncmp((const char *)in, "/api/", 5) == 0)
|
||||
{
|
||||
if (in && strcmp((const char *)in, whitelist[n].urlpath) == 0)
|
||||
break;
|
||||
response_buffer = (char *)malloc(100 * 1024 + 100);
|
||||
p = response_buffer;
|
||||
|
||||
/* put content length and payload to buffer */
|
||||
if(strncmp((const char *)in, "/api/get_browse", 15) == 0)
|
||||
{
|
||||
char *url;
|
||||
if(sscanf(in, "/api/get_browse/%m[^\t\n]", &url))
|
||||
{
|
||||
char *url_decoded = url_decode(url);
|
||||
printf("searching for %s", url_decoded);
|
||||
response_size = mpd_put_browse(response_buffer + 98, url_decoded);
|
||||
free(url_decoded);
|
||||
free(url);
|
||||
}
|
||||
else
|
||||
response_size = mpd_put_browse(response_buffer + 98, "/");
|
||||
|
||||
}
|
||||
else if(strncmp((const char *)in, "/api/get_playlist", 17) == 0)
|
||||
response_size = mpd_put_playlist(response_buffer + 98);
|
||||
else
|
||||
{
|
||||
/* invalid request, close connection */
|
||||
free(response_buffer);
|
||||
return -1;
|
||||
}
|
||||
p += response_size + sprintf(p, "HTTP/1.0 200 OK\x0d\x0a"
|
||||
"Server: libwebsockets\x0d\x0a"
|
||||
"Content-Type: application/json\x0d\x0a"
|
||||
"Content-Length: %6lu\x0d\x0a\x0d\x0a",
|
||||
response_size
|
||||
);
|
||||
response_buffer[98] = '{';
|
||||
|
||||
n = libwebsocket_write(wsi, (unsigned char *)response_buffer,
|
||||
p - response_buffer, LWS_WRITE_HTTP);
|
||||
|
||||
free(response_buffer);
|
||||
/*
|
||||
* book us a LWS_CALLBACK_HTTP_WRITEABLE callback
|
||||
*/
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
|
||||
}
|
||||
sprintf(buf, "%s%s", resource_path, whitelist[n].urlpath);
|
||||
|
||||
if (libwebsockets_serve_http_file(context, wsi, buf, whitelist[n].mimetype))
|
||||
return -1; /* through completion or error, close the socket */
|
||||
else if(in && strcmp((const char *)in, "getPlaylist") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for (n = 0; n < (sizeof(whitelist) / sizeof(whitelist[0]) - 1); n++)
|
||||
{
|
||||
if (in && strcmp((const char *)in, whitelist[n].urlpath) == 0)
|
||||
break;
|
||||
}
|
||||
sprintf(buf, "%s%s", resource_path, whitelist[n].urlpath);
|
||||
|
||||
if (libwebsockets_serve_http_file(context, wsi, buf, whitelist[n].mimetype))
|
||||
return -1; /* through completion or error, close the socket */
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
struct per_session_data__http {
|
||||
int fd;
|
||||
};
|
||||
|
||||
int callback_http(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
|
||||
@@ -21,6 +21,11 @@ enum mpd_conn_states mpd_conn_state = MPD_DISCONNECTED;
|
||||
enum mpd_state mpd_play_state = MPD_STATE_UNKNOWN;
|
||||
unsigned queue_version;
|
||||
|
||||
void *mpd_idle_connection(void *_data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int callback_ympd(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason,
|
||||
@@ -251,24 +256,30 @@ int mpd_put_state(char *buffer)
|
||||
|
||||
int mpd_put_current_song(char *buffer)
|
||||
{
|
||||
char *cur = buffer;
|
||||
const char *end = buffer + MAX_SIZE;
|
||||
struct mpd_song *song;
|
||||
int len;
|
||||
|
||||
song = mpd_run_current_song(conn);
|
||||
if(song == NULL)
|
||||
return 0;
|
||||
|
||||
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"current_song\", \"data\":"
|
||||
"{\"pos\":%d, \"title\":\"%s\", \"artist\":\"%s\", \"album\":\"%s\"}}",
|
||||
cur += snprintf(cur, end - cur, "{\"type\": \"current_song\", \"data\":"
|
||||
"{\"pos\":%d, \"title\":\"%s\"",
|
||||
mpd_song_get_pos(song),
|
||||
mpd_get_title(song),
|
||||
mpd_song_get_tag(song, MPD_TAG_ARTIST, 0),
|
||||
mpd_song_get_tag(song, MPD_TAG_ALBUM, 0)
|
||||
);
|
||||
mpd_get_title(song));
|
||||
if(mpd_song_get_tag(song, MPD_TAG_ARTIST, 0) != NULL)
|
||||
cur += snprintf(cur, end - cur, ", \"artist\":\"%s\"",
|
||||
mpd_song_get_tag(song, MPD_TAG_ARTIST, 0));
|
||||
if(mpd_song_get_tag(song, MPD_TAG_ALBUM, 0) != NULL)
|
||||
cur += snprintf(cur, end - cur, ", \"album\":\"%s\"",
|
||||
mpd_song_get_tag(song, MPD_TAG_ALBUM, 0));
|
||||
|
||||
cur += snprintf(cur, end - cur, "}}");
|
||||
mpd_song_free(song);
|
||||
mpd_response_finish(conn);
|
||||
|
||||
return len;
|
||||
return cur - buffer;
|
||||
}
|
||||
|
||||
int mpd_put_playlist(char *buffer)
|
||||
@@ -342,8 +353,9 @@ int mpd_put_browse(char *buffer, char *path)
|
||||
case MPD_ENTITY_TYPE_DIRECTORY:
|
||||
dir = mpd_entity_get_directory(entity);
|
||||
cur += snprintf(cur, end - cur,
|
||||
"{\"type\":\"directory\",\"dir\":\"%s\"},",
|
||||
mpd_directory_get_path(dir)
|
||||
"{\"type\":\"directory\",\"dir\":\"%s\", \"basename\":\"%s\"},",
|
||||
mpd_directory_get_path(dir),
|
||||
basename((char *)mpd_directory_get_path(dir))
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ enum mpd_conn_states {
|
||||
MPD_CONNECTED
|
||||
};
|
||||
|
||||
void *mpd_idle_connection(void *_data);
|
||||
int callback_ympd(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason,
|
||||
|
||||
40
src/urldecode.c
Normal file
40
src/urldecode.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
from http://www.geekhideout.com/urlcode.shtml
|
||||
public domain
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Converts a hex character to its integer value */
|
||||
char from_hex(char ch) {
|
||||
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
|
||||
}
|
||||
|
||||
/* Converts an integer value to its hex character*/
|
||||
char to_hex(char code) {
|
||||
static char hex[] = "0123456789abcdef";
|
||||
return hex[code & 15];
|
||||
}
|
||||
|
||||
/* Returns a url-decoded version of str */
|
||||
/* IMPORTANT: be sure to free() the returned string after use */
|
||||
char *url_decode(char *str) {
|
||||
char *pstr = str, *buf = malloc(strlen(str) + 1), *pbuf = buf;
|
||||
while (*pstr) {
|
||||
if (*pstr == '%') {
|
||||
if (pstr[1] && pstr[2]) {
|
||||
*pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
|
||||
pstr += 2;
|
||||
}
|
||||
} else if (*pstr == '+') {
|
||||
*pbuf++ = ' ';
|
||||
} else {
|
||||
*pbuf++ = *pstr;
|
||||
}
|
||||
pstr++;
|
||||
}
|
||||
*pbuf = '\0';
|
||||
return buf;
|
||||
}
|
||||
1
src/ympd_process.c
Normal file
1
src/ympd_process.c
Normal file
@@ -0,0 +1 @@
|
||||
ympd_process.c
|
||||
Reference in New Issue
Block a user