mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 23:25:56 -05:00
[httpd] More refactoring, reduce code duplication in the httpd_xxx modules
This commit is contained in:
parent
9ed810d9df
commit
473a29ef8a
17
src/cache.c
17
src/cache.c
@ -47,13 +47,14 @@
|
||||
#include "commands.h"
|
||||
|
||||
|
||||
#define CACHE_VERSION 2
|
||||
#define CACHE_VERSION 3
|
||||
|
||||
|
||||
struct cache_arg
|
||||
{
|
||||
char *query; // daap query
|
||||
char *ua; // user agent
|
||||
int is_remote;
|
||||
int msec;
|
||||
|
||||
char *path; // artwork path
|
||||
@ -139,6 +140,7 @@ cache_create_tables(void)
|
||||
" id INTEGER PRIMARY KEY NOT NULL," \
|
||||
" query VARCHAR(4096) UNIQUE NOT NULL," \
|
||||
" user_agent VARCHAR(1024)," \
|
||||
" is_remote INTEGER DEFAULT 0," \
|
||||
" msec INTEGER DEFAULT 0," \
|
||||
" timestamp INTEGER DEFAULT 0" \
|
||||
");"
|
||||
@ -605,7 +607,7 @@ cache_daap_reply_add(const char *query, struct evbuffer *evbuf)
|
||||
static enum command_state
|
||||
cache_daap_query_add(void *arg, int *retval)
|
||||
{
|
||||
#define Q_TMPL "INSERT OR REPLACE INTO queries (user_agent, query, msec, timestamp) VALUES ('%q', '%q', %d, %" PRIi64 ");"
|
||||
#define Q_TMPL "INSERT OR REPLACE INTO queries (user_agent, is_remote, query, msec, timestamp) VALUES ('%q', %d, '%q', %d, %" PRIi64 ");"
|
||||
#define Q_CLEANUP "DELETE FROM queries WHERE id NOT IN (SELECT id FROM queries ORDER BY timestamp DESC LIMIT 20);"
|
||||
struct cache_arg *cmdarg;
|
||||
struct timeval delay = { 60, 0 };
|
||||
@ -631,7 +633,7 @@ cache_daap_query_add(void *arg, int *retval)
|
||||
remove_tag(cmdarg->query, "session-id");
|
||||
remove_tag(cmdarg->query, "revision-number");
|
||||
|
||||
query = sqlite3_mprintf(Q_TMPL, cmdarg->ua, cmdarg->query, cmdarg->msec, (int64_t)time(NULL));
|
||||
query = sqlite3_mprintf(Q_TMPL, cmdarg->ua, cmdarg->is_remote, cmdarg->query, cmdarg->msec, (int64_t)time(NULL));
|
||||
if (!query)
|
||||
{
|
||||
DPRINTF(E_LOG, L_CACHE, "Out of memory making query string.\n");
|
||||
@ -809,7 +811,7 @@ cache_daap_update_cb(int fd, short what, void *arg)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = sqlite3_prepare_v2(g_db_hdl, "SELECT id, user_agent, query FROM queries;", -1, &stmt, 0);
|
||||
ret = sqlite3_prepare_v2(g_db_hdl, "SELECT id, user_agent, is_remote, query FROM queries;", -1, &stmt, 0);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_LOG, L_CACHE, "Error preparing for cache update: %s\n", sqlite3_errmsg(g_db_hdl));
|
||||
@ -818,9 +820,9 @@ cache_daap_update_cb(int fd, short what, void *arg)
|
||||
|
||||
while ((ret = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
query = strdup((char *)sqlite3_column_text(stmt, 2));
|
||||
query = strdup((char *)sqlite3_column_text(stmt, 3));
|
||||
|
||||
evbuf = daap_reply_build(query, (char *)sqlite3_column_text(stmt, 1));
|
||||
evbuf = daap_reply_build(query, (char *)sqlite3_column_text(stmt, 1), sqlite3_column_int(stmt, 2));
|
||||
if (!evbuf)
|
||||
{
|
||||
DPRINTF(E_LOG, L_CACHE, "Error building DAAP reply for query: %s\n", query);
|
||||
@ -1329,7 +1331,7 @@ cache_daap_get(struct evbuffer *evbuf, const char *query)
|
||||
}
|
||||
|
||||
void
|
||||
cache_daap_add(const char *query, const char *ua, int msec)
|
||||
cache_daap_add(const char *query, const char *ua, int is_remote, int msec)
|
||||
{
|
||||
struct cache_arg *cmdarg;
|
||||
|
||||
@ -1345,6 +1347,7 @@ cache_daap_add(const char *query, const char *ua, int msec)
|
||||
|
||||
cmdarg->query = strdup(query);
|
||||
cmdarg->ua = strdup(ua);
|
||||
cmdarg->is_remote = is_remote;
|
||||
cmdarg->msec = msec;
|
||||
|
||||
commands_exec_async(cmdbase, cache_daap_query_add, cmdarg);
|
||||
|
@ -16,7 +16,7 @@ int
|
||||
cache_daap_get(struct evbuffer *evbuf, const char *query);
|
||||
|
||||
void
|
||||
cache_daap_add(const char *query, const char *ua, int msec);
|
||||
cache_daap_add(const char *query, const char *ua, int is_remote, int msec);
|
||||
|
||||
int
|
||||
cache_daap_threshold(void);
|
||||
|
41
src/httpd.c
41
src/httpd.c
@ -253,6 +253,7 @@ httpd_fixup_uri(struct evhttp_request *req)
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------- REQUEST HELPERS ------------------------------ */
|
||||
|
||||
static void
|
||||
@ -877,6 +878,46 @@ httpd_uri_parse(const char *uri)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct httpd_request *
|
||||
httpd_request_parse(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed, const char *user_agent, struct httpd_uri_map *uri_map)
|
||||
{
|
||||
struct httpd_request *hreq;
|
||||
struct evkeyvalq *headers;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
CHECK_NULL(L_HTTPD, hreq = calloc(1, sizeof(struct httpd_request)));
|
||||
|
||||
// Note req is allowed to be NULL
|
||||
hreq->req = req;
|
||||
hreq->uri_parsed = uri_parsed;
|
||||
hreq->query = &(uri_parsed->ev_query);
|
||||
|
||||
if (req && !user_agent)
|
||||
{
|
||||
headers = evhttp_request_get_input_headers(req);
|
||||
hreq->user_agent = evhttp_find_header(headers, "User-Agent");
|
||||
}
|
||||
else
|
||||
hreq->user_agent = user_agent;
|
||||
|
||||
// Find a handler for the path
|
||||
for (i = 0; uri_map[i].handler; i++)
|
||||
{
|
||||
ret = regexec(&uri_map[i].preg, uri_parsed->path, 0, NULL, 0);
|
||||
if (ret == 0)
|
||||
{
|
||||
hreq->handler = uri_map[i].handler;
|
||||
return hreq; // Success
|
||||
}
|
||||
}
|
||||
|
||||
// Handler not found, that's an error
|
||||
free(hreq);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Thread: httpd */
|
||||
void
|
||||
httpd_stream_file(struct evhttp_request *req, int id)
|
||||
|
46
src/httpd.h
46
src/httpd.h
@ -2,10 +2,11 @@
|
||||
#ifndef __HTTPD_H__
|
||||
#define __HTTPD_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <regex.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/keyvalq_struct.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum httpd_send_flags
|
||||
{
|
||||
@ -36,6 +37,40 @@ struct httpd_uri_parsed
|
||||
char *path_parts[7];
|
||||
};
|
||||
|
||||
/*
|
||||
* A collection of pointers to request data that the reply handlers may need.
|
||||
* Also has the function pointer to the reply handler and a pointer to a reply
|
||||
* evbuffer.
|
||||
*/
|
||||
struct httpd_request {
|
||||
// User-agent (if available)
|
||||
const char *user_agent;
|
||||
// The parsed request URI given to us by httpd_uri_parse
|
||||
struct httpd_uri_parsed *uri_parsed;
|
||||
// Shortcut to &uri_parsed->ev_query
|
||||
struct evkeyvalq *query;
|
||||
// http request struct (if available)
|
||||
struct evhttp_request *req;
|
||||
// A pointer to extra data that the module handling the request might need
|
||||
void *extra_data;
|
||||
|
||||
// Reply evbuffer
|
||||
struct evbuffer *reply;
|
||||
|
||||
// A pointer to the handler that will process the request
|
||||
int (*handler)(struct httpd_request *hreq);
|
||||
};
|
||||
|
||||
/*
|
||||
* Maps a regex of the request path to a handler of the request
|
||||
*/
|
||||
struct httpd_uri_map
|
||||
{
|
||||
char *regexp;
|
||||
int (*handler)(struct httpd_request *hreq);
|
||||
regex_t preg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper to free the parsed uri struct
|
||||
*/
|
||||
@ -48,6 +83,15 @@ httpd_uri_free(struct httpd_uri_parsed *parsed);
|
||||
struct httpd_uri_parsed *
|
||||
httpd_uri_parse(const char *uri);
|
||||
|
||||
/*
|
||||
* Parse a request into the httpd_request struct. It can later be freed with
|
||||
* free(), unless the module has allocated something to *extra_data. Note that
|
||||
* the pointers in the returned struct are only valid as long as the inputs are
|
||||
* still valid. If req is not null, then we will find the user-agent from the
|
||||
* request headers, except if provided as an argument to this function.
|
||||
*/
|
||||
struct httpd_request *
|
||||
httpd_request_parse(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed, const char *user_agent, struct httpd_uri_map *uri_map);
|
||||
|
||||
void
|
||||
httpd_stream_file(struct evhttp_request *req, int id);
|
||||
|
613
src/httpd_daap.c
613
src/httpd_daap.c
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,6 @@ int
|
||||
daap_session_is_valid(int id);
|
||||
|
||||
struct evbuffer *
|
||||
daap_reply_build(const char *uri, const char *user_agent);
|
||||
daap_reply_build(const char *uri, const char *user_agent, int is_remote);
|
||||
|
||||
#endif /* !__HTTPD_DAAP_H__ */
|
||||
|
701
src/httpd_dacp.c
701
src/httpd_dacp.c
File diff suppressed because it is too large
Load Diff
@ -49,26 +49,6 @@
|
||||
# include "spotify.h"
|
||||
#endif
|
||||
|
||||
struct json_request {
|
||||
// The parsed request URI given to us by httpd.c
|
||||
struct httpd_uri_parsed *uri_parsed;
|
||||
// Shortcut to &uri_parsed->ev_query
|
||||
struct evkeyvalq *query;
|
||||
// http request struct
|
||||
struct evhttp_request *req;
|
||||
// A pointer to the handler that will process the request
|
||||
int (*handler)(struct evbuffer *reply, struct json_request *jreq);
|
||||
};
|
||||
|
||||
struct uri_map
|
||||
{
|
||||
regex_t preg;
|
||||
char *regexp;
|
||||
int (*handler)(struct evbuffer *reply, struct json_request *jreq);
|
||||
};
|
||||
|
||||
/* Forward declaration of handlers */
|
||||
static struct uri_map adm_handlers[];
|
||||
|
||||
/* -------------------------------- HELPERS --------------------------------- */
|
||||
|
||||
@ -147,44 +127,6 @@ pairing_get(struct evbuffer *evbuf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct json_request *
|
||||
json_request_parse(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
{
|
||||
struct json_request *jreq;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
CHECK_NULL(L_WEB, jreq = calloc(1, sizeof(struct json_request)));
|
||||
|
||||
jreq->req = req;
|
||||
jreq->uri_parsed = uri_parsed;
|
||||
jreq->query = &(uri_parsed->ev_query);
|
||||
|
||||
// Find a handler for the path
|
||||
for (i = 0; adm_handlers[i].handler; i++)
|
||||
{
|
||||
ret = regexec(&adm_handlers[i].preg, uri_parsed->path, 0, NULL, 0);
|
||||
if (ret == 0)
|
||||
{
|
||||
jreq->handler = adm_handlers[i].handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!jreq->handler)
|
||||
{
|
||||
DPRINTF(E_LOG, L_WEB, "Unrecognized path '%s' in JSON api request: '%s'\n", uri_parsed->path, uri_parsed->uri);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return jreq;
|
||||
|
||||
error:
|
||||
free(jreq);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------- REPLY HANDLERS ------------------------------- */
|
||||
|
||||
@ -199,7 +141,7 @@ json_request_parse(struct evhttp_request *req, struct httpd_uri_parsed *uri_pars
|
||||
* }
|
||||
*/
|
||||
static int
|
||||
jsonapi_reply_config(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_config(struct httpd_request *hreq)
|
||||
{
|
||||
json_object *jreply;
|
||||
json_object *buildopts;
|
||||
@ -229,7 +171,7 @@ jsonapi_reply_config(struct evbuffer *reply, struct json_request *jreq)
|
||||
}
|
||||
json_object_object_add(jreply, "buildoptions", buildopts);
|
||||
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(reply, "%s", json_object_to_json_string(jreply)));
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply)));
|
||||
|
||||
jparse_free(jreply);
|
||||
|
||||
@ -250,7 +192,7 @@ jsonapi_reply_config(struct evbuffer *reply, struct json_request *jreq)
|
||||
*}
|
||||
*/
|
||||
static int
|
||||
jsonapi_reply_library(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_library(struct httpd_request *hreq)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct filecount_info fci;
|
||||
@ -276,9 +218,7 @@ jsonapi_reply_library(struct evbuffer *reply, struct json_request *jreq)
|
||||
|
||||
is_scanning = library_is_scanning();
|
||||
|
||||
|
||||
// Build json response
|
||||
|
||||
CHECK_NULL(L_WEB, jreply = json_object_new_object());
|
||||
|
||||
json_object_object_add(jreply, "artists", json_object_new_int(artists));
|
||||
@ -287,7 +227,7 @@ jsonapi_reply_library(struct evbuffer *reply, struct json_request *jreq)
|
||||
json_object_object_add(jreply, "db_playtime", json_object_new_int64((fci.length / 1000)));
|
||||
json_object_object_add(jreply, "updating", json_object_new_boolean(is_scanning));
|
||||
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(reply, "%s", json_object_to_json_string(jreply)));
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply)));
|
||||
|
||||
jparse_free(jreply);
|
||||
|
||||
@ -298,7 +238,7 @@ jsonapi_reply_library(struct evbuffer *reply, struct json_request *jreq)
|
||||
* Endpoint to trigger a library rescan
|
||||
*/
|
||||
static int
|
||||
jsonapi_reply_update(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_update(struct httpd_request *hreq)
|
||||
{
|
||||
library_rescan();
|
||||
return 0;
|
||||
@ -315,7 +255,7 @@ jsonapi_reply_update(struct evbuffer *reply, struct json_request *jreq)
|
||||
* }
|
||||
*/
|
||||
static int
|
||||
jsonapi_reply_spotify(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_spotify(struct httpd_request *hreq)
|
||||
{
|
||||
json_object *jreply;
|
||||
|
||||
@ -354,7 +294,7 @@ jsonapi_reply_spotify(struct evbuffer *reply, struct json_request *jreq)
|
||||
json_object_object_add(jreply, "enabled", json_object_new_boolean(false));
|
||||
#endif
|
||||
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(reply, "%s", json_object_to_json_string(jreply)));
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply)));
|
||||
|
||||
jparse_free(jreply);
|
||||
|
||||
@ -362,7 +302,7 @@ jsonapi_reply_spotify(struct evbuffer *reply, struct json_request *jreq)
|
||||
}
|
||||
|
||||
static int
|
||||
jsonapi_reply_spotify_login(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_spotify_login(struct httpd_request *hreq)
|
||||
{
|
||||
#ifdef HAVE_SPOTIFY_H
|
||||
struct evbuffer *in_evbuf;
|
||||
@ -376,7 +316,7 @@ jsonapi_reply_spotify_login(struct evbuffer *reply, struct json_request *jreq)
|
||||
|
||||
DPRINTF(E_DBG, L_WEB, "Received Spotify login request\n");
|
||||
|
||||
in_evbuf = evhttp_request_get_input_buffer(jreq->req);
|
||||
in_evbuf = evhttp_request_get_input_buffer(hreq->req);
|
||||
|
||||
request = jparse_obj_from_evbuffer(in_evbuf);
|
||||
if (!request)
|
||||
@ -418,7 +358,7 @@ jsonapi_reply_spotify_login(struct evbuffer *reply, struct json_request *jreq)
|
||||
json_object_object_add(jreply, "errors", errors);
|
||||
}
|
||||
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(reply, "%s", json_object_to_json_string(jreply)));
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply)));
|
||||
|
||||
jparse_free(jreply);
|
||||
|
||||
@ -436,18 +376,18 @@ jsonapi_reply_spotify_login(struct evbuffer *reply, struct json_request *jreq)
|
||||
* If request is a POST request, tries to pair the active remote with the given pin.
|
||||
*/
|
||||
static int
|
||||
jsonapi_reply_pairing(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_pairing(struct httpd_request *hreq)
|
||||
{
|
||||
if (evhttp_request_get_command(jreq->req) == EVHTTP_REQ_POST)
|
||||
if (evhttp_request_get_command(hreq->req) == EVHTTP_REQ_POST)
|
||||
{
|
||||
return pairing_kickoff(jreq->req);
|
||||
return pairing_kickoff(hreq->req);
|
||||
}
|
||||
|
||||
return pairing_get(reply);
|
||||
return pairing_get(hreq->reply);
|
||||
}
|
||||
|
||||
static int
|
||||
jsonapi_reply_lastfm(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_lastfm(struct httpd_request *hreq)
|
||||
{
|
||||
json_object *jreply;
|
||||
bool enabled = false;
|
||||
@ -463,7 +403,7 @@ jsonapi_reply_lastfm(struct evbuffer *reply, struct json_request *jreq)
|
||||
json_object_object_add(jreply, "enabled", json_object_new_boolean(enabled));
|
||||
json_object_object_add(jreply, "scrobbling_enabled", json_object_new_boolean(scrobbling_enabled));
|
||||
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(reply, "%s", json_object_to_json_string(jreply)));
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply)));
|
||||
|
||||
jparse_free(jreply);
|
||||
|
||||
@ -474,7 +414,7 @@ jsonapi_reply_lastfm(struct evbuffer *reply, struct json_request *jreq)
|
||||
* Endpoint to log into LastFM
|
||||
*/
|
||||
static int
|
||||
jsonapi_reply_lastfm_login(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_lastfm_login(struct httpd_request *hreq)
|
||||
{
|
||||
#ifdef LASTFM
|
||||
struct evbuffer *in_evbuf;
|
||||
@ -488,7 +428,7 @@ jsonapi_reply_lastfm_login(struct evbuffer *reply, struct json_request *jreq)
|
||||
|
||||
DPRINTF(E_DBG, L_WEB, "Received LastFM login request\n");
|
||||
|
||||
in_evbuf = evhttp_request_get_input_buffer(jreq->req);
|
||||
in_evbuf = evhttp_request_get_input_buffer(hreq->req);
|
||||
request = jparse_obj_from_evbuffer(in_evbuf);
|
||||
if (!request)
|
||||
{
|
||||
@ -532,7 +472,7 @@ jsonapi_reply_lastfm_login(struct evbuffer *reply, struct json_request *jreq)
|
||||
json_object_object_add(jreply, "errors", errors);
|
||||
}
|
||||
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(reply, "%s", json_object_to_json_string(jreply)));
|
||||
CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply)));
|
||||
|
||||
jparse_free(jreply);
|
||||
|
||||
@ -544,7 +484,7 @@ jsonapi_reply_lastfm_login(struct evbuffer *reply, struct json_request *jreq)
|
||||
}
|
||||
|
||||
static int
|
||||
jsonapi_reply_lastfm_logout(struct evbuffer *reply, struct json_request *jreq)
|
||||
jsonapi_reply_lastfm_logout(struct httpd_request *hreq)
|
||||
{
|
||||
#ifdef LASTFM
|
||||
lastfm_logout();
|
||||
@ -552,7 +492,7 @@ jsonapi_reply_lastfm_logout(struct evbuffer *reply, struct json_request *jreq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct uri_map adm_handlers[] =
|
||||
static struct httpd_uri_map adm_handlers[] =
|
||||
{
|
||||
{ .regexp = "^/api/config", .handler = jsonapi_reply_config },
|
||||
{ .regexp = "^/api/library", .handler = jsonapi_reply_library },
|
||||
@ -572,8 +512,7 @@ static struct uri_map adm_handlers[] =
|
||||
void
|
||||
jsonapi_request(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
{
|
||||
struct json_request *jreq;
|
||||
struct evbuffer *reply;
|
||||
struct httpd_request *hreq;
|
||||
struct evkeyvalq *headers;
|
||||
int ret;
|
||||
|
||||
@ -585,9 +524,11 @@ jsonapi_request(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
return;
|
||||
}
|
||||
|
||||
jreq = json_request_parse(req, uri_parsed);
|
||||
if (!jreq)
|
||||
hreq = httpd_request_parse(req, uri_parsed, NULL, adm_handlers);
|
||||
if (!hreq)
|
||||
{
|
||||
DPRINTF(E_LOG, L_WEB, "Unrecognized path '%s' in JSON api request: '%s'\n", uri_parsed->path, uri_parsed->uri);
|
||||
|
||||
httpd_send_error(req, HTTP_BADREQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
@ -595,9 +536,9 @@ jsonapi_request(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
evhttp_add_header(headers, "DAAP-Server", "forked-daapd/" VERSION);
|
||||
|
||||
CHECK_NULL(L_WEB, reply = evbuffer_new());
|
||||
CHECK_NULL(L_WEB, hreq->reply = evbuffer_new());
|
||||
|
||||
ret = jreq->handler(reply, jreq);
|
||||
ret = hreq->handler(hreq);
|
||||
if (ret < 0)
|
||||
{
|
||||
httpd_send_error(req, 500, "Internal Server Error");
|
||||
@ -606,11 +547,11 @@ jsonapi_request(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
|
||||
evhttp_add_header(headers, "Content-Type", "application/json");
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", reply, 0);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", hreq->reply, 0);
|
||||
|
||||
error:
|
||||
evbuffer_free(reply);
|
||||
free(jreq);
|
||||
evbuffer_free(hreq->reply);
|
||||
free(hreq);
|
||||
}
|
||||
|
||||
int
|
||||
@ -654,4 +595,3 @@ jsonapi_deinit(void)
|
||||
for (i = 0; adm_handlers[i].handler; i++)
|
||||
regfree(&adm_handlers[i].preg);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <regex.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
@ -37,72 +36,12 @@
|
||||
# include "spotify.h"
|
||||
#endif
|
||||
|
||||
struct oauth_request {
|
||||
// The parsed request URI given to us by httpd.c
|
||||
struct httpd_uri_parsed *uri_parsed;
|
||||
// Shortcut to &uri_parsed->ev_query
|
||||
struct evkeyvalq *query;
|
||||
// http request struct
|
||||
struct evhttp_request *req;
|
||||
// A pointer to the handler that will process the request
|
||||
void (*handler)(struct oauth_request *oreq);
|
||||
};
|
||||
|
||||
struct uri_map {
|
||||
regex_t preg;
|
||||
char *regexp;
|
||||
void (*handler)(struct oauth_request *oreq);
|
||||
};
|
||||
|
||||
/* Forward declaration of handlers */
|
||||
static struct uri_map oauth_handlers[];
|
||||
|
||||
|
||||
/* ------------------------------- HELPERS ---------------------------------- */
|
||||
|
||||
static struct oauth_request *
|
||||
oauth_request_parse(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
{
|
||||
struct oauth_request *oreq;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
CHECK_NULL(L_WEB, oreq = calloc(1, sizeof(struct oauth_request)));
|
||||
|
||||
oreq->req = req;
|
||||
oreq->uri_parsed = uri_parsed;
|
||||
oreq->query = &(uri_parsed->ev_query);
|
||||
|
||||
for (i = 0; oauth_handlers[i].handler; i++)
|
||||
{
|
||||
ret = regexec(&oauth_handlers[i].preg, uri_parsed->path, 0, NULL, 0);
|
||||
if (ret == 0)
|
||||
{
|
||||
oreq->handler = oauth_handlers[i].handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!oreq->handler)
|
||||
{
|
||||
DPRINTF(E_LOG, L_WEB, "Unrecognized path '%s' in OAuth request: '%s'\n", uri_parsed->path, uri_parsed->uri);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return oreq;
|
||||
|
||||
error:
|
||||
free(oreq);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------- REPLY HANDLERS ------------------------------- */
|
||||
|
||||
#ifdef HAVE_SPOTIFY_H
|
||||
static void
|
||||
oauth_reply_spotify(struct oauth_request *oreq)
|
||||
static int
|
||||
oauth_reply_spotify(struct httpd_request *hreq)
|
||||
{
|
||||
char redirect_uri[256];
|
||||
char *errmsg;
|
||||
@ -112,28 +51,32 @@ oauth_reply_spotify(struct oauth_request *oreq)
|
||||
httpd_port = cfg_getint(cfg_getsec(cfg, "library"), "port");
|
||||
|
||||
snprintf(redirect_uri, sizeof(redirect_uri), "http://forked-daapd.local:%d/oauth/spotify", httpd_port);
|
||||
ret = spotify_oauth_callback(oreq->query, redirect_uri, &errmsg);
|
||||
ret = spotify_oauth_callback(hreq->query, redirect_uri, &errmsg);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_WEB, "Could not parse Spotify OAuth callback: '%s'\n", oreq->uri_parsed->uri);
|
||||
httpd_send_error(oreq->req, HTTP_INTERNAL, errmsg);
|
||||
DPRINTF(E_LOG, L_WEB, "Could not parse Spotify OAuth callback: '%s'\n", hreq->uri_parsed->uri);
|
||||
httpd_send_error(hreq->req, HTTP_INTERNAL, errmsg);
|
||||
free(errmsg);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
httpd_redirect_to_admin(oreq->req);
|
||||
httpd_redirect_to_admin(hreq->req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static void
|
||||
oauth_reply_spotify(struct oauth_request *oreq)
|
||||
static int
|
||||
oauth_reply_spotify(struct httpd_request *hreq)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "This version of forked-daapd was built without support for Spotify\n");
|
||||
|
||||
httpd_send_error(oreq->req, HTTP_NOTFOUND, "This version of forked-daapd was built without support for Spotify");
|
||||
httpd_send_error(hreq->req, HTTP_NOTFOUND, "This version of forked-daapd was built without support for Spotify");
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct uri_map oauth_handlers[] =
|
||||
static struct httpd_uri_map oauth_handlers[] =
|
||||
{
|
||||
{
|
||||
.regexp = "^/oauth/spotify$",
|
||||
@ -151,20 +94,22 @@ static struct uri_map oauth_handlers[] =
|
||||
void
|
||||
oauth_request(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
{
|
||||
struct oauth_request *oreq;
|
||||
struct httpd_request *hreq;
|
||||
|
||||
DPRINTF(E_LOG, L_WEB, "OAuth request: '%s'\n", uri_parsed->uri);
|
||||
|
||||
oreq = oauth_request_parse(req, uri_parsed);
|
||||
if (!oreq)
|
||||
hreq = httpd_request_parse(req, uri_parsed, NULL, oauth_handlers);
|
||||
if (!hreq)
|
||||
{
|
||||
DPRINTF(E_LOG, L_WEB, "Unrecognized path '%s' in OAuth request: '%s'\n", uri_parsed->path, uri_parsed->uri);
|
||||
|
||||
httpd_send_error(req, HTTP_NOTFOUND, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
oreq->handler(oreq);
|
||||
hreq->handler(hreq);
|
||||
|
||||
free(oreq);
|
||||
free(hreq);
|
||||
}
|
||||
|
||||
int
|
||||
|
205
src/httpd_rsp.c
205
src/httpd_rsp.c
@ -28,7 +28,6 @@
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <mxml.h>
|
||||
@ -52,24 +51,6 @@
|
||||
#define F_DETAILED (1 << 3)
|
||||
#define F_ALWAYS (F_FULL | F_BROWSE | F_ID | F_DETAILED)
|
||||
|
||||
// Will be filled out by rsp_request_parse()
|
||||
struct rsp_request {
|
||||
// The parsed request URI given to us by httpd.c
|
||||
struct httpd_uri_parsed *uri_parsed;
|
||||
// Shortcut to &uri_parsed->ev_query
|
||||
struct evkeyvalq *query;
|
||||
// http request struct
|
||||
struct evhttp_request *req;
|
||||
// A pointer to the handler that will process the request
|
||||
void (*handler)(struct rsp_request *rreq);
|
||||
};
|
||||
|
||||
struct uri_map {
|
||||
regex_t preg;
|
||||
char *regexp;
|
||||
void (*handler)(struct rsp_request *rreq);
|
||||
};
|
||||
|
||||
struct field_map {
|
||||
char *field;
|
||||
size_t offset;
|
||||
@ -133,9 +114,6 @@ static const struct field_map rsp_fields[] =
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
/* Forward declaration of handlers */
|
||||
static struct uri_map rsp_handlers[];
|
||||
|
||||
|
||||
/* -------------------------------- HELPERS --------------------------------- */
|
||||
|
||||
@ -226,31 +204,31 @@ rsp_send_error(struct evhttp_request *req, char *errmsg)
|
||||
}
|
||||
|
||||
static int
|
||||
query_params_set(struct query_params *qp, struct rsp_request *rreq)
|
||||
query_params_set(struct query_params *qp, struct httpd_request *hreq)
|
||||
{
|
||||
const char *param;
|
||||
int ret;
|
||||
|
||||
qp->offset = 0;
|
||||
param = evhttp_find_header(rreq->query, "offset");
|
||||
param = evhttp_find_header(hreq->query, "offset");
|
||||
if (param)
|
||||
{
|
||||
ret = safe_atoi32(param, &qp->offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
rsp_send_error(rreq->req, "Invalid offset");
|
||||
rsp_send_error(hreq->req, "Invalid offset");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
qp->limit = 0;
|
||||
param = evhttp_find_header(rreq->query, "limit");
|
||||
param = evhttp_find_header(hreq->query, "limit");
|
||||
if (param)
|
||||
{
|
||||
ret = safe_atoi32(param, &qp->limit);
|
||||
if (ret < 0)
|
||||
{
|
||||
rsp_send_error(rreq->req, "Invalid limit");
|
||||
rsp_send_error(hreq->req, "Invalid limit");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -262,7 +240,7 @@ query_params_set(struct query_params *qp, struct rsp_request *rreq)
|
||||
|
||||
qp->sort = S_NONE;
|
||||
|
||||
param = evhttp_find_header(rreq->query, "query");
|
||||
param = evhttp_find_header(hreq->query, "query");
|
||||
if (param)
|
||||
{
|
||||
DPRINTF(E_DBG, L_RSP, "RSP browse query filter: %s\n", param);
|
||||
@ -300,46 +278,8 @@ rsp_send_reply(struct evhttp_request *req, mxml_node_t *reply)
|
||||
evbuffer_free(evbuf);
|
||||
}
|
||||
|
||||
static struct rsp_request *
|
||||
rsp_request_parse(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
{
|
||||
struct rsp_request *rreq;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
CHECK_NULL(L_DAAP, rreq = calloc(1, sizeof(struct rsp_request)));
|
||||
|
||||
rreq->req = req;
|
||||
rreq->uri_parsed = uri_parsed;
|
||||
rreq->query = &(uri_parsed->ev_query);
|
||||
|
||||
// Find a handler for the path
|
||||
for (i = 0; rsp_handlers[i].handler; i++)
|
||||
{
|
||||
ret = regexec(&rsp_handlers[i].preg, uri_parsed->path, 0, NULL, 0);
|
||||
if (ret == 0)
|
||||
{
|
||||
rreq->handler = rsp_handlers[i].handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rreq->handler)
|
||||
{
|
||||
DPRINTF(E_LOG, L_RSP, "Unrecognized path '%s' in RSP request: '%s'\n", uri_parsed->path, uri_parsed->uri);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return rreq;
|
||||
|
||||
error:
|
||||
free(rreq);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
rsp_request_authorize(struct rsp_request *rreq)
|
||||
rsp_request_authorize(struct httpd_request *hreq)
|
||||
{
|
||||
char *passwd;
|
||||
int ret;
|
||||
@ -354,7 +294,7 @@ rsp_request_authorize(struct rsp_request *rreq)
|
||||
DPRINTF(E_DBG, L_RSP, "Checking authentication for library\n");
|
||||
|
||||
// We don't care about the username
|
||||
ret = httpd_basic_auth(rreq->req, NULL, passwd, cfg_getstr(cfg_getsec(cfg, "library"), "name"));
|
||||
ret = httpd_basic_auth(hreq->req, NULL, passwd, cfg_getstr(cfg_getsec(cfg, "library"), "name"));
|
||||
if (ret != 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_RSP, "Unsuccessful library authentication\n");
|
||||
@ -367,8 +307,8 @@ rsp_request_authorize(struct rsp_request *rreq)
|
||||
|
||||
/* --------------------------- REPLY HANDLERS ------------------------------- */
|
||||
|
||||
static void
|
||||
rsp_reply_info(struct rsp_request *rreq)
|
||||
static int
|
||||
rsp_reply_info(struct httpd_request *hreq)
|
||||
{
|
||||
mxml_node_t *reply;
|
||||
mxml_node_t *status;
|
||||
@ -418,11 +358,13 @@ rsp_reply_info(struct rsp_request *rreq)
|
||||
node = mxmlNewElement(info, "name");
|
||||
mxmlNewText(node, 0, library);
|
||||
|
||||
rsp_send_reply(rreq->req, reply);
|
||||
rsp_send_reply(hreq->req, reply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rsp_reply_db(struct rsp_request *rreq)
|
||||
static int
|
||||
rsp_reply_db(struct httpd_request *hreq)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct db_playlist_info dbpli;
|
||||
@ -445,8 +387,8 @@ rsp_reply_db(struct rsp_request *rreq)
|
||||
{
|
||||
DPRINTF(E_LOG, L_RSP, "Could not start query\n");
|
||||
|
||||
rsp_send_error(rreq->req, "Could not start query");
|
||||
return;
|
||||
rsp_send_error(hreq->req, "Could not start query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We'd use mxmlNewXML(), but then we can't put any attributes
|
||||
@ -495,8 +437,8 @@ rsp_reply_db(struct rsp_request *rreq)
|
||||
|
||||
mxmlDelete(reply);
|
||||
db_query_end(&qp);
|
||||
rsp_send_error(rreq->req, "Error fetching query results");
|
||||
return;
|
||||
rsp_send_error(hreq->req, "Error fetching query results");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* HACK
|
||||
@ -509,11 +451,13 @@ rsp_reply_db(struct rsp_request *rreq)
|
||||
|
||||
db_query_end(&qp);
|
||||
|
||||
rsp_send_reply(rreq->req, reply);
|
||||
rsp_send_reply(hreq->req, reply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rsp_reply_playlist(struct rsp_request *rreq)
|
||||
static int
|
||||
rsp_reply_playlist(struct httpd_request *hreq)
|
||||
{
|
||||
struct query_params qp;
|
||||
struct db_media_file_info dbmfi;
|
||||
@ -536,11 +480,11 @@ rsp_reply_playlist(struct rsp_request *rreq)
|
||||
|
||||
memset(&qp, 0, sizeof(struct query_params));
|
||||
|
||||
ret = safe_atoi32(rreq->uri_parsed->path_parts[2], &qp.id);
|
||||
ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &qp.id);
|
||||
if (ret < 0)
|
||||
{
|
||||
rsp_send_error(rreq->req, "Invalid playlist ID");
|
||||
return;
|
||||
rsp_send_error(hreq->req, "Invalid playlist ID");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (qp.id == 0)
|
||||
@ -549,7 +493,7 @@ rsp_reply_playlist(struct rsp_request *rreq)
|
||||
qp.type = Q_PLITEMS;
|
||||
|
||||
mode = F_FULL;
|
||||
param = evhttp_find_header(rreq->query, "type");
|
||||
param = evhttp_find_header(hreq->query, "type");
|
||||
if (param)
|
||||
{
|
||||
if (strcasecmp(param, "full") == 0)
|
||||
@ -564,20 +508,20 @@ rsp_reply_playlist(struct rsp_request *rreq)
|
||||
DPRINTF(E_LOG, L_RSP, "Unknown browse mode %s\n", param);
|
||||
}
|
||||
|
||||
ret = query_params_set(&qp, rreq);
|
||||
ret = query_params_set(&qp, hreq);
|
||||
if (ret < 0)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
ret = db_query_start(&qp);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_RSP, "Could not start query\n");
|
||||
|
||||
rsp_send_error(rreq->req, "Could not start query");
|
||||
rsp_send_error(hreq->req, "Could not start query");
|
||||
|
||||
if (qp.filter)
|
||||
free(qp.filter);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (qp.offset > qp.results)
|
||||
@ -612,7 +556,7 @@ rsp_reply_playlist(struct rsp_request *rreq)
|
||||
/* Items block (all items) */
|
||||
while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
|
||||
{
|
||||
headers = evhttp_request_get_input_headers(rreq->req);
|
||||
headers = evhttp_request_get_input_headers(hreq->req);
|
||||
|
||||
ua = evhttp_find_header(headers, "User-Agent");
|
||||
client_codecs = evhttp_find_header(headers, "Accept-Codecs");
|
||||
@ -683,8 +627,8 @@ rsp_reply_playlist(struct rsp_request *rreq)
|
||||
|
||||
mxmlDelete(reply);
|
||||
db_query_end(&qp);
|
||||
rsp_send_error(rreq->req, "Error fetching query results");
|
||||
return;
|
||||
rsp_send_error(hreq->req, "Error fetching query results");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* HACK
|
||||
@ -697,11 +641,13 @@ rsp_reply_playlist(struct rsp_request *rreq)
|
||||
|
||||
db_query_end(&qp);
|
||||
|
||||
rsp_send_reply(rreq->req, reply);
|
||||
rsp_send_reply(hreq->req, reply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rsp_reply_browse(struct rsp_request *rreq)
|
||||
static int
|
||||
rsp_reply_browse(struct httpd_request *hreq)
|
||||
{
|
||||
struct query_params qp;
|
||||
char *browse_item;
|
||||
@ -714,43 +660,43 @@ rsp_reply_browse(struct rsp_request *rreq)
|
||||
|
||||
memset(&qp, 0, sizeof(struct query_params));
|
||||
|
||||
if (strcmp(rreq->uri_parsed->path_parts[3], "artist") == 0)
|
||||
if (strcmp(hreq->uri_parsed->path_parts[3], "artist") == 0)
|
||||
qp.type = Q_BROWSE_ARTISTS;
|
||||
else if (strcmp(rreq->uri_parsed->path_parts[3], "genre") == 0)
|
||||
else if (strcmp(hreq->uri_parsed->path_parts[3], "genre") == 0)
|
||||
qp.type = Q_BROWSE_GENRES;
|
||||
else if (strcmp(rreq->uri_parsed->path_parts[3], "album") == 0)
|
||||
else if (strcmp(hreq->uri_parsed->path_parts[3], "album") == 0)
|
||||
qp.type = Q_BROWSE_ALBUMS;
|
||||
else if (strcmp(rreq->uri_parsed->path_parts[3], "composer") == 0)
|
||||
else if (strcmp(hreq->uri_parsed->path_parts[3], "composer") == 0)
|
||||
qp.type = Q_BROWSE_COMPOSERS;
|
||||
else
|
||||
{
|
||||
DPRINTF(E_LOG, L_RSP, "Unsupported browse type '%s'\n", rreq->uri_parsed->path_parts[3]);
|
||||
DPRINTF(E_LOG, L_RSP, "Unsupported browse type '%s'\n", hreq->uri_parsed->path_parts[3]);
|
||||
|
||||
rsp_send_error(rreq->req, "Unsupported browse type");
|
||||
return;
|
||||
rsp_send_error(hreq->req, "Unsupported browse type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = safe_atoi32(rreq->uri_parsed->path_parts[2], &qp.id);
|
||||
ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &qp.id);
|
||||
if (ret < 0)
|
||||
{
|
||||
rsp_send_error(rreq->req, "Invalid playlist ID");
|
||||
return;
|
||||
rsp_send_error(hreq->req, "Invalid playlist ID");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = query_params_set(&qp, rreq);
|
||||
ret = query_params_set(&qp, hreq);
|
||||
if (ret < 0)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
ret = db_query_start(&qp);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_RSP, "Could not start query\n");
|
||||
|
||||
rsp_send_error(rreq->req, "Could not start query");
|
||||
rsp_send_error(hreq->req, "Could not start query");
|
||||
|
||||
if (qp.filter)
|
||||
free(qp.filter);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (qp.offset > qp.results)
|
||||
@ -798,8 +744,8 @@ rsp_reply_browse(struct rsp_request *rreq)
|
||||
|
||||
mxmlDelete(reply);
|
||||
db_query_end(&qp);
|
||||
rsp_send_error(rreq->req, "Error fetching query results");
|
||||
return;
|
||||
rsp_send_error(hreq->req, "Error fetching query results");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* HACK
|
||||
@ -812,24 +758,31 @@ rsp_reply_browse(struct rsp_request *rreq)
|
||||
|
||||
db_query_end(&qp);
|
||||
|
||||
rsp_send_reply(rreq->req, reply);
|
||||
rsp_send_reply(hreq->req, reply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rsp_stream(struct rsp_request *rreq)
|
||||
static int
|
||||
rsp_stream(struct httpd_request *hreq)
|
||||
{
|
||||
int id;
|
||||
int ret;
|
||||
|
||||
ret = safe_atoi32(rreq->uri_parsed->path_parts[2], &id);
|
||||
ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &id);
|
||||
if (ret < 0)
|
||||
httpd_send_error(rreq->req, HTTP_BADREQUEST, "Bad Request");
|
||||
else
|
||||
httpd_stream_file(rreq->req, id);
|
||||
{
|
||||
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
httpd_stream_file(hreq->req, id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct uri_map rsp_handlers[] =
|
||||
static struct httpd_uri_map rsp_handlers[] =
|
||||
{
|
||||
{
|
||||
.regexp = "^/rsp/info$",
|
||||
@ -863,29 +816,31 @@ static struct uri_map rsp_handlers[] =
|
||||
void
|
||||
rsp_request(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
{
|
||||
struct rsp_request *rreq;
|
||||
struct httpd_request *hreq;
|
||||
int ret;
|
||||
|
||||
DPRINTF(E_DBG, L_RSP, "RSP request: '%s'\n", uri_parsed->uri);
|
||||
|
||||
rreq = rsp_request_parse(req, uri_parsed);
|
||||
if (!rreq)
|
||||
hreq = httpd_request_parse(req, uri_parsed, NULL, rsp_handlers);
|
||||
if (!hreq)
|
||||
{
|
||||
DPRINTF(E_LOG, L_RSP, "Unrecognized path '%s' in RSP request: '%s'\n", uri_parsed->path, uri_parsed->uri);
|
||||
|
||||
rsp_send_error(req, "Server error");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = rsp_request_authorize(rreq);
|
||||
ret = rsp_request_authorize(hreq);
|
||||
if (ret < 0)
|
||||
{
|
||||
rsp_send_error(req, "Access denied");
|
||||
free(rreq);
|
||||
free(hreq);
|
||||
return;
|
||||
}
|
||||
|
||||
rreq->handler(rreq);
|
||||
hreq->handler(hreq);
|
||||
|
||||
free(rreq);
|
||||
free(hreq);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user