mirror of
				https://github.com/owntone/owntone-server.git
				synced 2025-10-29 15:55:02 -04:00 
			
		
		
		
	Merge branch 'cors' (includes modified gzip and daap cache)
This commit is contained in:
		
						commit
						2f8c061c11
					
				
							
								
								
									
										22
									
								
								src/cache.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/cache.c
									
									
									
									
									
								
							| @ -38,6 +38,7 @@ | ||||
| 
 | ||||
| #include "conffile.h" | ||||
| #include "logger.h" | ||||
| #include "httpd.h" | ||||
| #include "httpd_daap.h" | ||||
| #include "db.h" | ||||
| #include "cache.h" | ||||
| @ -680,7 +681,8 @@ cache_daap_query_add(void *arg, int *retval) | ||||
| #undef Q_TMPL | ||||
| } | ||||
| 
 | ||||
| /* Gets a reply from the cache */ | ||||
| // Gets a reply from the cache.
 | ||||
| // cmdarg->evbuf will be filled with the reply (gzipped)
 | ||||
| static enum command_state | ||||
| cache_daap_query_get(void *arg, int *retval) | ||||
| { | ||||
| @ -783,6 +785,7 @@ cache_daap_update_cb(int fd, short what, void *arg) | ||||
| { | ||||
|   sqlite3_stmt *stmt; | ||||
|   struct evbuffer *evbuf; | ||||
|   struct evbuffer *gzbuf; | ||||
|   char *errmsg; | ||||
|   char *query; | ||||
|   int ret; | ||||
| @ -818,10 +821,23 @@ cache_daap_update_cb(int fd, short what, void *arg) | ||||
| 	  continue; | ||||
| 	} | ||||
| 
 | ||||
|       cache_daap_reply_add(query, evbuf); | ||||
|       gzbuf = httpd_gzip_deflate(evbuf); | ||||
|       if (!gzbuf) | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_CACHE, "Error gzipping DAAP reply for query: %s\n", query); | ||||
| 	  cache_daap_query_delete(sqlite3_column_int(stmt, 0)); | ||||
| 	  free(query); | ||||
| 	  evbuffer_free(evbuf); | ||||
| 
 | ||||
| 	  continue; | ||||
| 	} | ||||
| 
 | ||||
|       evbuffer_free(evbuf); | ||||
| 
 | ||||
|       cache_daap_reply_add(query, gzbuf); | ||||
| 
 | ||||
|       free(query); | ||||
|       evbuffer_free(evbuf); | ||||
|       evbuffer_free(gzbuf); | ||||
|     } | ||||
| 
 | ||||
|   if (ret != SQLITE_DONE) | ||||
|  | ||||
| @ -56,7 +56,7 @@ static cfg_opt_t sec_general[] = | ||||
|     CFG_STR("cache_path", STATEDIR "/cache/" PACKAGE "/cache.db", CFGF_NONE), | ||||
|     CFG_INT("cache_daap_threshold", 1000, CFGF_NONE), | ||||
|     CFG_BOOL("speaker_autoselect", cfg_true, CFGF_NONE), | ||||
|     CFG_STR("allow_origin", NULL, CFGF_NONE), | ||||
|     CFG_STR("allow_origin", "*", CFGF_NONE), | ||||
|     CFG_END() | ||||
|   }; | ||||
| 
 | ||||
|  | ||||
| @ -25,6 +25,7 @@ | ||||
| 
 | ||||
| #include "db.h" | ||||
| #include "misc.h" | ||||
| #include "httpd.h" | ||||
| #include "logger.h" | ||||
| #include "dmap_common.h" | ||||
| 
 | ||||
| @ -355,7 +356,7 @@ dmap_send_error(struct evhttp_request *req, const char *container, const char *e | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DMAP, "Could not allocate evbuffer for DMAP error\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -366,7 +367,7 @@ dmap_send_error(struct evhttp_request *req, const char *container, const char *e | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DMAP, "Could not expand evbuffer for DMAP error\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
| 
 | ||||
|       evbuffer_free(evbuf); | ||||
|       return; | ||||
| @ -376,7 +377,7 @@ dmap_send_error(struct evhttp_request *req, const char *container, const char *e | ||||
|   dmap_add_int(evbuf, "mstt", 500); | ||||
|   dmap_add_string(evbuf, "msts", errmsg); | ||||
| 
 | ||||
|   evhttp_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| 
 | ||||
|   evbuffer_free(evbuf); | ||||
| } | ||||
|  | ||||
							
								
								
									
										297
									
								
								src/httpd.c
									
									
									
									
									
								
							
							
						
						
									
										297
									
								
								src/httpd.c
									
									
									
									
									
								
							| @ -86,6 +86,11 @@ | ||||
| 
 | ||||
| #define STREAM_CHUNK_SIZE (64 * 1024) | ||||
| #define WEBFACE_ROOT   DATADIR "/webface/" | ||||
| #define ERR_PAGE "<html>\n<head>\n" \ | ||||
|   "<title>%d %s</title>\n" \ | ||||
|   "</head>\n<body>\n" \ | ||||
|   "<h1>%s</h1>\n" \ | ||||
|   "</body>\n</html>\n" | ||||
| 
 | ||||
| struct content_type_map { | ||||
|   char *ext; | ||||
| @ -134,6 +139,8 @@ static struct event *exitev; | ||||
| static struct evhttp *evhttpd; | ||||
| static pthread_t tid_httpd; | ||||
| 
 | ||||
| static char *allow_origin; | ||||
| 
 | ||||
| #ifdef HAVE_LIBEVENT2_OLD | ||||
| struct stream_ctx *g_st; | ||||
| #endif | ||||
| @ -693,135 +700,141 @@ httpd_stream_file(struct evhttp_request *req, int id) | ||||
|   free_mfi(mfi, 0); | ||||
| } | ||||
| 
 | ||||
| /* Thread: httpd */ | ||||
| void | ||||
| httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf) | ||||
| struct evbuffer * | ||||
| httpd_gzip_deflate(struct evbuffer *in) | ||||
| { | ||||
|   unsigned char outbuf[128 * 1024]; | ||||
|   struct evbuffer *out; | ||||
|   struct evbuffer_iovec iovec[1]; | ||||
|   z_stream strm; | ||||
|   struct evbuffer *gzbuf; | ||||
|   struct evkeyvalq *headers; | ||||
|   const char *param; | ||||
|   int flush; | ||||
|   int zret; | ||||
|   int ret; | ||||
|   char *origin; | ||||
| 
 | ||||
|   if (!req) | ||||
|     return; | ||||
| 
 | ||||
|   if (!evbuf || (evbuffer_get_length(evbuf) == 0)) | ||||
|     { | ||||
|       DPRINTF(E_DBG, L_HTTPD, "Not gzipping body-less reply\n"); | ||||
| 
 | ||||
|       goto no_gzip; | ||||
|     } | ||||
| 
 | ||||
|   headers = evhttp_request_get_input_headers(req); | ||||
| 
 | ||||
|   param = evhttp_find_header(headers, "Accept-Encoding"); | ||||
|   if (!param) | ||||
|     { | ||||
|       DPRINTF(E_DBG, L_HTTPD, "Not gzipping; no Accept-Encoding header\n"); | ||||
| 
 | ||||
|       goto no_gzip; | ||||
|     } | ||||
|   else if (!strstr(param, "gzip") && !strstr(param, "*")) | ||||
|     { | ||||
|       DPRINTF(E_DBG, L_HTTPD, "Not gzipping; gzip not in Accept-Encoding (%s)\n", param); | ||||
| 
 | ||||
|       goto no_gzip; | ||||
|     } | ||||
| 
 | ||||
|   gzbuf = evbuffer_new(); | ||||
|   if (!gzbuf) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n"); | ||||
| 
 | ||||
|       goto no_gzip; | ||||
|     } | ||||
| 
 | ||||
