diff --git a/rhythmbox.spec b/rhythmbox.spec index 42fb867..e53e522 100644 --- a/rhythmbox.spec +++ b/rhythmbox.spec @@ -3,7 +3,7 @@ Name: rhythmbox Summary: Music Management Application Version: 0.11.4 -Release: 4%{?dist} +Release: 5%{?dist} License: GPLv2+ and GFDL+ Group: Applications/Multimedia URL: http://www.gnome.org/projects/rhythmbox/ @@ -39,7 +39,7 @@ BuildRequires: gstreamer-devel BuildRequires: gnome-doc-utils BuildRequires: python-devel BuildRequires: pygtk2-devel -BuildRequires: libsoup-devel +BuildRequires: libsoup-devel >= 2.3.0 BuildRequires: hal-devel BuildRequires: lirc-devel BuildRequires: libmtp-devel @@ -57,6 +57,8 @@ Patch0: rb-disable-power-plugin-by-default.patch Patch1: rhythmbox-0.11.3-force-python-thread-init.patch # http://bugzilla.gnome.org/show_bug.cgi?id=510323 Patch2: x-content.patch +# http://bugzilla.gnome.org/show_bug.cgi?id=509701 +Patch3: soup24.patch %description Rhythmbox is an integrated music management application based on the powerful @@ -88,6 +90,7 @@ UPnP/DLNA network devices. %patch0 -p0 -b .dont-disable-suspend %patch1 -p1 -b .python-threading %patch2 -p1 -b .x-content +%patch3 -p0 -b .soup24 %build @@ -202,6 +205,9 @@ fi %{_libdir}/rhythmbox/plugins/upnp_coherence %changelog +* Tue Jan 29 2008 Matthias Clasen - 0.11.4-5 +- Port to libsoup 2.4 + * Fri Jan 18 2008 Matthias Clasen - 0.11.4-4 - Add content-type support diff --git a/soup24.patch b/soup24.patch new file mode 100644 index 0000000..fde0f0b --- /dev/null +++ b/soup24.patch @@ -0,0 +1,1382 @@ +Index: configure.ac +=================================================================== +--- configure.ac (revision 5543) ++++ configure.ac (working copy) +@@ -441,15 +441,9 @@ + dnl Check for libsoup, needed for DAAP and audioscrobbler + if test "x$enable_daap" = "xyes" || test "x$enable_audioscrobbler" != "xno"; then + PKG_CHECK_MODULES(SOUP, \ +- libsoup-2.2, ++ libsoup-2.4, + have_libsoup=yes, + have_libsoup=no) +- if test x"$have_libsoup" = "xno"; then +- PKG_CHECK_MODULES(SOUP, +- libsoup-2.4, +- have_libsoup=yes, +- have_libsoup=no) +- fi + if test x"$have_libsoup" = "xyes"; then + AC_DEFINE(HAVE_LIBSOUP, 1, [Define if libsoup support is enabled]) + fi +@@ -513,15 +507,10 @@ + + + +-AC_PATH_X ++AC_PATH_XTRA ++CFLAGS="$CFLAGS $X_CFLAGS" ++#LIBS=$X_LIBS + +-if test x"$x_includes" != x"NONE" && test -n "$x_includes" ; then +- CFLAGS=$CFLAGS -I`echo $x_includes | sed -e "s/:/ -I/g"` +-fi +-if test x"$x_libraries" != x"NONE" && test -n "$x_libraries" ; then +- LIBS=-L`echo $x_libraries | sed -e "s/:/ -L/g"` +-fi +- + have_xidle=no + AC_COMPILE_IFELSE([ + #include +Index: lib/rb-proxy-config.c +=================================================================== +--- lib/rb-proxy-config.c (revision 5543) ++++ lib/rb-proxy-config.c (working copy) +@@ -232,22 +232,22 @@ + } + + #if defined(HAVE_LIBSOUP) +-SoupUri * ++SoupURI * + rb_proxy_config_get_libsoup_uri (RBProxyConfig *config) + { +- SoupUri *uri = NULL; ++ SoupURI *uri = NULL; + + if (!config->enabled) + return NULL; + +- uri = g_new0 (SoupUri, 1); +- uri->protocol = SOUP_PROTOCOL_HTTP; ++ uri = soup_uri_new (NULL); ++ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP); ++ soup_uri_set_host (uri, config->host); ++ soup_uri_set_port (uri, config->port); + +- uri->host = g_strdup (config->host); +- uri->port = config->port; + if (config->auth_enabled) { +- uri->user = g_strdup (config->username); +- uri->passwd = g_strdup (config->password); ++ soup_uri_set_user (uri, config->username); ++ soup_uri_set_password (uri, config->password); + } + + return uri; +Index: lib/rb-proxy-config.h +=================================================================== +--- lib/rb-proxy-config.h (revision 5543) ++++ lib/rb-proxy-config.h (working copy) +@@ -25,7 +25,6 @@ + + #if defined(HAVE_LIBSOUP) + #include +-#include + #endif + + G_BEGIN_DECLS +@@ -66,7 +65,7 @@ + RBProxyConfig * rb_proxy_config_new (void); + + #if defined(HAVE_LIBSOUP) +-SoupUri * rb_proxy_config_get_libsoup_uri (RBProxyConfig *config); ++SoupURI * rb_proxy_config_get_libsoup_uri (RBProxyConfig *config); + #endif + + #endif /* RB_PROXY_CONFIG_H */ +Index: plugins/audioscrobbler/rb-audioscrobbler.c +=================================================================== +--- plugins/audioscrobbler/rb-audioscrobbler.c (revision 5543) ++++ plugins/audioscrobbler/rb-audioscrobbler.c (working copy) +@@ -36,7 +36,6 @@ + #include + + #include +-#include + + #include "config.h" + #include "eel-gconf-extensions.h" +@@ -196,11 +195,11 @@ + static void rb_audioscrobbler_perform (RBAudioscrobbler *audioscrobbler, + char *url, + char *post_data, +- SoupMessageCallbackFn response_handler); ++ SoupSessionCallback response_handler); + static void rb_audioscrobbler_do_handshake (RBAudioscrobbler *audioscrobbler); +-static void rb_audioscrobbler_do_handshake_cb (SoupMessage *msg, gpointer user_data); ++static void rb_audioscrobbler_do_handshake_cb (SoupSession *session, SoupMessage *msg, gpointer user_data); + static void rb_audioscrobbler_submit_queue (RBAudioscrobbler *audioscrobbler); +-static void rb_audioscrobbler_submit_queue_cb (SoupMessage *msg, gpointer user_data); ++static void rb_audioscrobbler_submit_queue_cb (SoupSession *session, SoupMessage *msg, gpointer user_data); + + static void rb_audioscrobbler_import_settings (RBAudioscrobbler *audioscrobbler); + static void rb_audioscrobbler_preferences_sync (RBAudioscrobbler *audioscrobbler); +@@ -690,17 +689,12 @@ + { + rb_debug ("Parsing response, status=%d", msg->status_code); + +- if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code) && (msg->response).body != NULL) { +- gchar *body; ++ if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code) && msg->response_body->length != 0) { + gchar **breaks; +- +- body = g_malloc0 ((msg->response).length + 1); +- memcpy (body, (msg->response).body, (msg->response).length); +- +- g_strstrip (body); +- breaks = g_strsplit (body, "\n", 4); + int i; + ++ breaks = g_strsplit (msg->response_body->data, "\n", 4); ++ + g_free (audioscrobbler->priv->status_msg); + audioscrobbler->priv->status = STATUS_OK; + audioscrobbler->priv->status_msg = NULL; +@@ -771,10 +765,9 @@ + audioscrobbler->priv->submit_next = time(NULL) + audioscrobbler->priv->submit_interval; + + g_strfreev (breaks); +- g_free (body); + } else { + audioscrobbler->priv->status = REQUEST_FAILED; +- audioscrobbler->priv->status_msg = g_strdup (soup_status_get_phrase (msg->status_code)); ++ audioscrobbler->priv->status_msg = g_strdup (msg->reason_phrase); + } + } + +@@ -793,7 +786,7 @@ + rb_audioscrobbler_perform (RBAudioscrobbler *audioscrobbler, + char *url, + char *post_data, +- SoupMessageCallbackFn response_handler) ++ SoupSessionCallback response_handler) + { + SoupMessage *msg; + +@@ -803,14 +796,14 @@ + rb_debug ("Submitting to Audioscrobbler: %s", post_data); + soup_message_set_request (msg, + "application/x-www-form-urlencoded", +- SOUP_BUFFER_SYSTEM_OWNED, ++ SOUP_MEMORY_TAKE, + post_data, + strlen (post_data)); + } + + /* create soup session, if we haven't got one yet */ + if (!audioscrobbler->priv->soup_session) { +- SoupUri *uri; ++ SoupURI *uri; + + uri = rb_proxy_config_get_libsoup_uri (audioscrobbler->priv->proxy_config); + audioscrobbler->priv->soup_session = soup_session_async_new_with_options ( +@@ -892,7 +885,7 @@ + + + static void +-rb_audioscrobbler_do_handshake_cb (SoupMessage *msg, gpointer user_data) ++rb_audioscrobbler_do_handshake_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) + { + RBAudioscrobbler *audioscrobbler = RB_AUDIOSCROBBLER(user_data); + +@@ -1050,7 +1043,7 @@ + } + + static void +-rb_audioscrobbler_submit_queue_cb (SoupMessage *msg, gpointer user_data) ++rb_audioscrobbler_submit_queue_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) + { + RBAudioscrobbler *audioscrobbler = RB_AUDIOSCROBBLER (user_data); + +@@ -1232,7 +1225,7 @@ + rb_audioscrobbler_proxy_config_changed_cb (RBProxyConfig *config, + RBAudioscrobbler *audioscrobbler) + { +- SoupUri *uri; ++ SoupURI *uri; + + if (audioscrobbler->priv->soup_session) { + uri = rb_proxy_config_get_libsoup_uri (config); +Index: plugins/audioscrobbler/rb-lastfm-source.c +=================================================================== +--- plugins/audioscrobbler/rb-lastfm-source.c (revision 5543) ++++ plugins/audioscrobbler/rb-lastfm-source.c (working copy) +@@ -43,7 +43,6 @@ + #include + + #include +-#include + + #include "md5.h" + +@@ -100,8 +99,8 @@ + static void rb_lastfm_perform (RBLastfmSource *lastfm, + const char *url, + char *post_data, /* this takes ownership */ +- SoupMessageCallbackFn response_handler); +-static void rb_lastfm_message_cb (SoupMessage *req, gpointer user_data); ++ SoupSessionCallback response_handler); ++static void rb_lastfm_message_cb (SoupSession *session, SoupMessage *req, gpointer user_data); + static void rb_lastfm_change_station (RBLastfmSource *source, const char *station); + + static void rb_lastfm_proxy_config_changed_cb (RBProxyConfig *config, +@@ -724,7 +723,7 @@ + rb_lastfm_perform (RBLastfmSource *source, + const char *url, + char *post_data, +- SoupMessageCallbackFn response_handler) ++ SoupSessionCallback response_handler) + { + SoupMessage *msg; + msg = soup_message_new ("GET", url); +@@ -732,22 +731,20 @@ + if (msg == NULL) + return; + +- soup_message_set_http_version (msg, SOUP_HTTP_1_1); +- + rb_debug ("Last.fm communicating with %s", url); + + if (post_data != NULL) { + rb_debug ("POST data: %s", post_data); + soup_message_set_request (msg, + "application/x-www-form-urlencoded", +- SOUP_BUFFER_SYSTEM_OWNED, ++ SOUP_MEMORY_TAKE, + post_data, + strlen (post_data)); + } + + /* create soup session, if we haven't got one yet */ + if (!source->priv->soup_session) { +- SoupUri *uri; ++ SoupURI *uri; + + uri = rb_proxy_config_get_libsoup_uri (source->priv->proxy_config); + source->priv->soup_session = soup_session_async_new_with_options ( +@@ -759,36 +756,31 @@ + + soup_session_queue_message (source->priv->soup_session, + msg, +- (SoupMessageCallbackFn) response_handler, ++ response_handler, + source); + source->priv->status = COMMUNICATING; + rb_source_notify_status_changed (RB_SOURCE(source)); + } + + static void +-rb_lastfm_message_cb (SoupMessage *req, gpointer user_data) ++rb_lastfm_message_cb (SoupSession *session, SoupMessage *req, gpointer user_data) + { + RBLastfmSource *source = RB_LASTFM_SOURCE (user_data); +- char *body; + char **pieces; + int i; + +- if ((req->response).body == NULL) { ++ if (req->response_body->length == 0) { + rb_debug ("Lastfm: Server failed to respond"); + return; + } + +- body = g_malloc0 ((req->response).length + 1); +- memcpy (body, (req->response).body, (req->response).length); ++ rb_debug ("response body: %s", req->response_body->data); + +- rb_debug ("response body: %s", body); +- +- if (strstr (body, "ERROR - no such artist") != NULL) { ++ if (strstr (req->response_body->data, "ERROR - no such artist") != NULL) { + source->priv->status = NO_ARTIST; + } + +- g_strstrip (body); +- pieces = g_strsplit (body, "\n", 0); ++ pieces = g_strsplit (req->response_body->data, "\n", 0); + for (i = 0; pieces[i] != NULL; i++) { + gchar **values = g_strsplit (pieces[i], "=", 2); + if (strcmp (values[0], "session") == 0) { +@@ -856,10 +848,10 @@ + rhythmdb_commit (source->priv->db); + + } ++ g_strfreev (values); + } + + g_strfreev (pieces); +- g_free (body); + + /* doesn't work yet + if (source->priv->pending_entry) { +@@ -898,7 +890,7 @@ + rb_lastfm_proxy_config_changed_cb (RBProxyConfig *config, + RBLastfmSource *source) + { +- SoupUri *uri; ++ SoupURI *uri; + + if (source->priv->soup_session) { + uri = rb_proxy_config_get_libsoup_uri (config); +@@ -1164,9 +1156,8 @@ + } + + static void +-rb_lastfm_source_metadata_cb (SoupMessage *req, RBLastfmSource *source) ++rb_lastfm_source_metadata_cb (SoupSession *session, SoupMessage *req, RBLastfmSource *source) + { +- char *body; + char **pieces; + int p; + RhythmDBEntry *entry; +@@ -1179,11 +1170,8 @@ + } + + rb_debug ("got response to metadata request"); +- body = g_malloc0 ((req->response).length + 1); +- memcpy (body, (req->response).body, (req->response).length); + +- g_strstrip (body); +- pieces = g_strsplit (body, "\n", 0); ++ pieces = g_strsplit (req->response_body->data, "\n", 0); + found_cover = FALSE; + + for (p = 0; pieces[p] != NULL; p++) { +@@ -1238,7 +1226,6 @@ + } + + g_strfreev (pieces); +- g_free (body); + + if (found_cover == FALSE) { + GValue v = {0,}; +@@ -1271,7 +1258,7 @@ + source->priv->base_url, + source->priv->base_path, + source->priv->session); +- rb_lastfm_perform (source, uri, NULL, (SoupMessageCallbackFn) rb_lastfm_source_metadata_cb); ++ rb_lastfm_perform (source, uri, NULL, (SoupSessionCallback) rb_lastfm_source_metadata_cb); + g_free (uri); + + /* re-enable actions */ +Index: plugins/audioscrobbler/rb-lastfm-gst-src.c +=================================================================== +--- plugins/audioscrobbler/rb-lastfm-gst-src.c (revision 5543) ++++ plugins/audioscrobbler/rb-lastfm-gst-src.c (working copy) +@@ -25,7 +25,6 @@ + + #include "rb-debug.h" + +-#include + #include + + #define RB_TYPE_LASTFM_SRC (rb_lastfm_src_get_type()) +Index: plugins/daap/rb-daap-plugin.c +=================================================================== +--- plugins/daap/rb-daap-plugin.c (revision 5543) ++++ plugins/daap/rb-daap-plugin.c (working copy) +@@ -30,7 +30,6 @@ + #include + + #include +-#include + + #include "rb-daap-plugin.h" + #include "rb-debug.h" +@@ -646,7 +645,7 @@ + addr = soup_address_new (host, port); + g_free (host); + +- soup_address_resolve_async (addr, ++ soup_address_resolve_async (addr, NULL, NULL, + (SoupAddressCallback) new_daap_share_resolve_cb, + data); + } +Index: plugins/daap/rb-daap-connection.c +=================================================================== +--- plugins/daap/rb-daap-connection.c (revision 5543) ++++ plugins/daap/rb-daap-connection.c (working copy) +@@ -34,9 +34,6 @@ + #include + + #include +-#include +-#include +-#include + + #include "rb-daap-hash.h" + #include "rb-daap-connection.h" +@@ -84,7 +81,7 @@ + gboolean is_connecting; + + SoupSession *session; +- SoupUri *base_uri; ++ SoupURI *base_uri; + gchar *daap_base_uri; + + gdouble daap_version; +@@ -329,7 +326,7 @@ + { + RBDAAPConnectionPrivate *priv = connection->priv; + SoupMessage *message = NULL; +- SoupUri *uri = NULL; ++ SoupURI *uri = NULL; + + uri = soup_uri_new_with_base (priv->base_uri, path); + if (uri == NULL) { +@@ -337,14 +334,13 @@ + } + + message = soup_message_new_from_uri (SOUP_METHOD_GET, uri); +- soup_message_set_http_version (message, SOUP_HTTP_1_1); + +- soup_message_add_header (message->request_headers, "Client-DAAP-Version", "3.0"); +- soup_message_add_header (message->request_headers, "Accept-Language", "en-us, en;q=5.0"); ++ soup_message_headers_append (message->request_headers, "Client-DAAP-Version", "3.0"); ++ soup_message_headers_append (message->request_headers, "Accept-Language", "en-us, en;q=5.0"); + #ifdef HAVE_LIBZ +- soup_message_add_header (message->request_headers, "Accept-Encoding", "gzip"); ++ soup_message_headers_append (message->request_headers, "Accept-Encoding", "gzip"); + #endif +- soup_message_add_header (message->request_headers, "Client-DAAP-Access-Index", "2"); ++ soup_message_headers_append (message->request_headers, "Client-DAAP-Access-Index", "2"); + + if (priv->password_protected) { + char *h; +@@ -352,13 +348,13 @@ + char *token; + + user_pass = g_strdup_printf ("%s:%s", priv->username, priv->password); +- token = soup_base64_encode (user_pass, strlen (user_pass)); ++ token = g_base64_encode ((guchar *)user_pass, strlen (user_pass)); + h = g_strdup_printf ("Basic %s", token); + + g_free (token); + g_free (user_pass); + +- soup_message_add_header (message->request_headers, "Authorization", h); ++ soup_message_headers_append (message->request_headers, "Authorization", h); + g_free (h); + } + +@@ -372,10 +368,10 @@ + + rb_daap_hash_generate ((short)floor (version), (const guchar*)no_daap_path, 2, (guchar*)hash, req_id); + +- soup_message_add_header (message->request_headers, "Client-DAAP-Validation", hash); ++ soup_message_headers_append (message->request_headers, "Client-DAAP-Validation", hash); + } + if (send_close) { +- soup_message_add_header (message->request_headers, "Connection", "close"); ++ soup_message_headers_append (message->request_headers, "Connection", "close"); + } + + soup_uri_free (uri); +@@ -425,16 +421,17 @@ + { + RBDAAPConnectionPrivate *priv; + GNode *structure; +- char *response; ++ const char *response; ++ char *new_response = NULL; + const char *encoding_header; + char *message_path; + int response_length; + + priv = data->connection->priv; + structure = NULL; +- response = data->message->response.body; ++ response = data->message->response_body->data; + encoding_header = NULL; +- response_length = data->message->response.length; ++ response_length = data->message->response_body->length; + + message_path = soup_uri_to_string (soup_message_get_uri (data->message), FALSE); + +@@ -444,13 +441,12 @@ + data->message->reason_phrase); + + if (data->message->response_headers) { +- encoding_header = soup_message_get_header (data->message->response_headers, "Content-Encoding"); ++ encoding_header = soup_message_headers_get (data->message->response_headers, "Content-Encoding"); + } + + if (SOUP_STATUS_IS_SUCCESSFUL (data->status) && encoding_header && strcmp (encoding_header, "gzip") == 0) { + #ifdef HAVE_LIBZ + z_stream stream; +- char *new_response; + unsigned int factor = 4; + unsigned int unc_size = response_length * factor; + +@@ -575,10 +571,7 @@ + rb_daap_structure_destroy (structure); + } + +- if (response != data->message->response.body) { +- g_free (response); +- } +- ++ g_free (new_response); + g_free (message_path); + g_object_unref (G_OBJECT (data->connection)); + g_object_unref (G_OBJECT (data->message)); +@@ -586,7 +579,8 @@ + } + + static void +-http_response_handler (SoupMessage *message, ++http_response_handler (SoupSession *session, ++ SoupMessage *message, + RBDAAPConnection *connection) + { + DAAPResponseData *data; +@@ -599,7 +593,7 @@ + + data = g_new0 (DAAPResponseData, 1); + data->status = message->status_code; +- response_length = message->response.length; ++ response_length = message->response_body->length; + + g_object_ref (G_OBJECT (connection)); + data->connection = connection; +@@ -655,7 +649,7 @@ + priv->use_response_handler_thread = use_thread; + priv->response_handler = handler; + soup_session_queue_message (priv->session, message, +- (SoupMessageCallbackFn) http_response_handler, ++ (SoupSessionCallback) http_response_handler, + connection); + rb_debug ("Queued message for http://%s:%d/%s", + priv->base_uri->host, +@@ -1674,7 +1668,7 @@ + char *token; + + user_pass = g_strdup_printf ("%s:%s", priv->username, priv->password); +- token = soup_base64_encode (user_pass, strlen (user_pass)); ++ token = g_base64_encode ((guchar *)user_pass, strlen (user_pass)); + g_string_append_printf (headers, "Authentication: Basic %s\r\n", token); + g_free (token); + g_free (user_pass); +Index: plugins/daap/rb-daap-share.c +=================================================================== +--- plugins/daap/rb-daap-share.c (revision 5543) ++++ plugins/daap/rb-daap-share.c (working copy) +@@ -28,12 +28,6 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include + #include + + #include "rb-daap-share.h" +@@ -513,20 +507,9 @@ + static void + message_add_standard_headers (SoupMessage *message) + { +- gchar *s; +- time_t t; +- struct tm *tm; ++ soup_message_headers_append (message->response_headers, "DAAP-Server", "Rhythmbox " VERSION); + +- soup_message_add_header (message->response_headers, "DAAP-Server", "Rhythmbox " VERSION); +- +- soup_message_add_header (message->response_headers, "Content-Type", "application/x-dmap-tagged"); +- +- t = time (NULL); +- tm = gmtime (&t); +- s = g_new (gchar, 100); +- strftime (s, 100, "%a, %d %b %Y %T GMT", tm); +- soup_message_add_header (message->response_headers, "Date", s); +- g_free (s); ++ soup_message_headers_append (message->response_headers, "Content-Type", "application/x-dmap-tagged"); + } + + static void +@@ -543,14 +526,11 @@ + return; + } + +- message->response.owner = SOUP_BUFFER_SYSTEM_OWNED; +- message->response.length = length; +- message->response.body = resp; +- ++ soup_message_set_response (message, "application/x-dmap-tagged", ++ SOUP_MEMORY_TAKE, resp, length); + message_add_standard_headers (message); + + soup_message_set_status (message, SOUP_STATUS_OK); +- soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (message), SOUP_TRANSFER_CONTENT_LENGTH); + } + + #define DMAP_STATUS_OK 200 +@@ -560,9 +540,12 @@ + #define DMAP_TIMEOUT 1800 + + static void +-server_info_cb (RBDAAPShare *share, +- SoupServerContext *context, +- SoupMessage *message) ++server_info_cb (SoupServer *server, ++ SoupMessage *message, ++ const char *path, ++ GHashTable *query, ++ SoupClientContext *context, ++ RBDAAPShare *share) + { + /* MSRV server info response + * MSTT status +@@ -620,9 +603,12 @@ + } + + static void +-content_codes_cb (RBDAAPShare *share, +- SoupServerContext *context, +- SoupMessage *message) ++content_codes_cb (SoupServer *server, ++ SoupMessage *message, ++ const char *path, ++ GHashTable *query, ++ SoupClientContext *context, ++ RBDAAPShare *share) + { + /* MCCR content codes response + * MSTT status +@@ -657,34 +643,23 @@ + } + + static gboolean +-message_get_session_id (SoupMessage *message, +- guint32 *id) ++get_session_id (GHashTable *query, ++ guint32 *id) + { +- const SoupUri *uri; +- char *position; +- guint32 session_id; ++ char *session_id_str; ++ guint32 session_id; + + if (id) { + *id = 0; + } + +- uri = soup_message_get_uri (message); +- if (uri == NULL) { +- return FALSE; +- } +- +- if (uri->query != NULL) +- position = strstr (uri->query, "session-id="); +- else +- position = NULL; +- +- if (position == NULL) { ++ session_id_str = g_hash_table_lookup (query, "session-id"); ++ if (session_id_str == NULL) { + rb_debug ("session id not found"); + return FALSE; + } + +- position += 11; +- session_id = (guint32) strtoul (position, NULL, 10); ++ session_id = (guint32) strtoul (session_id_str, NULL, 10); + + if (id) { + *id = session_id; +@@ -694,34 +669,23 @@ + } + + static gboolean +-message_get_revision_number (SoupMessage *message, +- guint *number) ++get_revision_number (GHashTable *query, ++ guint *number) + { +- const SoupUri *uri; +- char *position; +- guint revision_number; ++ char *revision_number_str; ++ guint revision_number; + + if (number) { + *number = 0; + } + +- uri = soup_message_get_uri (message); +- if (uri == NULL) { +- return FALSE; +- } +- +- if (uri->query != NULL) +- position = strstr (uri->query, "revision-number="); +- else +- position = NULL; +- +- if (position == NULL) { ++ revision_number_str = g_hash_table_lookup (query, "revision-number"); ++ if (revision_number_str == NULL) { + rb_debug ("client asked for an update without a revision number?!?\n"); + return FALSE; + } + +- position += 16; +- revision_number = atoi (position); ++ revision_number = atoi (revision_number_str); + + if (number) { + *number = revision_number; +@@ -732,8 +696,9 @@ + + static gboolean + session_id_validate (RBDAAPShare *share, +- SoupServerContext *context, ++ SoupClientContext *context, + SoupMessage *message, ++ GHashTable *query, + guint32 *id) + { + guint32 session_id; +@@ -745,7 +710,7 @@ + *id = 0; + } + +- res = message_get_session_id (message, &session_id); ++ res = get_session_id (query, &session_id); + if (! res) { + rb_debug ("Validation failed: Unable to parse session id from message"); + return FALSE; +@@ -758,7 +723,7 @@ + return FALSE; + } + +- remote_address = soup_server_context_get_client_host (context); ++ remote_address = soup_client_context_get_host (context); + rb_debug ("Validating session id %u from %s matches %s", + session_id, remote_address, addr); + if (remote_address == NULL || strcmp (addr, remote_address) != 0) { +@@ -775,7 +740,7 @@ + + static guint32 + session_id_generate (RBDAAPShare *share, +- SoupServerContext *context) ++ SoupClientContext *context) + { + guint32 id; + +@@ -786,7 +751,7 @@ + + static guint32 + session_id_create (RBDAAPShare *share, +- SoupServerContext *context) ++ SoupClientContext *context) + { + guint32 id; + const char *addr; +@@ -802,7 +767,7 @@ + } while (addr != NULL); + + /* store session id and remote address */ +- remote_address = g_strdup (soup_server_context_get_client_host (context)); ++ remote_address = g_strdup (soup_client_context_get_host (context)); + g_hash_table_insert (share->priv->session_ids, GUINT_TO_POINTER (id), remote_address); + + return id; +@@ -810,16 +775,19 @@ + + static void + session_id_remove (RBDAAPShare *share, +- SoupServerContext *context, ++ SoupClientContext *context, + guint32 id) + { + g_hash_table_remove (share->priv->session_ids, GUINT_TO_POINTER (id)); + } + + static void +-login_cb (RBDAAPShare *share, +- SoupServerContext *context, +- SoupMessage *message) ++login_cb (SoupServer *server, ++ SoupMessage *message, ++ const char *path, ++ GHashTable *query, ++ SoupClientContext *context, ++ RBDAAPShare *share) + { + /* MLOG login response + * MSTT status +@@ -841,14 +809,17 @@ + } + + static void +-logout_cb (RBDAAPShare *share, +- SoupServerContext *context, +- SoupMessage *message) ++logout_cb (SoupServer *server, ++ SoupMessage *message, ++ const char *path, ++ GHashTable *query, ++ SoupClientContext *context, ++ RBDAAPShare *share) + { + int status; + guint32 id; + +- if (session_id_validate (share, context, message, &id)) { ++ if (session_id_validate (share, context, message, query, &id)) { + rb_debug ("Handling logout session id %u", id); + session_id_remove (share, context, id); + +@@ -858,18 +829,20 @@ + } + + soup_message_set_status (message, status); +- soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (message), SOUP_TRANSFER_CONTENT_LENGTH); + } + + static void +-update_cb (RBDAAPShare *share, +- SoupServerContext *context, +- SoupMessage *message) ++update_cb (SoupServer *server, ++ SoupMessage *message, ++ const char *path, ++ GHashTable *query, ++ SoupClientContext *context, ++ RBDAAPShare *share) + { + guint revision_number; + gboolean res; + +- res = message_get_revision_number (message, &revision_number); ++ res = get_revision_number (query, &revision_number); + + if (res && revision_number != share->priv->revision_number) { + /* MUPD update response +@@ -885,8 +858,11 @@ + message_set_from_rb_daap_structure (message, mupd); + rb_daap_structure_destroy (mupd); + } else { ++ /* FIXME: This seems like a bug. It just leaks the ++ * message (and socket) without ever replying. ++ */ + g_object_ref (message); +- soup_message_io_pause (message); ++ soup_server_pause_message (server, message); + } + } + +@@ -1148,28 +1124,14 @@ + } + + static bitwise +-parse_meta (const gchar *s) ++parse_meta (GHashTable *query) + { +- gchar *start_of_attrs; +- gchar *end_of_attrs; +- gchar *attrs; ++ const gchar *attrs; + gchar **attrsv; + guint i; + bitwise bits = 0; + +- start_of_attrs = strstr (s, "meta="); +- if (start_of_attrs == NULL) { +- return 0; +- } +- start_of_attrs += 5; +- +- end_of_attrs = strchr (start_of_attrs, '&'); +- if (end_of_attrs) { +- attrs = g_strndup (start_of_attrs, end_of_attrs - start_of_attrs); +- } else { +- attrs = g_strdup (start_of_attrs); +- } +- ++ attrs = g_hash_table_lookup (query, "meta"); + attrsv = g_strsplit (attrs,",",-1); + + for (i = 0; attrsv[i]; i++) { +@@ -1182,7 +1144,6 @@ + } + } + +- g_free (attrs); + g_strfreev (attrsv); + + return bits; +@@ -1197,10 +1158,10 @@ + + result = gnome_vfs_read (handle, chunk, DAAP_SHARE_CHUNK_SIZE, &read_size); + if (result == GNOME_VFS_OK && read_size > 0) { +- soup_message_add_chunk (message, SOUP_BUFFER_SYSTEM_OWNED, chunk, read_size); ++ soup_message_body_append (message->response_body, SOUP_MEMORY_TAKE, chunk, read_size); + } else { + g_free (chunk); +- soup_message_add_final_chunk (message); ++ soup_message_body_complete (message->response_body); + } + } + +@@ -1238,7 +1199,7 @@ + file_size -= offset; + } + +- soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (message), SOUP_TRANSFER_CHUNKED); ++ soup_message_headers_set_encoding (message->response_headers, SOUP_ENCODING_CHUNKED); + + g_signal_connect (message, "wrote_chunk", G_CALLBACK (write_next_chunk), handle); + g_signal_connect (message, "finished", G_CALLBACK (chunked_message_finished), handle); +@@ -1268,11 +1229,9 @@ + g_warning ("Unable to map file %s: %s", path, error->message); + soup_message_set_status (message, SOUP_STATUS_INTERNAL_SERVER_ERROR); + } else { +- message->response.owner = SOUP_BUFFER_USER_OWNED; +- message->response.length = file_size; +- message->response.body = g_mapped_file_get_contents (mapped_file) + offset; +- soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (message), +- SOUP_TRANSFER_CONTENT_LENGTH); ++ soup_message_set_response (message, "application/x-dmap-tagged", ++ SOUP_MEMORY_TEMPORARY, ++ g_mapped_file_get_contents (mapped_file) + offset, file_size); + + g_signal_connect (message, + "finished", +@@ -1284,22 +1243,21 @@ + #endif + + static void +-databases_cb (RBDAAPShare *share, +- SoupServerContext *context, +- SoupMessage *message) ++databases_cb (SoupServer *server, ++ SoupMessage *message, ++ const char *path, ++ GHashTable *query, ++ SoupClientContext *context, ++ RBDAAPShare *share) + { +- gchar *path; +- gchar *rest_of_path; ++ const char *rest_of_path; + /*guint revision_number;*/ + +- if (! session_id_validate (share, context, message, NULL)) { ++ if (! session_id_validate (share, context, message, query, NULL)) { + soup_message_set_status (message, SOUP_STATUS_FORBIDDEN); +- soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (message), SOUP_TRANSFER_CONTENT_LENGTH); + return; + } + +- path = soup_uri_to_string (soup_message_get_uri (message), TRUE); +- + rest_of_path = strchr (path + 1, '/'); + + if (rest_of_path == NULL) { +@@ -1335,7 +1293,7 @@ + + message_set_from_rb_daap_structure (message, avdb); + rb_daap_structure_destroy (avdb); +- } else if (g_ascii_strncasecmp ("/1/items?", rest_of_path, 9) == 0) { ++ } else if (g_ascii_strcasecmp ("/1/items", rest_of_path) == 0) { + /* ADBS database songs + * MSTT status + * MUTY update type +@@ -1351,7 +1309,7 @@ + gint32 num_songs = rhythmdb_entry_count_by_type (share->priv->db, share->priv->entry_type); + struct MLCL_Bits mb = {NULL,0}; + +- mb.bits = parse_meta (rest_of_path); ++ mb.bits = parse_meta (query); + + adbs = rb_daap_structure_add (NULL, RB_DAAP_CC_ADBS); + rb_daap_structure_add (adbs, RB_DAAP_CC_MSTT, (gint32) DMAP_STATUS_OK); +@@ -1365,7 +1323,7 @@ + message_set_from_rb_daap_structure (message, adbs); + rb_daap_structure_destroy (adbs); + adbs = NULL; +- } else if (g_ascii_strncasecmp ("/1/containers?", rest_of_path, 14) == 0) { ++ } else if (g_ascii_strcasecmp ("/1/containers", rest_of_path) == 0) { + /* APLY database playlists + * MSTT status + * MUTY update type +@@ -1420,7 +1378,7 @@ + struct MLCL_Bits mb = {NULL,0}; + gint pl_id = atoi (rest_of_path + 14); + +- mb.bits = parse_meta (rest_of_path); ++ mb.bits = parse_meta (query); + + apso = rb_daap_structure_add (NULL, RB_DAAP_CC_APSO); + rb_daap_structure_add (apso, RB_DAAP_CC_MSTT, (gint32) DMAP_STATUS_OK); +@@ -1447,10 +1405,7 @@ + _find_by_id); + if (idl == NULL) { + soup_message_set_status (message, SOUP_STATUS_NOT_FOUND); +- soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (message), +- SOUP_TRANSFER_CONTENT_LENGTH); +- soup_message_set_response (message, "text/plain", SOUP_BUFFER_USER_OWNED, "", 0); +- goto out; ++ return; + } + id = (RBPlaylistID *)idl->data; + +@@ -1470,7 +1425,7 @@ + rb_daap_structure_destroy (apso); + } else if (g_ascii_strncasecmp ("/1/items/", rest_of_path, 9) == 0) { + /* just the file :) */ +- gchar *id_str; ++ const gchar *id_str; + gint id; + RhythmDBEntry *entry; + const gchar *location; +@@ -1486,9 +1441,9 @@ + file_size = rhythmdb_entry_get_uint64 (entry, RHYTHMDB_PROP_FILE_SIZE); + + message_add_standard_headers (message); +- soup_message_add_header (message->response_headers, "Accept-Ranges", "bytes"); ++ soup_message_headers_append (message->response_headers, "Accept-Ranges", "bytes"); + +- range_header = soup_message_get_header (message->request_headers, "Range"); ++ range_header = soup_message_headers_get (message->request_headers, "Range"); + if (range_header) { + const gchar *s; + gchar *content_range; +@@ -1497,7 +1452,7 @@ + offset = atoll (s); + + content_range = g_strdup_printf ("bytes %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, offset, file_size, file_size); +- soup_message_add_header (message->response_headers, "Content-Range", content_range); ++ soup_message_headers_append (message->response_headers, "Content-Range", content_range); + g_free (content_range); + + soup_message_set_status (message, SOUP_STATUS_PARTIAL_CONTENT); +@@ -1520,54 +1475,9 @@ + } else { + rb_debug ("unhandled: %s\n", path); + } +- +-out: +- g_free (path); + } + +-typedef void (* DAAPPathFunction) (RBDAAPShare *share, +- SoupServerContext *context, +- SoupMessage *message); +- +-struct DAAPPath { +- const gchar *path; +- guint path_length; +- DAAPPathFunction function; +-}; +- +-static const struct DAAPPath paths_to_functions[] = { +- {"/server-info", 12, server_info_cb}, +- {"/content-codes", 14, content_codes_cb}, +- {"/login", 6, login_cb}, +- {"/logout", 7, logout_cb}, +- {"/update", 7, update_cb}, +- {"/databases", 10, databases_cb} +-}; +- + static void +-server_cb (SoupServerContext *context, +- SoupMessage *message, +- RBDAAPShare *share) +-{ +- gchar *path; +- guint i; +- +- path = soup_uri_to_string (soup_message_get_uri (message), TRUE); +- rb_debug ("request for %s", path); +- +- for (i = 0; i < G_N_ELEMENTS (paths_to_functions); i++) { +- if (g_ascii_strncasecmp (paths_to_functions[i].path, path, paths_to_functions[i].path_length) == 0) { +- paths_to_functions[i].function (share, context, message); +- return; +- } +- } +- +- g_warning ("unhandled path %s\n", path); +- +- g_free (path); +-} +- +-static void + db_entry_added_cb (RhythmDB *db, + RhythmDBEntry *entry, + RBDAAPShare *share) +@@ -1604,41 +1514,42 @@ + } + + static gboolean +-soup_auth_callback (SoupServerAuthContext *auth_ctx, +- SoupServerAuth *auth, +- SoupMessage *message, +- RBDAAPShare *share) ++soup_auth_filter (SoupAuthDomain *auth_domain, ++ SoupMessage *msg, ++ gpointer user_data) + { +- const char *username; +- gboolean allowed; +- char *path; ++ const char *path; + +- path = soup_uri_to_string (soup_message_get_uri (message), TRUE); +- rb_debug ("Auth request for %s", path); +- +- if (auth == NULL) { +- +- /* This is to workaround libsoup looking up handlers by directory. +- We require auth for "/databases?" but not "/databases/" */ +- if (g_str_has_prefix (path, "/databases/")) { +- allowed = TRUE; +- goto done; +- } +- +- rb_debug ("Auth DENIED: information not provided"); +- allowed = FALSE; +- goto done; ++ path = soup_message_get_uri (msg)->path; ++ if (g_str_has_prefix (path, "/databases/")) { ++ /* Subdirectories of /databases don't actually require ++ * authentication ++ */ ++ return FALSE; ++ } else { ++ /* Everything else in auth_domain's paths, including ++ * /databases itself, does require auth. ++ */ ++ return TRUE; + } ++} + +- username = soup_server_auth_get_user (auth); +- rb_debug ("Auth request for user: %s", username); ++static gboolean ++soup_auth_callback (SoupAuthDomain *auth_domain, ++ SoupMessage *msg, ++ const char *username, ++ gpointer password, ++ RBDAAPShare *share) ++{ ++ gboolean allowed; ++ const char *path; + +- allowed = soup_server_auth_check_passwd (auth, share->priv->password); ++ path = soup_message_get_uri (msg)->path; ++ rb_debug ("Auth request for %s, user %s", path, username); ++ ++ allowed = !strcmp (password, share->priv->password); + rb_debug ("Auth request: %s", allowed ? "ALLOWED" : "DENIED"); + +- done: +- g_free (path); +- + return allowed; + } + +@@ -1647,7 +1558,6 @@ + { + int port = STANDARD_DAAP_PORT; + gboolean password_required; +- SoupServerAuthContext auth_ctx = { 0 }; + + share->priv->server = soup_server_new (SOUP_SERVER_PORT, port, NULL); + if (share->priv->server == NULL) { +@@ -1666,37 +1576,39 @@ + password_required = (share->priv->auth_method != RB_DAAP_SHARE_AUTH_METHOD_NONE); + + if (password_required) { +- auth_ctx.types = SOUP_AUTH_TYPE_BASIC; +- auth_ctx.callback = (SoupServerAuthCallbackFn)soup_auth_callback; +- auth_ctx.user_data = share; +- auth_ctx.basic_info.realm = "Music Sharing"; ++ SoupAuthDomain *auth_domain; + +- soup_server_add_handler (share->priv->server, +- "/login", +- &auth_ctx, +- (SoupServerCallbackFn)server_cb, +- NULL, +- share); +- soup_server_add_handler (share->priv->server, +- "/update", +- &auth_ctx, +- (SoupServerCallbackFn)server_cb, +- NULL, +- share); +- soup_server_add_handler (share->priv->server, +- "/databases", +- &auth_ctx, +- (SoupServerCallbackFn)server_cb, +- NULL, +- share); ++ auth_domain = soup_auth_domain_basic_new (SOUP_AUTH_DOMAIN_REALM, "Music Sharing", ++ SOUP_AUTH_DOMAIN_ADD_PATH, "/login", ++ SOUP_AUTH_DOMAIN_ADD_PATH, "/update", ++ SOUP_AUTH_DOMAIN_ADD_PATH, "/databases", ++ SOUP_AUTH_DOMAIN_FILTER, soup_auth_filter, ++ NULL); ++ g_signal_connect (auth_domain, "authenticate", ++ G_CALLBACK (soup_auth_callback), share); ++ soup_server_add_auth_domain (share->priv->server, auth_domain); ++ g_object_unref (auth_domain); + } + +- soup_server_add_handler (share->priv->server, +- NULL, +- NULL, +- (SoupServerCallbackFn)server_cb, +- NULL, +- share); ++ soup_server_add_handler (share->priv->server, "/server-info", ++ (SoupServerCallback)server_info_cb, ++ share, NULL); ++ soup_server_add_handler (share->priv->server, "/content-codes", ++ (SoupServerCallback)content_codes_cb, ++ share, NULL); ++ soup_server_add_handler (share->priv->server, "/login", ++ (SoupServerCallback)login_cb, ++ share, NULL); ++ soup_server_add_handler (share->priv->server, "/logout", ++ (SoupServerCallback)logout_cb, ++ share, NULL); ++ soup_server_add_handler (share->priv->server, "/update", ++ (SoupServerCallback)update_cb, ++ share, NULL); ++ soup_server_add_handler (share->priv->server, "/databases", ++ (SoupServerCallback)databases_cb, ++ share, NULL); ++ + soup_server_run_async (share->priv->server); + + /* using direct since there is no g_uint_hash or g_uint_equal */ +Index: plugins/daap/rb-daap-src.c +=================================================================== +--- plugins/daap/rb-daap-src.c (revision 5543) ++++ plugins/daap/rb-daap-src.c (working copy) +@@ -34,8 +34,7 @@ + #include + #include + +-#include +-#include ++#include + + #include + #include +@@ -432,7 +431,7 @@ + gchar *host; + guint port; + gchar *path; +- GHashTable *header_table; ++ SoupMessageHeaders *header_table; + gchar *request; + gchar *response; + gchar *end_headers; +@@ -441,7 +440,6 @@ + guint http_status; + gchar *http_status_phrase = NULL; + gboolean parse_result; +- char *dup_headers; + + if (src->buffer_base) { + g_free (src->buffer_base); +@@ -536,59 +534,34 @@ + return FALSE; + } + +- /* for compatibility with older versions of libsoup, we may need to retry +- * the soup_headers_parse_response call with slightly different arguments. +- * since this function modifies the string passed in, we need to copy it +- * before the first call. +- * +- * > 2.2.99 wants the full response header, including the trailing blank line, +- * with the length passed in up to the start of the start of the trailing +- * blank line. +- */ +- dup_headers = g_strndup (response, (end_headers + 4) - response); +- +- header_table = g_hash_table_new (soup_str_case_hash, soup_str_case_equal); +- parse_result = soup_headers_parse_response (dup_headers, ++ header_table = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE); ++ parse_result = soup_headers_parse_response (response, + ((end_headers+2) - response), + header_table, + NULL, + &http_status, + &http_status_phrase); +- g_free (dup_headers); +- if (parse_result == FALSE) { +- /* +- * < 2.2.98 wants the headers terminated before the trailing blank line. +- */ +- end_headers[2] = '\0'; +- parse_result = soup_headers_parse_response (response, +- (end_headers+2 - response), +- header_table, +- NULL, +- &http_status, +- &http_status_phrase); +- } +- + if (parse_result) { + if (http_status == 200 || http_status == 206) { +- GSList *val; ++ const char *val; + +- val = g_hash_table_lookup (header_table, "Transfer-Encoding"); ++ val = soup_message_headers_get (header_table, "Transfer-Encoding"); + if (val) { +- if (g_strcasecmp ((gchar *)val->data, "chunked") == 0) { ++ if (g_strcasecmp (val, "chunked") == 0) { + src->chunked = TRUE; + } else { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), +- ("Unknown HTTP transfer encoding \"%s\"", val->data)); ++ ("Unknown HTTP transfer encoding \"%s\"", val)); + } + } else { + src->chunked = FALSE; +- val = g_hash_table_lookup (header_table, "Content-Length"); ++ val = soup_message_headers_get (header_table, "Content-Length"); + if (val) { + char *e; +- src->size = strtoul ((char *)val->data, &e, 10); +- if (e == val->data) { ++ src->size = strtoul (val, &e, 10); ++ if (e == (char *)val) { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), +- ("Couldn't read HTTP content length \"%s\"", val->data)); ++ ("Couldn't read HTTP content length \"%s\"", val)); + ok = FALSE; + } + } else { +@@ -609,8 +582,7 @@ + ok = FALSE; + } + g_free (http_status_phrase); +- soup_message_clear_headers (header_table); +- g_hash_table_destroy (header_table); ++ soup_message_headers_free (header_table); + + end_headers += 4; +