|   strm.zalloc = Z_NULL; | ||||
|   strm.zfree = Z_NULL; | ||||
|   strm.opaque = Z_NULL; | ||||
| 
 | ||||
|   /* Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default) */ | ||||
|   zret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); | ||||
|   if (zret != Z_OK) | ||||
|   // Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default)
 | ||||
|   ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); | ||||
|   if (ret != Z_OK) | ||||
|     { | ||||
|       DPRINTF(E_DBG, L_HTTPD, "zlib setup failed: %s\n", zError(zret)); | ||||
| 
 | ||||
|       goto out_fail_init; | ||||
|       DPRINTF(E_LOG, L_HTTPD, "zlib setup failed: %s\n", zError(ret)); | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|   strm.next_in = evbuffer_pullup(evbuf, -1); | ||||
|   strm.avail_in = evbuffer_get_length(evbuf); | ||||
|   strm.next_in = evbuffer_pullup(in, -1); | ||||
|   strm.avail_in = evbuffer_get_length(in); | ||||
| 
 | ||||
|   flush = Z_NO_FLUSH; | ||||
| 
 | ||||
|   /* 2 iterations: Z_NO_FLUSH until input is consumed, then Z_FINISH */ | ||||
|   for (;;) | ||||
|   out = evbuffer_new(); | ||||
|   if (!out) | ||||
|     { | ||||
|       do | ||||
| 	{ | ||||
| 	  strm.next_out = outbuf; | ||||
| 	  strm.avail_out = sizeof(outbuf); | ||||
| 
 | ||||
| 	  zret = deflate(&strm, flush); | ||||
| 	  if (zret == Z_STREAM_ERROR) | ||||
| 	    { | ||||
| 	      DPRINTF(E_LOG, L_HTTPD, "Could not deflate data: %s\n", strm.msg); | ||||
| 
 | ||||
| 	      goto out_fail_gz; | ||||
| 	    } | ||||
| 
 | ||||
| 	  ret = evbuffer_add(gzbuf, outbuf, sizeof(outbuf) - strm.avail_out); | ||||
| 	  if (ret < 0) | ||||
| 	    { | ||||
| 	      DPRINTF(E_LOG, L_HTTPD, "Out of memory adding gzipped data to evbuffer\n"); | ||||
| 
 | ||||
| 	      goto out_fail_gz; | ||||
| 	    } | ||||
| 	} | ||||
|       while (strm.avail_out == 0); | ||||
| 
 | ||||
|       if (flush == Z_FINISH) | ||||
| 	break; | ||||
| 
 | ||||
|       flush = Z_FINISH; | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n"); | ||||
|       goto out_deflate_end; | ||||
|     } | ||||
| 
 | ||||
|   if (zret != Z_STREAM_END) | ||||
|   // We use this to avoid a memcpy. The 512 is an arbitrary padding to make sure
 | ||||
|   // there is enough space, even if the compressed output should be slightly
 | ||||
|   // larger than input (could happen with small inputs).
 | ||||
|   ret = evbuffer_reserve_space(out, strm.avail_in + 512, iovec, 1); | ||||
|   if (ret < 0) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Compressed data not finalized!\n"); | ||||
| 
 | ||||
|       goto out_fail_gz; | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Could not reserve memory for gzipped reply\n"); | ||||
|       goto out_evbuf_free; | ||||
|     } | ||||
| 
 | ||||
|   strm.next_out = iovec[0].iov_base; | ||||
|   strm.avail_out = iovec[0].iov_len; | ||||
| 
 | ||||
|   ret = deflate(&strm, Z_FINISH); | ||||
|   if (ret != Z_STREAM_END) | ||||
|     goto out_evbuf_free; | ||||
| 
 | ||||
|   iovec[0].iov_len -= strm.avail_out; | ||||
| 
 | ||||
|   evbuffer_commit_space(out, iovec, 1); | ||||
|   deflateEnd(&strm); | ||||
| 
 | ||||
|   headers = evhttp_request_get_output_headers(req); | ||||
|   return out; | ||||
| 
 | ||||
|   origin = cfg_getstr(cfg_getsec(cfg, "general"), "allow_origin"); | ||||
|   if (origin && strlen(origin)) | ||||
|       evhttp_add_header(headers, "Access-Control-Allow-Origin", origin); | ||||
|  out_evbuf_free: | ||||
|   evbuffer_free(out); | ||||
| 
 | ||||
|   evhttp_add_header(headers, "Content-Encoding", "gzip"); | ||||
|   evhttp_send_reply(req, code, reason, gzbuf); | ||||
| 
 | ||||
|   evbuffer_free(gzbuf); | ||||
| 
 | ||||
|   /* Drain original buffer, as would be after evhttp_send_reply() */ | ||||
|   evbuffer_drain(evbuf, evbuffer_get_length(evbuf)); | ||||
| 
 | ||||
|   return; | ||||
| 
 | ||||
|  out_fail_gz: | ||||
|  out_deflate_end: | ||||
|   deflateEnd(&strm); | ||||
|  out_fail_init: | ||||
|   evbuffer_free(gzbuf); | ||||
|  no_gzip: | ||||
|   evhttp_send_reply(req, code, reason, evbuf); | ||||
| 
 | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags) | ||||
| { | ||||
|   struct evbuffer *gzbuf; | ||||
|   struct evkeyvalq *input_headers; | ||||
|   struct evkeyvalq *output_headers; | ||||
|   const char *param; | ||||
|   int do_gzip; | ||||
| 
 | ||||
|   if (!req) | ||||
|     return; | ||||
| 
 | ||||
|   input_headers = evhttp_request_get_input_headers(req); | ||||
|   output_headers = evhttp_request_get_output_headers(req); | ||||
| 
 | ||||
|   do_gzip = ( (!(flags & HTTPD_SEND_NO_GZIP)) && | ||||
|               evbuf && (evbuffer_get_length(evbuf) > 512) && | ||||
|               (param = evhttp_find_header(input_headers, "Accept-Encoding")) && | ||||
|               (strstr(param, "gzip") || strstr(param, "*")) | ||||
|             ); | ||||
| 
 | ||||
|   if (allow_origin) | ||||
|     evhttp_add_header(output_headers, "Access-Control-Allow-Origin", allow_origin); | ||||
| 
 | ||||
|   if (do_gzip && (gzbuf = httpd_gzip_deflate(evbuf))) | ||||
|     { | ||||
|       DPRINTF(E_DBG, L_HTTPD, "Gzipping response\n"); | ||||
| 
 | ||||
|       evhttp_add_header(output_headers, "Content-Encoding", "gzip"); | ||||
|       evhttp_send_reply(req, code, reason, gzbuf); | ||||
|       evbuffer_free(gzbuf); | ||||
| 
 | ||||
|       // Drain original buffer, as would be after evhttp_send_reply()
 | ||||
|       evbuffer_drain(evbuf, evbuffer_get_length(evbuf)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       evhttp_send_reply(req, code, reason, evbuf); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // This is a modified version of evhttp_send_error (credit libevent)
 | ||||
| void | ||||
| httpd_send_error(struct evhttp_request* req, int error, const char* reason) | ||||
| { | ||||
|   struct evkeyvalq *output_headers; | ||||
|   struct evbuffer *evbuf; | ||||
| 
 | ||||
|   if (!allow_origin) | ||||
|     { | ||||
|       evhttp_send_error(req, error, reason); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   output_headers = evhttp_request_get_output_headers(req); | ||||
| 
 | ||||
|   evhttp_clear_headers(output_headers); | ||||
| 
 | ||||
|   evhttp_add_header(output_headers, "Access-Control-Allow-Origin", allow_origin); | ||||
|   evhttp_add_header(output_headers, "Content-Type", "text/html"); | ||||
|   evhttp_add_header(output_headers, "Connection", "close"); | ||||
| 
 | ||||
|   evbuf = evbuffer_new(); | ||||
|   if (!evbuf) | ||||
|     DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for error page\n"); | ||||
|   else | ||||
|     evbuffer_add_printf(evbuf, ERR_PAGE, error, reason, reason); | ||||
| 
 | ||||
|   evhttp_send_reply(req, error, reason, evbuf); | ||||
| 
 | ||||
|   if (evbuf) | ||||
|     evbuffer_free(evbuf); | ||||
| } | ||||
| 
 | ||||
| /* Thread: httpd */ | ||||
| @ -847,14 +860,14 @@ redirect_to_index(struct evhttp_request *req, char *uri) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Redirection URL exceeds buffer length\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
|       httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   headers = evhttp_request_get_output_headers(req); | ||||
| 
 | ||||
|   evhttp_add_header(headers, "Location", buf); | ||||
|   evhttp_send_reply(req, HTTP_MOVETEMP, "Moved", NULL); | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_MOVETEMP, "Moved", NULL, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| /* Thread: httpd */ | ||||
| @ -894,7 +907,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_HTTPD, "Remote web interface request denied; no password set\n"); | ||||
| 
 | ||||
| 	  evhttp_send_error(req, 403, "Forbidden"); | ||||
| 	  httpd_send_error(req, 403, "Forbidden"); | ||||
| 	  return; | ||||
| 	} | ||||
|     } | ||||
| @ -904,7 +917,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Request exceeds PATH_MAX: %s\n", uri); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
|       httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| 
 | ||||
|       return; | ||||
|     } | ||||
| @ -914,7 +927,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Could not lstat() %s: %s\n", path, strerror(errno)); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
|       httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| 
 | ||||
|       return; | ||||
|     } | ||||
| @ -932,7 +945,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_HTTPD, "Could not dereference %s: %s\n", path, strerror(errno)); | ||||
| 
 | ||||
| 	  evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| 	  httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| 
 | ||||
| 	  return; | ||||
| 	} | ||||
| @ -941,7 +954,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_HTTPD, "Dereferenced path exceeds PATH_MAX: %s\n", path); | ||||
| 
 | ||||
| 	  evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| 	  httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| 
 | ||||
| 	  free(deref); | ||||
| 	  return; | ||||
| @ -955,7 +968,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", path, strerror(errno)); | ||||
| 
 | ||||
| 	  evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| 	  httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| 
 | ||||
| 	  return; | ||||
| 	} | ||||
| @ -970,7 +983,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
| 
 | ||||
|   if (path_is_legal(path) != 0) | ||||
|     { | ||||
|       evhttp_send_error(req, 403, "Forbidden"); | ||||
|       httpd_send_error(req, 403, "Forbidden"); | ||||
| 
 | ||||
|       return; | ||||
|     } | ||||
| @ -980,7 +993,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Could not create evbuffer\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal error"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -989,7 +1002,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", path, strerror(errno)); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
|       httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -1002,7 +1015,7 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_HTTPD, "Could not read file into evbuffer\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal error"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -1021,9 +1034,9 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
|     } | ||||
| 
 | ||||
|   headers = evhttp_request_get_output_headers(req); | ||||
| 
 | ||||
|   evhttp_add_header(headers, "Content-Type", ctype); | ||||
|   evhttp_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| 
 | ||||
|   evbuffer_free(evbuf); | ||||
| } | ||||
| @ -1032,10 +1045,32 @@ serve_file(struct evhttp_request *req, char *uri) | ||||
| static void | ||||
| httpd_gen_cb(struct evhttp_request *req, void *arg) | ||||
| { | ||||
|   struct evkeyvalq *input_headers; | ||||
|   struct evkeyvalq *output_headers; | ||||
|   const char *req_uri; | ||||
|   char *uri; | ||||
|   char *ptr; | ||||
| 
 | ||||
|   // Did we get a CORS preflight request?
 | ||||
|   input_headers = evhttp_request_get_input_headers(req); | ||||
|   if ( input_headers && allow_origin && | ||||
|        (evhttp_request_get_command(req) == EVHTTP_REQ_OPTIONS) && | ||||
|        evhttp_find_header(input_headers, "Origin") && | ||||
|        evhttp_find_header(input_headers, "Access-Control-Request-Method") ) | ||||
|     { | ||||
|       output_headers = evhttp_request_get_output_headers(req); | ||||
| 
 | ||||
|       evhttp_add_header(output_headers, "Access-Control-Allow-Origin", allow_origin); | ||||
| 
 | ||||
|       // Allow only GET method and authorization header in cross origin requests
 | ||||
|       evhttp_add_header(output_headers, "Access-Control-Allow-Method", "GET"); | ||||
|       evhttp_add_header(output_headers, "Access-Control-Allow-Headers", "authorization"); | ||||
| 
 | ||||
|       // In this case there is no reason to go through httpd_send_reply
 | ||||
|       evhttp_send_reply(req, HTTP_OK, "OK", NULL); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   req_uri = evhttp_request_get_uri(req); | ||||
|   if (!req_uri) | ||||
|     { | ||||
| @ -1286,28 +1321,30 @@ httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *rea | ||||
|   header = (char *)malloc(len); | ||||
|   if (!header) | ||||
|     { | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       return -1; | ||||
|     } | ||||
| 
 | ||||
|   ret = snprintf(header, len, "Basic realm=\"%s\"", realm); | ||||
|   if ((ret < 0) || (ret >= len)) | ||||
|     { | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       return -1; | ||||
|     } | ||||
| 
 | ||||
|   evbuf = evbuffer_new(); | ||||
|   if (!evbuf) | ||||
|     { | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       return -1; | ||||
|     } | ||||
| 
 | ||||
|   headers = evhttp_request_get_output_headers(req); | ||||
|   evhttp_add_header(headers, "WWW-Authenticate", header); | ||||
| 
 | ||||
|   evbuffer_add(evbuf, http_reply_401, strlen(http_reply_401)); | ||||
|   evhttp_send_reply(req, 401, "Unauthorized", evbuf); | ||||
| 
 | ||||
|   httpd_send_reply(req, 401, "Unauthorized", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| 
 | ||||
|   free(header); | ||||
|   evbuffer_free(evbuf); | ||||
| @ -1403,6 +1440,16 @@ httpd_init(void) | ||||
|   v6enabled = cfg_getbool(cfg_getsec(cfg, "general"), "ipv6"); | ||||
|   port = cfg_getint(cfg_getsec(cfg, "library"), "port"); | ||||
| 
 | ||||
|   // For CORS headers
 | ||||
|   allow_origin = cfg_getstr(cfg_getsec(cfg, "general"), "allow_origin"); | ||||
|   if (allow_origin) | ||||
|     { | ||||
|       if (strlen(allow_origin) != 0) | ||||
| 	evhttp_set_allowed_methods(evhttpd, EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_HEAD | EVHTTP_REQ_OPTIONS); | ||||
|       else | ||||
| 	allow_origin = NULL; | ||||
|     } | ||||
| 
 | ||||
|   if (v6enabled) | ||||
|     { | ||||
|       ret = evhttp_bind_socket(evhttpd, "::", port); | ||||
|  | ||||
							
								
								
									
										43
									
								
								src/httpd.h
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								src/httpd.h
									
									
									
									
									
								
							| @ -5,11 +5,52 @@ | ||||
| #include <event2/http.h> | ||||
| #include <event2/buffer.h> | ||||
| 
 | ||||
| enum httpd_send_flags | ||||
| { | ||||
|   HTTPD_SEND_NO_GZIP =   (1 << 0), | ||||
| }; | ||||
| 
 | ||||
| void | ||||
| httpd_stream_file(struct evhttp_request *req, int id); | ||||
| 
 | ||||
| /*
 | ||||
|  * Gzips an evbuffer | ||||
|  * | ||||
|  * @in  in       Data to be compressed | ||||
|  * @return       Compressed data - must be freed by caller | ||||
|  */ | ||||
| struct evbuffer * | ||||
| httpd_gzip_deflate(struct evbuffer *in); | ||||
| 
 | ||||
| /*
 | ||||
|  * This wrapper around evhttp_send_reply should be used whenever a request may | ||||
|  * come from a browser. It will automatically gzip if feasible, but the caller | ||||
|  * may direct it not to. It will set CORS headers as appropriate. Should be | ||||
|  * thread safe. | ||||
|  * | ||||
|  * @in  req      The evhttp request struct | ||||
|  * @in  code     HTTP code, e.g. 200 | ||||
|  * @in  reason   A brief explanation of the error - if NULL the standard meaning | ||||
|                  of the error code will be used | ||||
|  * @in  evbuf    Data for the response body | ||||
|  * @in  flags    See flags above | ||||
|  */ | ||||
| void | ||||
| httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf); | ||||
| httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags); | ||||
| 
 | ||||
| /*
 | ||||
|  * This is a substitute for evhttp_send_error that should be used whenever an | ||||
|  * error may be returned to a browser. It will set CORS headers as appropriate, | ||||
|  * which is not possible with evhttp_send_error, because it clears the headers. | ||||
|  * Should be thread safe. | ||||
|  * | ||||
|  * @in  req      The evhttp request struct | ||||
|  * @in  error    HTTP code, e.g. 200 | ||||
|  * @in  reason   A brief explanation of the error - if NULL the standard meaning | ||||
|                  of the error code will be used | ||||
|  */ | ||||
| void | ||||
| httpd_send_error(struct evhttp_request *req, int error, const char *reason); | ||||
| 
 | ||||
| char * | ||||
| httpd_fixup_uri(struct evhttp_request *req); | ||||
|  | ||||
| @ -282,7 +282,7 @@ daap_session_find(struct evhttp_request *req, struct evkeyvalq *query, struct ev | ||||
|   return s; | ||||
| 
 | ||||
|  invalid: | ||||
|   evhttp_send_error(req, 403, "Forbidden"); | ||||
|   httpd_send_error(req, 403, "Forbidden"); | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| @ -355,7 +355,7 @@ update_refresh_cb(int fd, short event, void *arg) | ||||
|   evcon = evhttp_request_get_connection(ur->req); | ||||
|   evhttp_connection_set_closecb(evcon, NULL, NULL); | ||||
| 
 | ||||
|   httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   update_remove(ur); | ||||
| } | ||||
| @ -882,7 +882,7 @@ daap_reply_server_info(struct evhttp_request *req, struct evbuffer *evbuf, char | ||||
|   evbuffer_add_buffer(evbuf, content); | ||||
|   evbuffer_free(content); | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| @ -924,7 +924,7 @@ daap_reply_content_codes(struct evhttp_request *req, struct evbuffer *evbuf, cha | ||||
|       dmap_add_short(evbuf, "mcty", dmap_fields[i].type);  /* 10 */ | ||||
|     } | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| @ -954,7 +954,7 @@ daap_reply_login(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_DAAP, "Login attempt with U-A: Remote and no pairing-guid\n"); | ||||
| 
 | ||||
| 	  evhttp_send_error(req, 403, "Forbidden"); | ||||
| 	  httpd_send_error(req, 403, "Forbidden"); | ||||
| 	  return -1; | ||||
| 	} | ||||
| 
 | ||||
| @ -967,7 +967,7 @@ daap_reply_login(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, | ||||
| 	  DPRINTF(E_LOG, L_DAAP, "Login attempt with invalid pairing-guid\n"); | ||||
| 
 | ||||
| 	  free_pi(&pi, 1); | ||||
| 	  evhttp_send_error(req, 403, "Forbidden"); | ||||
| 	  httpd_send_error(req, 403, "Forbidden"); | ||||
| 	  return -1; | ||||
| 	} | ||||
| 
 | ||||
| @ -999,7 +999,7 @@ daap_reply_login(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, | ||||
|   dmap_add_int(evbuf, "mstt", 200);        /* 12 */ | ||||
|   dmap_add_int(evbuf, "mlid", s->id); /* 12 */ | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| @ -1015,7 +1015,7 @@ daap_reply_logout(struct evhttp_request *req, struct evbuffer *evbuf, char **uri | ||||
| 
 | ||||
|   daap_session_remove(s); | ||||
| 
 | ||||
|   httpd_send_reply(req, 204, "Logout Successful", evbuf); | ||||
|   httpd_send_reply(req, 204, "Logout Successful", evbuf, 0); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| @ -1068,7 +1068,7 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri | ||||
|       dmap_add_int(evbuf, "mstt", 200);         /* 12 */ | ||||
|       dmap_add_int(evbuf, "musr", current_rev); /* 12 */ | ||||
| 
 | ||||
|       httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|       httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|       return 0; | ||||
|     } | ||||
| @ -1122,7 +1122,7 @@ static int | ||||
| daap_reply_activity(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query, const char *ua) | ||||
| { | ||||
|   /* That's so nice, thanks for letting us know */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| @ -1222,7 +1222,7 @@ daap_reply_dblist(struct evhttp_request *req, struct evbuffer *evbuf, char **uri | ||||
|   evbuffer_add_buffer(evbuf, content); | ||||
|   evbuffer_free(content); | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| @ -1510,7 +1510,7 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   return 0; | ||||
| 
 | ||||
| @ -1821,7 +1821,7 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** | ||||
|       return -1; | ||||
|     } | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   return 0; | ||||
| 
 | ||||
| @ -2132,7 +2132,7 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   return 0; | ||||
| 
 | ||||
| @ -2338,7 +2338,7 @@ daap_reply_browse(struct evhttp_request *req, struct evbuffer *evbuf, char **uri | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   ret = 0; | ||||
| 
 | ||||
| @ -2378,7 +2378,7 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char * | ||||
|   ret = safe_atoi32(uri[3], &id); | ||||
|   if (ret < 0) | ||||
|     { | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return -1; | ||||
|     } | ||||
| 
 | ||||
| @ -2390,7 +2390,7 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char * | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_DAAP, "Could not convert mw parameter to integer\n"); | ||||
| 
 | ||||
| 	  evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 	  httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 	  return -1; | ||||
| 	} | ||||
| 
 | ||||
| @ -2400,7 +2400,7 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char * | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_DAAP, "Could not convert mh parameter to integer\n"); | ||||
| 
 | ||||
| 	  evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 	  httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 	  return -1; | ||||
| 	} | ||||
|     } | ||||
| @ -2442,12 +2442,11 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char * | ||||
|   snprintf(clen, sizeof(clen), "%ld", (long)len); | ||||
|   evhttp_add_header(headers, "Content-Length", clen); | ||||
| 
 | ||||
|   /* No gzip compression for artwork */ | ||||
|   evhttp_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); | ||||
|   return 0; | ||||
| 
 | ||||
|  no_artwork: | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
|   return -1; | ||||
| } | ||||
| 
 | ||||
| @ -2459,7 +2458,7 @@ daap_stream(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, stru | ||||
| 
 | ||||
|   ret = safe_atoi32(uri[3], &id); | ||||
|   if (ret < 0) | ||||
|     evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|     httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|   else | ||||
|     httpd_stream_file(req, id); | ||||
| 
 | ||||
| @ -2602,7 +2601,7 @@ daap_reply_dmap_test(struct evhttp_request *req, struct evbuffer *evbuf, char ** | ||||
|       return -1;       | ||||
|     } | ||||
| 
 | ||||
|   evhttp_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| @ -2711,7 +2710,7 @@ daap_request(struct evhttp_request *req) | ||||
|   full_uri = httpd_fixup_uri(req); | ||||
|   if (!full_uri) | ||||
|     { | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2719,7 +2718,7 @@ daap_request(struct evhttp_request *req) | ||||
|   if (!ptr) | ||||
|     { | ||||
|       free(full_uri); | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2730,7 +2729,7 @@ daap_request(struct evhttp_request *req) | ||||
| 
 | ||||
|       if (!uri) | ||||
| 	{ | ||||
| 	  evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 	  httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 	  return; | ||||
| 	} | ||||
| 
 | ||||
| @ -2741,7 +2740,7 @@ daap_request(struct evhttp_request *req) | ||||
|   if (!uri) | ||||
|     { | ||||
|       free(full_uri); | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2762,7 +2761,7 @@ daap_request(struct evhttp_request *req) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DAAP, "Unrecognized DAAP request\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 
 | ||||
|       free(uri); | ||||
|       free(full_uri); | ||||
| @ -2820,7 +2819,7 @@ daap_request(struct evhttp_request *req) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DAAP, "DAAP URI has too many/few components (%d)\n", (uri_parts[0]) ? i : 0); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 
 | ||||
|       free(uri); | ||||
|       free(full_uri); | ||||
| @ -2842,7 +2841,7 @@ daap_request(struct evhttp_request *req) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DAAP, "Could not allocate evbuffer for DAAP reply\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
| 
 | ||||
|       free(uri); | ||||
|       free(full_uri); | ||||
| @ -2853,7 +2852,9 @@ daap_request(struct evhttp_request *req) | ||||
|   ret = cache_daap_get(full_uri, evbuf); | ||||
|   if (ret == 0) | ||||
|     { | ||||
|       httpd_send_reply(req, HTTP_OK, "OK", evbuf); // TODO not all want this reply
 | ||||
|       // The cache will return the data gzipped, so httpd_send_reply won't need to do it
 | ||||
|       evhttp_add_header(headers, "Content-Encoding", "gzip"); | ||||
|       httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); // TODO not all want this reply
 | ||||
| 
 | ||||
|       evbuffer_free(evbuf); | ||||
|       free(uri); | ||||
|  | ||||
| @ -368,10 +368,10 @@ playstatusupdate_cb(int fd, short what, void *arg) | ||||
| 	{ | ||||
| 	  buf = evbuffer_pullup(update, -1); | ||||
| 	  evbuffer_add(evbuf, buf, len); | ||||
| 	  httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf); | ||||
| 	  httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf, 0); | ||||
| 	} | ||||
|       else | ||||
| 	httpd_send_reply(ur->req, HTTP_OK, "OK", update); | ||||
| 	httpd_send_reply(ur->req, HTTP_OK, "OK", update, 0); | ||||
| 
 | ||||
|       free(ur); | ||||
|     } | ||||
| @ -774,7 +774,7 @@ dacp_reply_ctrlint(struct evhttp_request *req, struct evbuffer *evbuf, char **ur | ||||
|   dmap_add_char(evbuf, "cmrl", 1);        /*  9, unknown */ | ||||
|   dmap_add_long(evbuf, "ceSX", (1 << 1 | 1));  /* 16, unknown dacp - lowest bit announces support for playqueue-contents/-edit */ | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| @ -1103,7 +1103,7 @@ dacp_reply_cue_play(struct evhttp_request *req, struct evbuffer *evbuf, char **u | ||||
|   dmap_add_int(evbuf, "mstt", 200);      /* 12 */ | ||||
|   dmap_add_int(evbuf, "miid", id);       /* 12 */ | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1119,7 +1119,7 @@ dacp_reply_cue_clear(struct evhttp_request *req, struct evbuffer *evbuf, char ** | ||||
|   dmap_add_int(evbuf, "mstt", 200);      /* 12 */ | ||||
|   dmap_add_int(evbuf, "miid", 0);        /* 12 */ | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1282,11 +1282,11 @@ dacp_reply_playspec(struct evhttp_request *req, struct evbuffer *evbuf, char **u | ||||
|     } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
|   return; | ||||
| 
 | ||||
|  out_fail: | ||||
|   evhttp_send_error(req, 500, "Internal Server Error"); | ||||
|   httpd_send_error(req, 500, "Internal Server Error"); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1301,7 +1301,7 @@ dacp_reply_pause(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, | ||||
|   player_playback_pause(); | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1328,13 +1328,13 @@ dacp_reply_playpause(struct evhttp_request *req, struct evbuffer *evbuf, char ** | ||||
| 	{ | ||||
| 	  DPRINTF(E_LOG, L_DACP, "Player returned an error for start after pause\n"); | ||||
| 
 | ||||
| 	  evhttp_send_error(req, 500, "Internal Server Error"); | ||||
| 	  httpd_send_error(req, 500, "Internal Server Error"); | ||||
| 	  return; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1352,7 +1352,7 @@ dacp_reply_nextitem(struct evhttp_request *req, struct evbuffer *evbuf, char **u | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Player returned an error for nextitem\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, 500, "Internal Server Error"); | ||||
|       httpd_send_error(req, 500, "Internal Server Error"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -1361,12 +1361,12 @@ dacp_reply_nextitem(struct evhttp_request *req, struct evbuffer *evbuf, char **u | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Player returned an error for start after nextitem\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, 500, "Internal Server Error"); | ||||
|       httpd_send_error(req, 500, "Internal Server Error"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1384,7 +1384,7 @@ dacp_reply_previtem(struct evhttp_request *req, struct evbuffer *evbuf, char **u | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Player returned an error for previtem\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, 500, "Internal Server Error"); | ||||
|       httpd_send_error(req, 500, "Internal Server Error"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -1393,12 +1393,12 @@ dacp_reply_previtem(struct evhttp_request *req, struct evbuffer *evbuf, char **u | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Player returned an error for start after previtem\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, 500, "Internal Server Error"); | ||||
|       httpd_send_error(req, 500, "Internal Server Error"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1413,7 +1413,7 @@ dacp_reply_beginff(struct evhttp_request *req, struct evbuffer *evbuf, char **ur | ||||
|   /* TODO */ | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1428,7 +1428,7 @@ dacp_reply_beginrew(struct evhttp_request *req, struct evbuffer *evbuf, char **u | ||||
|   /* TODO */ | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1443,7 +1443,7 @@ dacp_reply_playresume(struct evhttp_request *req, struct evbuffer *evbuf, char * | ||||
|   /* TODO */ | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| @ -1673,7 +1673,7 @@ dacp_reply_playqueuecontents(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
|   dmap_add_char(evbuf, "apsm", status.shuffle); /*  9, daap.playlistshufflemode - not part of mlcl container */ | ||||
|   dmap_add_char(evbuf, "aprm", status.repeat);  /*  9, daap.playlistrepeatmode  - not part of mlcl container */ | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1697,7 +1697,7 @@ dacp_reply_playqueueedit_clear(struct evhttp_request *req, struct evbuffer *evbu | ||||
|   dmap_add_int(evbuf, "mstt", 200);      /* 12 */ | ||||
|   dmap_add_int(evbuf, "miid", 0);        /* 12 */ | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1826,7 +1826,7 @@ dacp_reply_playqueueedit_add(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
|     } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1871,7 +1871,7 @@ dacp_reply_playqueueedit_move(struct evhttp_request *req, struct evbuffer *evbuf | ||||
|   } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -1903,7 +1903,7 @@ dacp_reply_playqueueedit_remove(struct evhttp_request *req, struct evbuffer *evb | ||||
|   } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -2023,9 +2023,9 @@ dacp_reply_playstatusupdate(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
|     { | ||||
|       ret = make_playstatusupdate(evbuf); | ||||
|       if (ret < 0) | ||||
| 	evhttp_send_error(req, 500, "Internal Server Error"); | ||||
| 	httpd_send_error(req, 500, "Internal Server Error"); | ||||
|       else | ||||
| 	httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
| 	httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|       return; | ||||
|     } | ||||
| @ -2076,7 +2076,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Request for artwork without mw parameter\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2085,7 +2085,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Could not convert mw parameter to integer\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2094,7 +2094,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Request for artwork without mh parameter\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2103,7 +2103,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Could not convert mh parameter to integer\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2137,12 +2137,11 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf, | ||||
|   snprintf(clen, sizeof(clen), "%ld", (long)len); | ||||
|   evhttp_add_header(headers, "Content-Length", clen); | ||||
| 
 | ||||
|   /* No gzip compression for artwork */ | ||||
|   evhttp_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); | ||||
|   return; | ||||
| 
 | ||||
|  no_artwork: | ||||
|   evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
|   httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -2243,7 +2242,7 @@ dacp_reply_getproperty(struct evhttp_request *req, struct evbuffer *evbuf, char | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   return; | ||||
| 
 | ||||
| @ -2291,7 +2290,7 @@ dacp_reply_setproperty(struct evhttp_request *req, struct evbuffer *evbuf, char | ||||
|     } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -2354,7 +2353,7 @@ dacp_reply_getspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char | ||||
| 
 | ||||
|   evbuffer_free(spklist); | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -2377,7 +2376,7 @@ dacp_reply_setspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Missing speaker-id parameter in DACP setspeakers request\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2397,7 +2396,7 @@ dacp_reply_setspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Out of memory for speaker ids\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2437,15 +2436,15 @@ dacp_reply_setspeakers(struct evhttp_request *req, struct evbuffer *evbuf, char | ||||
| 
 | ||||
|       /* Password problem */ | ||||
|       if (ret == -2) | ||||
| 	evhttp_send_error(req, 902, ""); | ||||
| 	httpd_send_error(req, 902, ""); | ||||
|       else | ||||
| 	evhttp_send_error(req, 500, "Internal Server Error"); | ||||
| 	httpd_send_error(req, 500, "Internal Server Error"); | ||||
| 
 | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   /* 204 No Content is the canonical reply */ | ||||
|   evhttp_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf); | ||||
|   httpd_send_reply(req, HTTP_NOCONTENT, "No Content", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -2548,7 +2547,7 @@ dacp_request(struct evhttp_request *req) | ||||
|   full_uri = httpd_fixup_uri(req); | ||||
|   if (!full_uri) | ||||
|     { | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2560,7 +2559,7 @@ dacp_request(struct evhttp_request *req) | ||||
|   if (!uri) | ||||
|     { | ||||
|       free(full_uri); | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -2588,7 +2587,7 @@ dacp_request(struct evhttp_request *req) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Unrecognized DACP request\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 
 | ||||
|       free(uri); | ||||
|       free(full_uri); | ||||
| @ -2609,7 +2608,7 @@ dacp_request(struct evhttp_request *req) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "DACP URI has too many/few components (%d)\n", (uri_parts[0]) ? i : 0); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
| 
 | ||||
|       free(uri); | ||||
|       free(full_uri); | ||||
| @ -2621,7 +2620,7 @@ dacp_request(struct evhttp_request *req) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_DACP, "Could not allocate evbuffer for DACP reply\n"); | ||||
| 
 | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
| 
 | ||||
|       free(uri); | ||||
|       free(full_uri); | ||||
|  | ||||
| @ -251,7 +251,7 @@ rsp_send_error(struct evhttp_request *req, char *errmsg) | ||||
| 
 | ||||
|   if (!evbuf) | ||||
|     { | ||||
|       evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
|       httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); | ||||
| 
 | ||||
|       return; | ||||
|     } | ||||
| @ -259,7 +259,8 @@ rsp_send_error(struct evhttp_request *req, char *errmsg) | ||||
|   headers = evhttp_request_get_output_headers(req); | ||||
|   evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8"); | ||||
|   evhttp_add_header(headers, "Connection", "close"); | ||||
|   evhttp_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); | ||||
| 
 | ||||
|   evbuffer_free(evbuf); | ||||
| } | ||||
| @ -283,7 +284,8 @@ rsp_send_reply(struct evhttp_request *req, mxml_node_t *reply) | ||||
|   headers = evhttp_request_get_output_headers(req); | ||||
|   evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8"); | ||||
|   evhttp_add_header(headers, "Connection", "close"); | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf); | ||||
| 
 | ||||
|   httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); | ||||
| 
 | ||||
|   evbuffer_free(evbuf); | ||||
| } | ||||
| @ -745,7 +747,7 @@ rsp_stream(struct evhttp_request *req, char **uri, struct evkeyvalq *query) | ||||
| 
 | ||||
|   ret = safe_atoi32(uri[2], &id); | ||||
|   if (ret < 0) | ||||
|     evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|     httpd_send_error(req, HTTP_BADREQUEST, "Bad Request"); | ||||
|   else | ||||
|     httpd_stream_file(req, id); | ||||
| } | ||||
|  | ||||
							
								
								
									
										18
									
								
								src/mpd.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/mpd.c
									
									
									
									
									
								
							| @ -55,6 +55,7 @@ | ||||
| #include "logger.h" | ||||
| #include "db.h" | ||||
| #include "conffile.h" | ||||
| #include "httpd.h" | ||||
| #include "misc.h" | ||||
| #include "listener.h" | ||||
| #include "artwork.h" | ||||
| @ -4534,7 +4535,7 @@ artwork_cb(struct evhttp_request *req, void *arg) | ||||
|   if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_MPD, "Unsupported request type for artwork\n"); | ||||
|       evhttp_send_error(req, HTTP_BADMETHOD, "Method not allowed"); | ||||
|       httpd_send_error(req, HTTP_BADMETHOD, "Method not allowed"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -4545,7 +4546,7 @@ artwork_cb(struct evhttp_request *req, void *arg) | ||||
|   if (!decoded) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_MPD, "Bad artwork request with uri '%s'\n", uri); | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, 0); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, 0); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -4553,7 +4554,7 @@ artwork_cb(struct evhttp_request *req, void *arg) | ||||
|   if (!path) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_MPD, "Invalid path from artwork request with uri '%s'\n", uri); | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, 0); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, 0); | ||||
|       evhttp_uri_free(decoded); | ||||
|       return; | ||||
|     } | ||||
| @ -4562,7 +4563,7 @@ artwork_cb(struct evhttp_request *req, void *arg) | ||||
|   if (!decoded_path) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_MPD, "Error decoding path from artwork request with uri '%s'\n", uri); | ||||
|       evhttp_send_error(req, HTTP_BADREQUEST, 0); | ||||
|       httpd_send_error(req, HTTP_BADREQUEST, 0); | ||||
|       evhttp_uri_free(decoded); | ||||
|       return; | ||||
|     } | ||||
| @ -4577,7 +4578,7 @@ artwork_cb(struct evhttp_request *req, void *arg) | ||||
|   if (!itemid) | ||||
|     { | ||||
|       DPRINTF(E_WARN, L_MPD, "No item found for path '%s' from request uri '%s'\n", decoded_path, uri); | ||||
|       evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found"); | ||||
|       httpd_send_error(req, HTTP_NOTFOUND, "Document was not found"); | ||||
|       evhttp_uri_free(decoded); | ||||
|       free(decoded_path); | ||||
|       return; | ||||
| @ -4587,7 +4588,7 @@ artwork_cb(struct evhttp_request *req, void *arg) | ||||
|   if (!evbuffer) | ||||
|     { | ||||
|       DPRINTF(E_LOG, L_MPD, "Could not allocate an evbuffer for artwork request\n"); | ||||
|       evhttp_send_error(req, HTTP_INTERNAL, "Document was not found"); | ||||
|       httpd_send_error(req, HTTP_INTERNAL, "Document was not found"); | ||||
|       evhttp_uri_free(decoded); | ||||
|       free(decoded_path); | ||||
|       return; | ||||
| @ -4596,7 +4597,7 @@ artwork_cb(struct evhttp_request *req, void *arg) | ||||
|   format = artwork_get_item(evbuffer, itemid, 600, 600); | ||||
|   if (format < 0) | ||||
|     { | ||||
|       evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found"); | ||||
|       httpd_send_error(req, HTTP_NOTFOUND, "Document was not found"); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| @ -4610,7 +4611,8 @@ artwork_cb(struct evhttp_request *req, void *arg) | ||||
| 	    evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "image/jpeg"); | ||||
| 	    break; | ||||
| 	} | ||||
|       evhttp_send_reply(req, HTTP_OK, "OK", evbuffer); | ||||
| 
 | ||||
|       httpd_send_reply(req, HTTP_OK, "OK", evbuffer, HTTPD_SEND_NO_GZIP); | ||||
|     } | ||||
| 
 | ||||
|   evbuffer_free(evbuffer); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user